Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:49

0001 
0002 //              Copyright Catch2 Authors
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //   (See accompanying file LICENSE.txt or copy at
0005 //        https://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // SPDX-License-Identifier: BSL-1.0
0008 #ifndef CATCH_DECOMPOSER_HPP_INCLUDED
0009 #define CATCH_DECOMPOSER_HPP_INCLUDED
0010 
0011 #include <catch2/catch_tostring.hpp>
0012 #include <catch2/internal/catch_stringref.hpp>
0013 #include <catch2/internal/catch_compare_traits.hpp>
0014 #include <catch2/internal/catch_test_failure_exception.hpp>
0015 #include <catch2/internal/catch_logical_traits.hpp>
0016 
0017 #include <type_traits>
0018 #include <iosfwd>
0019 
0020 #ifdef _MSC_VER
0021 #pragma warning(push)
0022 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
0023 #pragma warning(disable:4018) // more "signed/unsigned mismatch"
0024 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
0025 #pragma warning(disable:4180) // qualifier applied to function type has no meaning
0026 #pragma warning(disable:4800) // Forcing result to true or false
0027 #endif
0028 
0029 #ifdef __clang__
0030 #  pragma clang diagnostic push
0031 #  pragma clang diagnostic ignored "-Wsign-compare"
0032 #elif defined __GNUC__
0033 #  pragma GCC diagnostic push
0034 #  pragma GCC diagnostic ignored "-Wsign-compare"
0035 #endif
0036 
0037 namespace Catch {
0038 
0039     template <typename T>
0040     struct always_false : std::false_type {};
0041 
0042     class ITransientExpression {
0043         bool m_isBinaryExpression;
0044         bool m_result;
0045 
0046     public:
0047         auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
0048         auto getResult() const -> bool { return m_result; }
0049         virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
0050 
0051         ITransientExpression( bool isBinaryExpression, bool result )
0052         :   m_isBinaryExpression( isBinaryExpression ),
0053             m_result( result )
0054         {}
0055 
0056         ITransientExpression() = default;
0057         ITransientExpression(ITransientExpression const&) = default;
0058         ITransientExpression& operator=(ITransientExpression const&) = default;
0059 
0060         // We don't actually need a virtual destructor, but many static analysers
0061         // complain if it's not here :-(
0062         virtual ~ITransientExpression(); // = default;
0063 
0064         friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
0065             expr.streamReconstructedExpression(out);
0066             return out;
0067         }
0068     };
0069 
0070     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
0071 
0072     template<typename LhsT, typename RhsT>
0073     class BinaryExpr  : public ITransientExpression {
0074         LhsT m_lhs;
0075         StringRef m_op;
0076         RhsT m_rhs;
0077 
0078         void streamReconstructedExpression( std::ostream &os ) const override {
0079             formatReconstructedExpression
0080                     ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
0081         }
0082 
0083     public:
0084         BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
0085         :   ITransientExpression{ true, comparisonResult },
0086             m_lhs( lhs ),
0087             m_op( op ),
0088             m_rhs( rhs )
0089         {}
0090 
0091         template<typename T>
0092         auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0093             static_assert(always_false<T>::value,
0094             "chained comparisons are not supported inside assertions, "
0095             "wrap the expression inside parentheses, or decompose it");
0096         }
0097 
0098         template<typename T>
0099         auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0100             static_assert(always_false<T>::value,
0101             "chained comparisons are not supported inside assertions, "
0102             "wrap the expression inside parentheses, or decompose it");
0103         }
0104 
0105         template<typename T>
0106         auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0107             static_assert(always_false<T>::value,
0108             "chained comparisons are not supported inside assertions, "
0109             "wrap the expression inside parentheses, or decompose it");
0110         }
0111 
0112         template<typename T>
0113         auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0114             static_assert(always_false<T>::value,
0115             "chained comparisons are not supported inside assertions, "
0116             "wrap the expression inside parentheses, or decompose it");
0117         }
0118 
0119         template<typename T>
0120         auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0121             static_assert(always_false<T>::value,
0122             "chained comparisons are not supported inside assertions, "
0123             "wrap the expression inside parentheses, or decompose it");
0124         }
0125 
0126         template<typename T>
0127         auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0128             static_assert(always_false<T>::value,
0129             "chained comparisons are not supported inside assertions, "
0130             "wrap the expression inside parentheses, or decompose it");
0131         }
0132 
0133         template<typename T>
0134         auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0135             static_assert(always_false<T>::value,
0136             "chained comparisons are not supported inside assertions, "
0137             "wrap the expression inside parentheses, or decompose it");
0138         }
0139 
0140         template<typename T>
0141         auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
0142             static_assert(always_false<T>::value,
0143             "chained comparisons are not supported inside assertions, "
0144             "wrap the expression inside parentheses, or decompose it");
0145         }
0146     };
0147 
0148     template<typename LhsT>
0149     class UnaryExpr : public ITransientExpression {
0150         LhsT m_lhs;
0151 
0152         void streamReconstructedExpression( std::ostream &os ) const override {
0153             os << Catch::Detail::stringify( m_lhs );
0154         }
0155 
0156     public:
0157         explicit UnaryExpr( LhsT lhs )
0158         :   ITransientExpression{ false, static_cast<bool>(lhs) },
0159             m_lhs( lhs )
0160         {}
0161     };
0162 
0163 
0164     template<typename LhsT>
0165     class ExprLhs {
0166         LhsT m_lhs;
0167     public:
0168         explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
0169 
0170 #define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op )           \
0171     template <typename RhsT>                                                   \
0172     friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )                       \
0173         ->std::enable_if_t<                                                    \
0174             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
0175                                 Detail::negation<std::is_arithmetic<           \
0176                                     std::remove_reference_t<RhsT>>>>::value,   \
0177             BinaryExpr<LhsT, RhsT const&>> {                                   \
0178         return {                                                               \
0179             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
0180     }                                                                          \
0181     template <typename RhsT>                                                   \
0182     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \
0183         ->std::enable_if_t<                                                    \
0184             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
0185                                 std::is_arithmetic<RhsT>>::value,              \
0186             BinaryExpr<LhsT, RhsT>> {                                          \
0187         return {                                                               \
0188             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
0189     }                                                                          \
0190     template <typename RhsT>                                                   \
0191     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \
0192         ->std::enable_if_t<                                                    \
0193             Detail::conjunction<                                               \
0194                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
0195                 Detail::is_eq_0_comparable<LhsT>,                              \
0196               /* We allow long because we want `ptr op NULL` to be accepted */ \
0197                 Detail::disjunction<std::is_same<RhsT, int>,                   \
0198                                     std::is_same<RhsT, long>>>::value,         \
0199             BinaryExpr<LhsT, RhsT>> {                                          \
0200         if ( rhs != 0 ) { throw_test_failure_exception(); }                    \
0201         return {                                                               \
0202             static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \
0203     }                                                                          \
0204     template <typename RhsT>                                                   \
0205     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \
0206         ->std::enable_if_t<                                                    \
0207             Detail::conjunction<                                               \
0208                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
0209                 Detail::is_eq_0_comparable<RhsT>,                              \
0210               /* We allow long because we want `ptr op NULL` to be accepted */ \
0211                 Detail::disjunction<std::is_same<LhsT, int>,                   \
0212                                     std::is_same<LhsT, long>>>::value,         \
0213             BinaryExpr<LhsT, RhsT>> {                                          \
0214         if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); }              \
0215         return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs };    \
0216     }
0217 
0218         CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
0219         CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != )
0220 
0221     #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
0222 
0223 #define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op )         \
0224     template <typename RhsT>                                                   \
0225     friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )                       \
0226         ->std::enable_if_t<                                                    \
0227             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
0228                                 Detail::negation<std::is_arithmetic<           \
0229                                     std::remove_reference_t<RhsT>>>>::value,   \
0230             BinaryExpr<LhsT, RhsT const&>> {                                   \
0231         return {                                                               \
0232             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
0233     }                                                                          \
0234     template <typename RhsT>                                                   \
0235     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \
0236         ->std::enable_if_t<                                                    \
0237             Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
0238                                 std::is_arithmetic<RhsT>>::value,              \
0239             BinaryExpr<LhsT, RhsT>> {                                          \
0240         return {                                                               \
0241             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
0242     }                                                                          \
0243     template <typename RhsT>                                                   \
0244     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \
0245         ->std::enable_if_t<                                                    \
0246             Detail::conjunction<                                               \
0247                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
0248                 Detail::is_##id##_0_comparable<LhsT>,                          \
0249                 std::is_same<RhsT, int>>::value,                               \
0250             BinaryExpr<LhsT, RhsT>> {                                          \
0251         if ( rhs != 0 ) { throw_test_failure_exception(); }                    \
0252         return {                                                               \
0253             static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \
0254     }                                                                          \
0255     template <typename RhsT>                                                   \
0256     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \
0257         ->std::enable_if_t<                                                    \
0258             Detail::conjunction<                                               \
0259                 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
0260                 Detail::is_##id##_0_comparable<RhsT>,                          \
0261                 std::is_same<LhsT, int>>::value,                               \
0262             BinaryExpr<LhsT, RhsT>> {                                          \
0263         if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); }              \
0264         return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs };    \
0265     }
0266 
0267         CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < )
0268         CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= )
0269         CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > )
0270         CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= )
0271 
0272     #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR
0273 
0274 
0275 #define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op )                        \
0276     template <typename RhsT>                                                   \
0277     friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )                       \
0278         ->std::enable_if_t<                                                    \
0279             !std::is_arithmetic<std::remove_reference_t<RhsT>>::value,         \
0280             BinaryExpr<LhsT, RhsT const&>> {                                   \
0281         return {                                                               \
0282             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
0283     }                                                                          \
0284     template <typename RhsT>                                                   \
0285     friend auto operator op( ExprLhs&& lhs, RhsT rhs )                         \
0286         ->std::enable_if_t<std::is_arithmetic<RhsT>::value,                    \
0287                            BinaryExpr<LhsT, RhsT>> {                           \
0288         return {                                                               \
0289             static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
0290     }
0291 
0292         CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|)
0293         CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&)
0294         CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^)
0295 
0296     #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR
0297 
0298         template<typename RhsT>
0299         friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
0300             static_assert(always_false<RhsT>::value,
0301             "operator&& is not supported inside assertions, "
0302             "wrap the expression inside parentheses, or decompose it");
0303         }
0304 
0305         template<typename RhsT>
0306         friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
0307             static_assert(always_false<RhsT>::value,
0308             "operator|| is not supported inside assertions, "
0309             "wrap the expression inside parentheses, or decompose it");
0310         }
0311 
0312         auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
0313             return UnaryExpr<LhsT>{ m_lhs };
0314         }
0315     };
0316 
0317     struct Decomposer {
0318         template<typename T, std::enable_if_t<!std::is_arithmetic<std::remove_reference_t<T>>::value, int> = 0>
0319         friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
0320             return ExprLhs<const T&>{ lhs };
0321         }
0322 
0323         template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
0324         friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
0325             return ExprLhs<T>{ value };
0326         }
0327     };
0328 
0329 } // end namespace Catch
0330 
0331 #ifdef _MSC_VER
0332 #pragma warning(pop)
0333 #endif
0334 #ifdef __clang__
0335 #  pragma clang diagnostic pop
0336 #elif defined __GNUC__
0337 #  pragma GCC diagnostic pop
0338 #endif
0339 
0340 #endif // CATCH_DECOMPOSER_HPP_INCLUDED