mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	v3.5.3
This commit is contained in:
		| @@ -6,8 +6,8 @@ | ||||
|  | ||||
| // SPDX-License-Identifier: BSL-1.0 | ||||
|  | ||||
| //  Catch v3.5.2 | ||||
| //  Generated: 2024-01-15 14:06:36.675713 | ||||
| //  Catch v3.5.3 | ||||
| //  Generated: 2024-03-01 22:05:56.038084 | ||||
| //  ---------------------------------------------------------- | ||||
| //  This file is an amalgamation of multiple different files. | ||||
| //  You probably shouldn't edit it directly. | ||||
| @@ -101,8 +101,8 @@ namespace Catch { | ||||
|                     FDuration mean = FDuration(0); | ||||
|                     int i = 0; | ||||
|                     for (auto it = first; it < last; ++it, ++i) { | ||||
|                         samples.push_back(FDuration(*it)); | ||||
|                         mean += FDuration(*it); | ||||
|                         samples.push_back(*it); | ||||
|                         mean += *it; | ||||
|                     } | ||||
|                     mean /= i; | ||||
|  | ||||
| @@ -558,7 +558,7 @@ bool marginComparison(double lhs, double rhs, double margin) { | ||||
| namespace Catch { | ||||
|  | ||||
|     Approx::Approx ( double value ) | ||||
|     :   m_epsilon( std::numeric_limits<float>::epsilon()*100. ), | ||||
|     :   m_epsilon( static_cast<double>(std::numeric_limits<float>::epsilon())*100. ), | ||||
|         m_margin( 0.0 ), | ||||
|         m_scale( 0.0 ), | ||||
|         m_value( value ) | ||||
| @@ -1038,6 +1038,7 @@ namespace Catch { | ||||
|                     m_messages.back().message += " := "; | ||||
|                     start = pos; | ||||
|                 } | ||||
|             default:; // noop | ||||
|             } | ||||
|         } | ||||
|         assert(openings.empty() && "Mismatched openings"); | ||||
| @@ -1581,8 +1582,10 @@ namespace Catch { | ||||
|             while (lastDot > 0 && filename[lastDot - 1] != '.') { | ||||
|                 --lastDot; | ||||
|             } | ||||
|             --lastDot; | ||||
|             // In theory we could have filename without any extension in it | ||||
|             if ( lastDot == 0 ) { return StringRef(); } | ||||
|  | ||||
|             --lastDot; | ||||
|             size_t nameStart = lastDot; | ||||
|             while (nameStart > 0 && filename[nameStart - 1] != '/' && filename[nameStart - 1] != '\\') { | ||||
|                 --nameStart; | ||||
| @@ -1966,13 +1969,13 @@ namespace Detail { | ||||
|         } | ||||
|     } // end unnamed namespace | ||||
|  | ||||
|     std::string convertIntoString(StringRef string, bool escape_invisibles) { | ||||
|     std::string convertIntoString(StringRef string, bool escapeInvisibles) { | ||||
|         std::string ret; | ||||
|         // This is enough for the "don't escape invisibles" case, and a good | ||||
|         // lower bound on the "escape invisibles" case. | ||||
|         ret.reserve(string.size() + 2); | ||||
|  | ||||
|         if (!escape_invisibles) { | ||||
|         if (!escapeInvisibles) { | ||||
|             ret += '"'; | ||||
|             ret += string; | ||||
|             ret += '"'; | ||||
| @@ -2050,7 +2053,7 @@ std::string StringMaker<char const*>::convert(char const* str) { | ||||
|         return{ "{null string}" }; | ||||
|     } | ||||
| } | ||||
| std::string StringMaker<char*>::convert(char* str) { | ||||
| std::string StringMaker<char*>::convert(char* str) { // NOLINT(readability-non-const-parameter) | ||||
|     if (str) { | ||||
|         return Detail::convertIntoString( str ); | ||||
|     } else { | ||||
| @@ -2147,8 +2150,8 @@ std::string StringMaker<signed char>::convert(signed char value) { | ||||
| std::string StringMaker<char>::convert(char c) { | ||||
|     return ::Catch::Detail::stringify(static_cast<signed char>(c)); | ||||
| } | ||||
| std::string StringMaker<unsigned char>::convert(unsigned char c) { | ||||
|     return ::Catch::Detail::stringify(static_cast<char>(c)); | ||||
| std::string StringMaker<unsigned char>::convert(unsigned char value) { | ||||
|     return ::Catch::Detail::stringify(static_cast<char>(value)); | ||||
| } | ||||
|  | ||||
| int StringMaker<float>::precision = 5; | ||||
| @@ -2268,7 +2271,7 @@ namespace Catch { | ||||
|     } | ||||
|  | ||||
|     Version const& libraryVersion() { | ||||
|         static Version version( 3, 5, 2, "", 0 ); | ||||
|         static Version version( 3, 5, 3, "", 0 ); | ||||
|         return version; | ||||
|     } | ||||
|  | ||||
| @@ -3092,7 +3095,7 @@ namespace Catch { | ||||
|                     line = trim(line); | ||||
|                     if( !line.empty() && !startsWith( line, '#' ) ) { | ||||
|                         if( !startsWith( line, '"' ) ) | ||||
|                             line = '"' + line + '"'; | ||||
|                             line = '"' + CATCH_MOVE(line) + '"'; | ||||
|                         config.testsOrTags.push_back( line ); | ||||
|                         config.testsOrTags.emplace_back( "," ); | ||||
|                     } | ||||
| @@ -3573,21 +3576,21 @@ namespace { | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode implSelection, | ||||
|     Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection, | ||||
|                                                    IStream* stream ) { | ||||
| #if defined( CATCH_CONFIG_COLOUR_WIN32 ) | ||||
|         if ( implSelection == ColourMode::Win32 ) { | ||||
|         if ( colourSelection == ColourMode::Win32 ) { | ||||
|             return Detail::make_unique<Win32ColourImpl>( stream ); | ||||
|         } | ||||
| #endif | ||||
|         if ( implSelection == ColourMode::ANSI ) { | ||||
|         if ( colourSelection == ColourMode::ANSI ) { | ||||
|             return Detail::make_unique<ANSIColourImpl>( stream ); | ||||
|         } | ||||
|         if ( implSelection == ColourMode::None ) { | ||||
|         if ( colourSelection == ColourMode::None ) { | ||||
|             return Detail::make_unique<NoColourImpl>( stream ); | ||||
|         } | ||||
|  | ||||
|         if ( implSelection == ColourMode::PlatformDefault) { | ||||
|         if ( colourSelection == ColourMode::PlatformDefault) { | ||||
| #if defined( CATCH_CONFIG_COLOUR_WIN32 ) | ||||
|             if ( Win32ColourImpl::useImplementationForStream( *stream ) ) { | ||||
|                 return Detail::make_unique<Win32ColourImpl>( stream ); | ||||
| @@ -3599,7 +3602,7 @@ namespace Catch { | ||||
|             return Detail::make_unique<NoColourImpl>( stream ); | ||||
|         } | ||||
|  | ||||
|         CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(implSelection) ); | ||||
|         CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(colourSelection) ); | ||||
|     } | ||||
|  | ||||
|     bool isColourImplAvailable( ColourMode colourSelection ) { | ||||
| @@ -3807,7 +3810,12 @@ namespace Catch { | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     ITransientExpression::~ITransientExpression() = default; | ||||
|     void ITransientExpression::streamReconstructedExpression( | ||||
|         std::ostream& os ) const { | ||||
|         // We can't make this function pure virtual to keep ITransientExpression | ||||
|         // constexpr, so we write error message instead | ||||
|         os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression"; | ||||
|     } | ||||
|  | ||||
|     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { | ||||
|         if( lhs.size() + rhs.size() < 40 && | ||||
| @@ -4473,7 +4481,7 @@ namespace Catch { | ||||
|         m_os{ os }, m_indent_level{ indent_level } { | ||||
|         m_os << '{'; | ||||
|     } | ||||
|     JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ): | ||||
|     JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ) noexcept: | ||||
|         m_os{ source.m_os }, | ||||
|         m_indent_level{ source.m_indent_level }, | ||||
|         m_should_comma{ source.m_should_comma }, | ||||
| @@ -4504,7 +4512,7 @@ namespace Catch { | ||||
|         m_os{ os }, m_indent_level{ indent_level } { | ||||
|         m_os << '['; | ||||
|     } | ||||
|     JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ): | ||||
|     JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ) noexcept: | ||||
|         m_os{ source.m_os }, | ||||
|         m_indent_level{ source.m_indent_level }, | ||||
|         m_should_comma{ source.m_should_comma }, | ||||
| @@ -5283,7 +5291,7 @@ namespace Catch { | ||||
|             auto kv = splitKVPair( parts[i] ); | ||||
|             auto key = kv.key, value = kv.value; | ||||
|  | ||||
|             if ( key.empty() || value.empty() ) { | ||||
|             if ( key.empty() || value.empty() ) { // NOLINT(bugprone-branch-clone) | ||||
|                 return {}; | ||||
|             } else if ( key[0] == 'X' ) { | ||||
|                 // This is a reporter-specific option, we don't check these | ||||
| @@ -6297,17 +6305,29 @@ namespace Catch { | ||||
|     } | ||||
|  | ||||
|     bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { | ||||
|         bool replaced = false; | ||||
|         std::size_t i = str.find( replaceThis ); | ||||
|         while( i != std::string::npos ) { | ||||
|             replaced = true; | ||||
|             str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); | ||||
|             if( i < str.size()-withThis.size() ) | ||||
|                 i = str.find( replaceThis, i+withThis.size() ); | ||||
|         if (i == std::string::npos) { | ||||
|             return false; | ||||
|         } | ||||
|         std::size_t copyBegin = 0; | ||||
|         std::string origStr = CATCH_MOVE(str); | ||||
|         str.clear(); | ||||
|         // There is at least one replacement, so reserve with the best guess | ||||
|         // we can make without actually counting the number of occurences. | ||||
|         str.reserve(origStr.size() - replaceThis.size() + withThis.size()); | ||||
|         do { | ||||
|             str.append(origStr, copyBegin, i-copyBegin ); | ||||
|             str += withThis; | ||||
|             copyBegin = i + replaceThis.size(); | ||||
|             if( copyBegin < origStr.size() ) | ||||
|                 i = origStr.find( replaceThis, copyBegin ); | ||||
|             else | ||||
|                 i = std::string::npos; | ||||
|         } while( i != std::string::npos ); | ||||
|         if ( copyBegin < origStr.size() ) { | ||||
|             str.append(origStr, copyBegin, origStr.size() ); | ||||
|         } | ||||
|         return replaced; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) { | ||||
| @@ -9099,8 +9119,8 @@ void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { | ||||
|     m_stream << '\n' << std::flush; | ||||
|     StreamingReporterBase::testRunEnded(_testRunStats); | ||||
| } | ||||
| void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) { | ||||
|     StreamingReporterBase::testRunStarting(_testInfo); | ||||
| void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) { | ||||
|     StreamingReporterBase::testRunStarting(_testRunInfo); | ||||
|     if ( m_config->testSpec().hasFilters() ) { | ||||
|         m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: " | ||||
|                  << m_config->testSpec() << '\n'; | ||||
| @@ -9253,8 +9273,7 @@ namespace Catch { | ||||
|     namespace { | ||||
|         struct BySectionInfo { | ||||
|             BySectionInfo( SectionInfo const& other ): m_other( other ) {} | ||||
|             BySectionInfo( BySectionInfo const& other ): | ||||
|                 m_other( other.m_other ) {} | ||||
|             BySectionInfo( BySectionInfo const& other ) = default; | ||||
|             bool operator()( | ||||
|                 Detail::unique_ptr<CumulativeReporterBase::SectionNode> const& | ||||
|                     node ) const { | ||||
| @@ -9879,8 +9898,8 @@ namespace Catch { | ||||
|         return "Outputs listings as JSON. Test listing is Work-in-Progress!"; | ||||
|     } | ||||
|  | ||||
|     void JsonReporter::testRunStarting( TestRunInfo const& testInfo ) { | ||||
|         StreamingReporterBase::testRunStarting( testInfo ); | ||||
|     void JsonReporter::testRunStarting( TestRunInfo const& runInfo ) { | ||||
|         StreamingReporterBase::testRunStarting( runInfo ); | ||||
|         endListing(); | ||||
|  | ||||
|         assert( isInside( Writer::Object ) ); | ||||
| @@ -10178,7 +10197,7 @@ namespace Catch { | ||||
|  | ||||
|         static void normalizeNamespaceMarkers(std::string& str) { | ||||
|             std::size_t pos = str.find( "::" ); | ||||
|             while ( pos != str.npos ) { | ||||
|             while ( pos != std::string::npos ) { | ||||
|                 str.replace( pos, 2, "." ); | ||||
|                 pos += 1; | ||||
|                 pos = str.find( "::", pos ); | ||||
|   | ||||
| @@ -6,8 +6,8 @@ | ||||
|  | ||||
| // SPDX-License-Identifier: BSL-1.0 | ||||
|  | ||||
| //  Catch v3.5.2 | ||||
| //  Generated: 2024-01-15 14:06:34.036475 | ||||
| //  Catch v3.5.3 | ||||
| //  Generated: 2024-03-01 22:05:55.031514 | ||||
| //  ---------------------------------------------------------- | ||||
| //  This file is an amalgamation of multiple different files. | ||||
| //  You probably shouldn't edit it directly. | ||||
| @@ -114,14 +114,14 @@ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|  | ||||
| #  if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) | ||||
| #    define CATCH_CPP14_OR_GREATER | ||||
| #  endif | ||||
|  | ||||
| #  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) | ||||
| #    define CATCH_CPP17_OR_GREATER | ||||
| #  endif | ||||
|  | ||||
| #  if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) | ||||
| #    define CATCH_CPP20_OR_GREATER | ||||
| #  endif | ||||
|  | ||||
| #endif | ||||
|  | ||||
| // Only GCC compiler should be used in this block, so other compilers trying to | ||||
| @@ -762,8 +762,8 @@ namespace Catch { | ||||
|         constexpr const_iterator end() const { return m_start + m_size; } | ||||
|  | ||||
|  | ||||
|         friend std::string& operator += (std::string& lhs, StringRef sr); | ||||
|         friend std::ostream& operator << (std::ostream& os, StringRef sr); | ||||
|         friend std::string& operator += (std::string& lhs, StringRef rhs); | ||||
|         friend std::ostream& operator << (std::ostream& os, StringRef str); | ||||
|         friend std::string operator+(StringRef lhs, StringRef rhs); | ||||
|  | ||||
|         /** | ||||
| @@ -2696,11 +2696,11 @@ namespace Catch { | ||||
|     }; | ||||
|     template<> | ||||
|     struct StringMaker<signed char> { | ||||
|         static std::string convert(signed char c); | ||||
|         static std::string convert(signed char value); | ||||
|     }; | ||||
|     template<> | ||||
|     struct StringMaker<unsigned char> { | ||||
|         static std::string convert(unsigned char c); | ||||
|         static std::string convert(unsigned char value); | ||||
|     }; | ||||
|  | ||||
|     template<> | ||||
| @@ -5147,6 +5147,86 @@ namespace Detail { | ||||
| #include <type_traits> | ||||
| #include <iosfwd> | ||||
|  | ||||
| /** \file | ||||
|  * Why does decomposing look the way it does: | ||||
|  * | ||||
|  * Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into | ||||
|  * `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first, | ||||
|  * and our custom operator is used for `a == b`, because `a` is transformed | ||||
|  * into `ExprLhs<T&>` and then into `BinaryExpr<T&, U&>`. | ||||
|  * | ||||
|  * In practice, decomposing ends up a mess, because we have to support | ||||
|  * various fun things. | ||||
|  * | ||||
|  * 1) Types that are only comparable with literal 0, and they do this by | ||||
|  *    comparing against a magic type with pointer constructor and deleted | ||||
|  *    other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++ | ||||
|  * | ||||
|  * 2) Types that are only comparable with literal 0, and they do this by | ||||
|  *    comparing against a magic type with consteval integer constructor. | ||||
|  *    Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL. | ||||
|  * | ||||
|  * 3) Types that have no linkage, and so we cannot form a reference to | ||||
|  *    them. Example: some implementations of traits. | ||||
|  * | ||||
|  * 4) Starting with C++20, when the compiler sees `a == b`, it also uses | ||||
|  *    `b == a` when constructing the overload set. For us this means that | ||||
|  *    when the compiler handles `ExprLhs<T> == b`, it also tries to resolve | ||||
|  *    the overload set for `b == ExprLhs<T>`. | ||||
|  * | ||||
|  * To accomodate these use cases, decomposer ended up rather complex. | ||||
|  * | ||||
|  * 1) These types are handled by adding SFINAE overloads to our comparison | ||||
|  *    operators, checking whether `T == U` are comparable with the given | ||||
|  *    operator, and if not, whether T (or U) are comparable with literal 0. | ||||
|  *    If yes, the overload compares T (or U) with 0 literal inline in the | ||||
|  *    definition. | ||||
|  * | ||||
|  *    Note that for extra correctness, we check  that the other type is | ||||
|  *    either an `int` (literal 0 is captured as `int` by templates), or | ||||
|  *    a `long` (some platforms use 0L for `NULL` and we want to support | ||||
|  *    that for pointer comparisons). | ||||
|  * | ||||
|  * 2) For these types, `is_foo_comparable<T, int>` is true, but letting | ||||
|  *    them fall into the overload that actually does `T == int` causes | ||||
|  *    compilation error. Handling them requires that the decomposition | ||||
|  *    is `constexpr`, so that P2564R3 applies and the `consteval` from | ||||
|  *    their accompanying magic type is propagated through the `constexpr` | ||||
|  *    call stack. | ||||
|  * | ||||
|  *    However this is not enough to handle these types automatically, | ||||
|  *    because our default is to capture types by reference, to avoid | ||||
|  *    runtime copies. While these references cannot become dangling, | ||||
|  *    they outlive the constexpr context and thus the default capture | ||||
|  *    path cannot be actually constexpr. | ||||
|  * | ||||
|  *    The solution is to capture these types by value, by explicitly | ||||
|  *    specializing `Catch::capture_by_value` for them. Catch2 provides | ||||
|  *    specialization for `std::foo_ordering`s, but users can specialize | ||||
|  *    the trait for their own types as well. | ||||
|  * | ||||
|  * 3) If a type has no linkage, we also cannot capture it by reference. | ||||
|  *    The solution is once again to capture them by value. We handle | ||||
|  *    the common cases by using `std::is_arithmetic` as the default | ||||
|  *    for `Catch::capture_by_value`, but that is only a some-effort | ||||
|  *    heuristic. But as with 2), users can specialize `capture_by_value` | ||||
|  *    for their own types as needed. | ||||
|  * | ||||
|  * 4) To support C++20 and make the SFINAE on our decomposing operators | ||||
|  *    work, the SFINAE has to happen in return type, rather than in | ||||
|  *    a template type. This is due to our use of logical type traits | ||||
|  *    (`conjunction`/`disjunction`/`negation`), that we use to workaround | ||||
|  *    an issue in older (9-) versions of GCC. I still blame C++20 for | ||||
|  *    this, because without the comparison order switching, the logical | ||||
|  *    traits could still be used in template type. | ||||
|  * | ||||
|  * There are also other side concerns, e.g. supporting both `REQUIRE(a)` | ||||
|  * and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot | ||||
|  * nicely into the same expression handling logic, but these are rather | ||||
|  * straightforward and add only a bit of complexity (e.g. common base | ||||
|  * class for decomposed expressions). | ||||
|  */ | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #pragma warning(push) | ||||
| #pragma warning(disable:4389) // '==' : signed/unsigned mismatch | ||||
| @@ -5164,8 +5244,33 @@ namespace Detail { | ||||
| #  pragma GCC diagnostic ignored "-Wsign-compare" | ||||
| #endif | ||||
|  | ||||
| #if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>) | ||||
| #  include <compare> | ||||
| #    if defined( __cpp_lib_three_way_comparison ) && \ | ||||
|             __cpp_lib_three_way_comparison >= 201907L | ||||
| #      define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS | ||||
| #    endif | ||||
| #endif | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     // Note: There is nothing that stops us from extending this, | ||||
|     //       e.g. to `std::is_scalar`, but the more encompassing | ||||
|     //       traits are usually also more expensive. For now we | ||||
|     //       keep this as it used to be and it can be changed later. | ||||
|     template <typename T> | ||||
|     struct capture_by_value | ||||
|         : std::integral_constant<bool, std::is_arithmetic<T>{}> {}; | ||||
|  | ||||
| #if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS ) | ||||
|     template <> | ||||
|     struct capture_by_value<std::strong_ordering> : std::true_type {}; | ||||
|     template <> | ||||
|     struct capture_by_value<std::weak_ordering> : std::true_type {}; | ||||
|     template <> | ||||
|     struct capture_by_value<std::partial_ordering> : std::true_type {}; | ||||
| #endif | ||||
|  | ||||
|     template <typename T> | ||||
|     struct always_false : std::false_type {}; | ||||
|  | ||||
| @@ -5174,11 +5279,12 @@ namespace Catch { | ||||
|         bool m_result; | ||||
|  | ||||
|     public: | ||||
|         auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } | ||||
|         auto getResult() const -> bool { return m_result; } | ||||
|         virtual void streamReconstructedExpression( std::ostream &os ) const = 0; | ||||
|         constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } | ||||
|         constexpr auto getResult() const -> bool { return m_result; } | ||||
|         //! This function **has** to be overriden by the derived class. | ||||
|         virtual void streamReconstructedExpression( std::ostream& os ) const; | ||||
|  | ||||
|         ITransientExpression( bool isBinaryExpression, bool result ) | ||||
|         constexpr ITransientExpression( bool isBinaryExpression, bool result ) | ||||
|         :   m_isBinaryExpression( isBinaryExpression ), | ||||
|             m_result( result ) | ||||
|         {} | ||||
| @@ -5189,7 +5295,7 @@ namespace Catch { | ||||
|  | ||||
|         // We don't actually need a virtual destructor, but many static analysers | ||||
|         // complain if it's not here :-( | ||||
|         virtual ~ITransientExpression(); // = default; | ||||
|         virtual ~ITransientExpression() = default; | ||||
|  | ||||
|         friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) { | ||||
|             expr.streamReconstructedExpression(out); | ||||
| @@ -5211,7 +5317,7 @@ namespace Catch { | ||||
|         } | ||||
|  | ||||
|     public: | ||||
|         BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) | ||||
|         constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) | ||||
|         :   ITransientExpression{ true, comparisonResult }, | ||||
|             m_lhs( lhs ), | ||||
|             m_op( op ), | ||||
| @@ -5284,7 +5390,7 @@ namespace Catch { | ||||
|         } | ||||
|  | ||||
|     public: | ||||
|         explicit UnaryExpr( LhsT lhs ) | ||||
|         explicit constexpr UnaryExpr( LhsT lhs ) | ||||
|         :   ITransientExpression{ false, static_cast<bool>(lhs) }, | ||||
|             m_lhs( lhs ) | ||||
|         {} | ||||
| @@ -5295,30 +5401,30 @@ namespace Catch { | ||||
|     class ExprLhs { | ||||
|         LhsT m_lhs; | ||||
|     public: | ||||
|         explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} | ||||
|         explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} | ||||
|  | ||||
| #define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op )           \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )                       \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \ | ||||
|                                 Detail::negation<std::is_arithmetic<           \ | ||||
|                                 Detail::negation<capture_by_value<             \ | ||||
|                                     std::remove_reference_t<RhsT>>>>::value,   \ | ||||
|             BinaryExpr<LhsT, RhsT const&>> {                                   \ | ||||
|         return {                                                               \ | ||||
|             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ | ||||
|     }                                                                          \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \ | ||||
|                                 std::is_arithmetic<RhsT>>::value,              \ | ||||
|                                 capture_by_value<RhsT>>::value,                \ | ||||
|             BinaryExpr<LhsT, RhsT>> {                                          \ | ||||
|         return {                                                               \ | ||||
|             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ | ||||
|     }                                                                          \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<                                               \ | ||||
|                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \ | ||||
| @@ -5332,7 +5438,7 @@ namespace Catch { | ||||
|             static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \ | ||||
|     }                                                                          \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<                                               \ | ||||
|                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \ | ||||
| @@ -5350,28 +5456,29 @@ namespace Catch { | ||||
|  | ||||
|     #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR | ||||
|  | ||||
|  | ||||
| #define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op )         \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )                       \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \ | ||||
|                                 Detail::negation<std::is_arithmetic<           \ | ||||
|                                 Detail::negation<capture_by_value<             \ | ||||
|                                     std::remove_reference_t<RhsT>>>>::value,   \ | ||||
|             BinaryExpr<LhsT, RhsT const&>> {                                   \ | ||||
|         return {                                                               \ | ||||
|             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ | ||||
|     }                                                                          \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \ | ||||
|                                 std::is_arithmetic<RhsT>>::value,              \ | ||||
|                                 capture_by_value<RhsT>>::value,                \ | ||||
|             BinaryExpr<LhsT, RhsT>> {                                          \ | ||||
|         return {                                                               \ | ||||
|             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ | ||||
|     }                                                                          \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<                                               \ | ||||
|                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \ | ||||
| @@ -5383,7 +5490,7 @@ namespace Catch { | ||||
|             static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \ | ||||
|     }                                                                          \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             Detail::conjunction<                                               \ | ||||
|                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \ | ||||
| @@ -5404,16 +5511,16 @@ namespace Catch { | ||||
|  | ||||
| #define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op )                        \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )                       \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \ | ||||
|         ->std::enable_if_t<                                                    \ | ||||
|             !std::is_arithmetic<std::remove_reference_t<RhsT>>::value,         \ | ||||
|             !capture_by_value<std::remove_reference_t<RhsT>>::value,           \ | ||||
|             BinaryExpr<LhsT, RhsT const&>> {                                   \ | ||||
|         return {                                                               \ | ||||
|             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ | ||||
|     }                                                                          \ | ||||
|     template <typename RhsT>                                                   \ | ||||
|     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \ | ||||
|         ->std::enable_if_t<std::is_arithmetic<RhsT>::value,                    \ | ||||
|     constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \ | ||||
|         ->std::enable_if_t<capture_by_value<RhsT>::value,                      \ | ||||
|                            BinaryExpr<LhsT, RhsT>> {                           \ | ||||
|         return {                                                               \ | ||||
|             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ | ||||
| @@ -5439,19 +5546,23 @@ namespace Catch { | ||||
|             "wrap the expression inside parentheses, or decompose it"); | ||||
|         } | ||||
|  | ||||
|         auto makeUnaryExpr() const -> UnaryExpr<LhsT> { | ||||
|         constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> { | ||||
|             return UnaryExpr<LhsT>{ m_lhs }; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     struct Decomposer { | ||||
|         template<typename T, std::enable_if_t<!std::is_arithmetic<std::remove_reference_t<T>>::value, int> = 0> | ||||
|         friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> { | ||||
|         template <typename T, | ||||
|                   std::enable_if_t< | ||||
|                       !capture_by_value<std::remove_reference_t<T>>::value, | ||||
|                       int> = 0> | ||||
|         constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> { | ||||
|             return ExprLhs<const T&>{ lhs }; | ||||
|         } | ||||
|  | ||||
|         template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0> | ||||
|         friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> { | ||||
|         template <typename T, | ||||
|                   std::enable_if_t<capture_by_value<T>::value, int> = 0> | ||||
|         constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> { | ||||
|             return ExprLhs<T>{ value }; | ||||
|         } | ||||
|     }; | ||||
| @@ -5571,7 +5682,7 @@ namespace Catch { | ||||
|         INTERNAL_CATCH_TRY { \ | ||||
|             CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ | ||||
|             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ | ||||
|             catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ | ||||
|             catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \ | ||||
|             CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ | ||||
|         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ | ||||
|         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||
| @@ -5786,7 +5897,9 @@ namespace Catch { | ||||
|     namespace Detail { | ||||
|         // Intentionally without linkage, as it should only be used as a dummy | ||||
|         // symbol for static analysis. | ||||
|         int GetNewSectionHint(); | ||||
|         // The arguments are used as a dummy for checking warnings in the passed | ||||
|         // expressions. | ||||
|         int GetNewSectionHint( StringRef, const char* const = nullptr ); | ||||
|     } // namespace Detail | ||||
| } // namespace Catch | ||||
|  | ||||
| @@ -5797,7 +5910,8 @@ namespace Catch { | ||||
|         CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \ | ||||
|         if ( [[maybe_unused]] const int catchInternalPreviousSectionHint =  \ | ||||
|                  catchInternalSectionHint,                                  \ | ||||
|              catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ | ||||
|              catchInternalSectionHint =                                     \ | ||||
|                  Catch::Detail::GetNewSectionHint(__VA_ARGS__);             \ | ||||
|              catchInternalPreviousSectionHint == __LINE__ )                 \ | ||||
|         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
|  | ||||
| @@ -5807,7 +5921,8 @@ namespace Catch { | ||||
|         CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \ | ||||
|         if ( [[maybe_unused]] const int catchInternalPreviousSectionHint =  \ | ||||
|                  catchInternalSectionHint,                                  \ | ||||
|              catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ | ||||
|              catchInternalSectionHint = Catch::Detail::GetNewSectionHint(   \ | ||||
|                 ( Catch::ReusableStringStream() << __VA_ARGS__ ).str());    \ | ||||
|              catchInternalPreviousSectionHint == __LINE__ )                 \ | ||||
|         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
|  | ||||
| @@ -5929,7 +6044,7 @@ struct AutoReg : Detail::NonCopyable { | ||||
| namespace Catch { | ||||
|     namespace Detail { | ||||
|         struct DummyUse { | ||||
|             DummyUse( void ( * )( int ) ); | ||||
|             DummyUse( void ( * )( int ), Catch::NameAndTags const& ); | ||||
|         }; | ||||
|     } // namespace Detail | ||||
| } // namespace Catch | ||||
| @@ -5941,18 +6056,18 @@ namespace Catch { | ||||
| // tests can compile. The redefined `TEST_CASE` shadows this with param. | ||||
| static int catchInternalSectionHint = 0; | ||||
|  | ||||
| #    define INTERNAL_CATCH_TESTCASE2( fname )                              \ | ||||
| #    define INTERNAL_CATCH_TESTCASE2( fname, ... )                         \ | ||||
|         static void fname( int );                                          \ | ||||
|         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                          \ | ||||
|         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                           \ | ||||
|         CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                   \ | ||||
|         static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME(   \ | ||||
|             dummyUser )( &(fname) );                                       \ | ||||
|             dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } );    \ | ||||
|         CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                            \ | ||||
|         static void fname( [[maybe_unused]] int catchInternalSectionHint ) \ | ||||
|             CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
| #    define INTERNAL_CATCH_TESTCASE( ... ) \ | ||||
|         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ) ) | ||||
|         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ ) | ||||
|  | ||||
|  | ||||
| #endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | ||||
| @@ -6935,7 +7050,7 @@ namespace Catch { | ||||
|     struct TestCaseInfo : Detail::NonCopyable { | ||||
|  | ||||
|         TestCaseInfo(StringRef _className, | ||||
|                      NameAndTags const& _tags, | ||||
|                      NameAndTags const& _nameAndTags, | ||||
|                      SourceLineInfo const& _lineInfo); | ||||
|  | ||||
|         bool isHidden() const; | ||||
| @@ -7148,7 +7263,7 @@ namespace Catch { | ||||
|  | ||||
| #define CATCH_VERSION_MAJOR 3 | ||||
| #define CATCH_VERSION_MINOR 5 | ||||
| #define CATCH_VERSION_PATCH 2 | ||||
| #define CATCH_VERSION_PATCH 3 | ||||
|  | ||||
| #endif // CATCH_VERSION_MACROS_HPP_INCLUDED | ||||
|  | ||||
| @@ -7847,9 +7962,8 @@ namespace Catch { | ||||
|         struct ExtendedMultResult { | ||||
|             T upper; | ||||
|             T lower; | ||||
|             friend bool operator==( ExtendedMultResult const& lhs, | ||||
|                                     ExtendedMultResult const& rhs ) { | ||||
|                 return lhs.upper == rhs.upper && lhs.lower == rhs.lower; | ||||
|             bool operator==( ExtendedMultResult const& rhs ) const { | ||||
|                 return upper == rhs.upper && lower == rhs.lower; | ||||
|             } | ||||
|         }; | ||||
|  | ||||
| @@ -9322,7 +9436,7 @@ namespace Catch { | ||||
|  | ||||
|             std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos; | ||||
|  | ||||
|             EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override; | ||||
|             EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override; | ||||
|         }; | ||||
|  | ||||
|         std::vector<StringRef> parseEnums( StringRef enums ); | ||||
| @@ -9795,7 +9909,7 @@ namespace Catch { | ||||
|         JsonObjectWriter( std::ostream& os ); | ||||
|         JsonObjectWriter( std::ostream& os, std::uint64_t indent_level ); | ||||
|  | ||||
|         JsonObjectWriter( JsonObjectWriter&& source ); | ||||
|         JsonObjectWriter( JsonObjectWriter&& source ) noexcept; | ||||
|         JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete; | ||||
|  | ||||
|         ~JsonObjectWriter(); | ||||
| @@ -9814,7 +9928,7 @@ namespace Catch { | ||||
|         JsonArrayWriter( std::ostream& os ); | ||||
|         JsonArrayWriter( std::ostream& os, std::uint64_t indent_level ); | ||||
|  | ||||
|         JsonArrayWriter( JsonArrayWriter&& source ); | ||||
|         JsonArrayWriter( JsonArrayWriter&& source ) noexcept; | ||||
|         JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete; | ||||
|  | ||||
|         ~JsonArrayWriter(); | ||||
| @@ -13454,7 +13568,7 @@ namespace Catch { | ||||
|  | ||||
|         void assertionEnded( AssertionStats const& assertionStats ) override; | ||||
|         void sectionEnded( SectionStats const& sectionStats ) override; | ||||
|         void testCasePartialEnded(TestCaseStats const& testInfo, uint64_t partNumber) override; | ||||
|         void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override; | ||||
|         void testCaseEnded( TestCaseStats const& testCaseStats ) override; | ||||
|         void testRunEnded( TestRunStats const& testRunStats ) override; | ||||
|  | ||||
| @@ -13622,7 +13736,7 @@ namespace Catch { | ||||
|             xml.endElement(); | ||||
|         } | ||||
|  | ||||
|         void writeRun( TestRunNode const& groupNode ); | ||||
|         void writeRun( TestRunNode const& runNode ); | ||||
|  | ||||
|         void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes); | ||||
|  | ||||
| @@ -13707,8 +13821,8 @@ namespace Catch { | ||||
|             return "Reports test results as TeamCity service messages"s; | ||||
|         } | ||||
|  | ||||
|         void testRunStarting( TestRunInfo const& groupInfo ) override; | ||||
|         void testRunEnded( TestRunStats const& testGroupStats ) override; | ||||
|         void testRunStarting( TestRunInfo const& runInfo ) override; | ||||
|         void testRunEnded( TestRunStats const& runStats ) override; | ||||
|  | ||||
|  | ||||
|         void assertionEnded(AssertionStats const& assertionStats) override; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský