diff options
| author | Martin Hořeňovský | 2024-03-01 22:07:10 +0100 |
|---|---|---|
| committer | Martin Hořeňovský | 2024-03-01 22:07:10 +0100 |
| commit | 8ac8190e494a381072c89f5e161b92a08d98b37b (patch) | |
| tree | 0ec2f7d6c09f218a65b83dc2cefd7a35d1032c1a /extras/catch_amalgamated.hpp | |
| parent | b20b365fd2e9697c8526d1d54e7bcb4b8af5b5cb (diff) | |
| download | catch3-3.5.3.tar.gz | |
v3.5.3v3.5.3
Diffstat (limited to 'extras/catch_amalgamated.hpp')
| -rw-r--r-- | extras/catch_amalgamated.hpp | 232 |
1 files changed, 173 insertions, 59 deletions
diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp index fdba759a..e5754314 100644 --- a/extras/catch_amalgamated.hpp +++ b/extras/catch_amalgamated.hpp @@ -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; |