File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/libcatch.x/i/catch2/internal/catch_decomposer.hpp
Criterion Covered Total %
statement 28 28 100.0
branch 5 10 50.0
condition n/a
subroutine n/a
pod n/a
total 33 38 86.8


line stmt bran cond sub pod time code
1              
2             // Copyright Catch2 Authors
3             // Distributed under the Boost Software License, Version 1.0.
4             // (See accompanying file LICENSE_1_0.txt or copy at
5             // https://www.boost.org/LICENSE_1_0.txt)
6              
7             // SPDX-License-Identifier: BSL-1.0
8             #ifndef CATCH_DECOMPOSER_HPP_INCLUDED
9             #define CATCH_DECOMPOSER_HPP_INCLUDED
10              
11             #include
12             #include
13             #include
14              
15             #include
16              
17             #ifdef _MSC_VER
18             #pragma warning(push)
19             #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
20             #pragma warning(disable:4018) // more "signed/unsigned mismatch"
21             #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
22             #pragma warning(disable:4180) // qualifier applied to function type has no meaning
23             #pragma warning(disable:4800) // Forcing result to true or false
24             #endif
25              
26             #ifdef __clang__
27             # pragma clang diagnostic push
28             # pragma clang diagnostic ignored "-Wsign-compare"
29             #elif defined __GNUC__
30             # pragma GCC diagnostic push
31             # pragma GCC diagnostic ignored "-Wsign-compare"
32             #endif
33              
34             namespace Catch {
35              
36             struct ITransientExpression {
37             auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
38             auto getResult() const -> bool { return m_result; }
39             virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
40              
41 50           ITransientExpression( bool isBinaryExpression, bool result )
42             : m_isBinaryExpression( isBinaryExpression ),
43 50           m_result( result )
44 50           {}
45              
46             ITransientExpression() = default;
47             ITransientExpression(ITransientExpression const&) = default;
48             ITransientExpression& operator=(ITransientExpression const&) = default;
49              
50             // We don't actually need a virtual destructor, but many static analysers
51             // complain if it's not here :-(
52             virtual ~ITransientExpression(); // = default;
53              
54             bool m_isBinaryExpression;
55             bool m_result;
56             friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
57             expr.streamReconstructedExpression(out);
58             return out;
59             }
60             };
61              
62             void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
63              
64             template
65 6 50         class BinaryExpr : public ITransientExpression {
66             LhsT m_lhs;
67             StringRef m_op;
68             RhsT m_rhs;
69              
70 3           void streamReconstructedExpression( std::ostream &os ) const override {
71 3 50         formatReconstructedExpression
72 6 50         ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
73 3           }
74              
75             public:
76 3           BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
77             : ITransientExpression{ true, comparisonResult },
78             m_lhs( lhs ),
79             m_op( op ),
80 3           m_rhs( rhs )
81 3           {}
82              
83             template
84             auto operator && ( T ) const -> BinaryExpr const {
85             static_assert(always_false::value,
86             "chained comparisons are not supported inside assertions, "
87             "wrap the expression inside parentheses, or decompose it");
88             }
89              
90             template
91             auto operator || ( T ) const -> BinaryExpr const {
92             static_assert(always_false::value,
93             "chained comparisons are not supported inside assertions, "
94             "wrap the expression inside parentheses, or decompose it");
95             }
96              
97             template
98             auto operator == ( T ) const -> BinaryExpr const {
99             static_assert(always_false::value,
100             "chained comparisons are not supported inside assertions, "
101             "wrap the expression inside parentheses, or decompose it");
102             }
103              
104             template
105             auto operator != ( T ) const -> BinaryExpr const {
106             static_assert(always_false::value,
107             "chained comparisons are not supported inside assertions, "
108             "wrap the expression inside parentheses, or decompose it");
109             }
110              
111             template
112             auto operator > ( T ) const -> BinaryExpr const {
113             static_assert(always_false::value,
114             "chained comparisons are not supported inside assertions, "
115             "wrap the expression inside parentheses, or decompose it");
116             }
117              
118             template
119             auto operator < ( T ) const -> BinaryExpr const {
120             static_assert(always_false::value,
121             "chained comparisons are not supported inside assertions, "
122             "wrap the expression inside parentheses, or decompose it");
123             }
124              
125             template
126             auto operator >= ( T ) const -> BinaryExpr const {
127             static_assert(always_false::value,
128             "chained comparisons are not supported inside assertions, "
129             "wrap the expression inside parentheses, or decompose it");
130             }
131              
132             template
133             auto operator <= ( T ) const -> BinaryExpr const {
134             static_assert(always_false::value,
135             "chained comparisons are not supported inside assertions, "
136             "wrap the expression inside parentheses, or decompose it");
137             }
138             };
139              
140             template
141 94 50         class UnaryExpr : public ITransientExpression {
142             LhsT m_lhs;
143              
144 47           void streamReconstructedExpression( std::ostream &os ) const override {
145 47 50         os << Catch::Detail::stringify( m_lhs );
146 47           }
147              
148             public:
149 47           explicit UnaryExpr( LhsT lhs )
150             : ITransientExpression{ false, static_cast(lhs) },
151 47           m_lhs( lhs )
152 47           {}
153             };
154              
155              
156             // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
157             template
158 6           auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast(lhs == rhs); }
159             template
160             auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }
161             template
162             auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }
163             template
164             auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }
165             template
166             auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }
167              
168             template
169             auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast(lhs != rhs); }
170             template
171             auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }
172             template
173             auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }
174             template
175             auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }
176             template
177             auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }
178              
179              
180             template
181             class ExprLhs {
182             LhsT m_lhs;
183             public:
184 50           explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
185              
186             template>::value, int> = 0>
187 3           friend auto operator == ( ExprLhs && lhs, RhsT && rhs ) -> BinaryExpr {
188 3           return { compareEqual( lhs.m_lhs, rhs ), lhs.m_lhs, "=="_sr, rhs };
189             }
190             template::value, int> = 0>
191             friend auto operator == ( ExprLhs && lhs, RhsT rhs ) -> BinaryExpr {
192             return { compareEqual( lhs.m_lhs, rhs ), lhs.m_lhs, "=="_sr, rhs };
193             }
194              
195             template>::value, int> = 0>
196             friend auto operator != ( ExprLhs && lhs, RhsT && rhs ) -> BinaryExpr {
197             return { compareNotEqual( lhs.m_lhs, rhs ), lhs.m_lhs, "!="_sr, rhs };
198             }
199             template::value, int> = 0>
200             friend auto operator != ( ExprLhs && lhs, RhsT rhs ) -> BinaryExpr {
201             return { compareNotEqual( lhs.m_lhs, rhs ), lhs.m_lhs, "!="_sr, rhs };
202             }
203              
204             #define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(op) \
205             template>::value, int> = 0> \
206             friend auto operator op ( ExprLhs && lhs, RhsT && rhs ) -> BinaryExpr { \
207             return { static_cast(lhs.m_lhs op rhs), lhs.m_lhs, #op##_sr, rhs }; \
208             } \
209             template::value, int> = 0> \
210             friend auto operator op ( ExprLhs && lhs, RhsT rhs ) -> BinaryExpr { \
211             return { static_cast(lhs.m_lhs op rhs), lhs.m_lhs, #op##_sr, rhs }; \
212             }
213              
214             CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(<)
215             CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(>)
216             CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(<=)
217             CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(>=)
218             CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|)
219             CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&)
220             CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^)
221              
222             #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR
223              
224             template
225             friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr {
226             static_assert(always_false::value,
227             "operator&& is not supported inside assertions, "
228             "wrap the expression inside parentheses, or decompose it");
229             }
230              
231             template
232             friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr {
233             static_assert(always_false::value,
234             "operator|| is not supported inside assertions, "
235             "wrap the expression inside parentheses, or decompose it");
236             }
237              
238 47           auto makeUnaryExpr() const -> UnaryExpr {
239 47           return UnaryExpr{ m_lhs };
240             }
241             };
242              
243             struct Decomposer {
244             template>::value, int> = 0>
245 3           friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs {
246 3           return ExprLhs{ lhs };
247             }
248              
249             template::value, int> = 0>
250 47           friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs {
251 47           return ExprLhs{ value };
252             }
253             };
254              
255             } // end namespace Catch
256              
257             #ifdef _MSC_VER
258             #pragma warning(pop)
259             #endif
260             #ifdef __clang__
261             # pragma clang diagnostic pop
262             #elif defined __GNUC__
263             # pragma GCC diagnostic pop
264             #endif
265              
266             #endif // CATCH_DECOMPOSER_HPP_INCLUDED