From 3d7aa24e22ef447ecdb09a267027af9900efebd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fahller?= Date: Sun, 9 Apr 2023 08:25:39 +0200 Subject: [PATCH] wildcard matches objects constructible from anything Unfortunately have to silence warnings when matching creating expectations. --- ChangeLog | 5 ++ compilation_errors/value_from_wildcard.cpp | 2 +- include/trompeloeil.hpp | 89 +++++++++++++--------- test/compiling_tests_14.cpp | 24 ++++++ 4 files changed, 82 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 64933f2c..7a08ce5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ + * Fixed issue 293: Wildcard _ could not match types that can be + constructed from any type. This fix unfortunately turns off conversion + warnings for REQUIRE_CALL and friends when building with gcc. Thank + you @TimonNoethlichs for reporting. + * Fixed issue 296: Improved sequence violation message when ALLOW_CALL is involved. Thank you Sigurður Sveinn Halldórsson for reporting. diff --git a/compilation_errors/value_from_wildcard.cpp b/compilation_errors/value_from_wildcard.cpp index ed9dd130..0a8fc9e2 100644 --- a/compilation_errors/value_from_wildcard.cpp +++ b/compilation_errors/value_from_wildcard.cpp @@ -11,7 +11,7 @@ * Project home: https://github.com/rollbear/trompeloeil */ -// exception: clang++-3 +// exception: g++-[678] // pass: value from wildcard #include diff --git a/include/trompeloeil.hpp b/include/trompeloeil.hpp index 148ce328..7448ea11 100644 --- a/include/trompeloeil.hpp +++ b/include/trompeloeil.hpp @@ -1091,38 +1091,39 @@ namespace trompeloeil struct wildcard : public matcher { - template = 50000 - ,detail::enable_if_t{}>* = nullptr -#endif - > - operator T&&() - const + template + struct wrapper { + operator T() { + static_assert(std::is_same{}, + "Getting a value from wildcard is not allowed.\n" + "See https://github.com/rollbear/trompeloeil/issues/270\n" + "and https://github.com/rollbear/trompeloeil/issues/290"); + return *this; + } + }; + template {}>::type* = nullptr> + operator T() { -#if !TROMPELOEIL_CLANG || TROMPELOEIL_CLANG_VERSION >= 40000 + return wrapper{}; + } - static_assert(std::is_same{}, - "Getting a value from wildcard is not allowed.\n" - "See https://github.com/rollbear/trompeloeil/issues/270\n" - "and https://github.com/rollbear/trompeloeil/issues/290"); -#endif + template + operator T&&() const + { +#if (!TROMPELOEIL_GCC || TROMPELOEIL_GCC_VERSION < 60000 || TROMPELOEIL_GCC_VERSION >= 90000) \ + && (!TROMPELOEIL_CLANG || TROMPELOEIL_CLANG_VERSION >= 40000 || !defined(_LIBCPP_STD_VER) || _LIBCPP_STD_VER != 14) + return wrapper{}; +#else return *this; +#endif } - template = 50000 - ,detail::enable_if_t{}>* = nullptr -#endif - > - operator T&() - volatile const // less preferred than T&& above + template + operator T&() const volatile { - static_assert(std::is_same{}, - "Getting a value from wildcard is not allowed.\n" - "See https://github.com/rollbear/trompeloeil/issues/270\n" - "and https://github.com/rollbear/trompeloeil/issues/290"); - return *this; + return wrapper{}; } + template constexpr bool @@ -1511,8 +1512,8 @@ template static void print( - std::ostream& os, - wildcard const&) + std::ostream& os, + wildcard const&) { os << " matching _"; } @@ -2354,7 +2355,7 @@ template // since it doesn't respect the trailing return type declaration on // the lambdas of template deduction context - #define TROMPELOEIL_MK_PRED_BINOP(name, op) \ +#define TROMPELOEIL_MK_PRED_BINOP(name, op) \ struct name { \ template \ auto operator()(X const& x, Y const& y) const -> decltype(x op y) \ @@ -2369,7 +2370,7 @@ template TROMPELOEIL_MK_PRED_BINOP(less_equal, <=); TROMPELOEIL_MK_PRED_BINOP(greater, >); TROMPELOEIL_MK_PRED_BINOP(greater_equal, >=); - #undef TROMPELOEIL_MK_PRED_BINOP +#undef TROMPELOEIL_MK_PRED_BINOP // Define `struct` with `operator()` to replace generic lambdas. @@ -2395,7 +2396,7 @@ template // These structures replace the `op` printer lambdas. - #define TROMPELOEIL_MK_OP_PRINTER(name, op_string) \ +#define TROMPELOEIL_MK_OP_PRINTER(name, op_string) \ struct name ## _printer \ { \ template \ @@ -2415,7 +2416,7 @@ template TROMPELOEIL_MK_OP_PRINTER(less_equal, " <= "); TROMPELOEIL_MK_OP_PRINTER(greater, " > "); TROMPELOEIL_MK_OP_PRINTER(greater_equal, " >= "); - #undef TROMPELOEIL_MK_OP_PRINTER +#undef TROMPELOEIL_MK_OP_PRINTER } @@ -4019,6 +4020,10 @@ template using call_matcher_base::name; using call_matcher_base::loc; +#if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 70000 && TROMPEOLEIL_GCC_VERSION < 80000 +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic push +#endif template call_matcher( char const *file, @@ -4028,6 +4033,9 @@ template : call_matcher_base(location{file, line}, call_string) , val(std::forward(u)...) {} +#if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 70000 && TROMPEOLEIL_GCC_VERSION < 80000 +#pragma GCC diagnostic pop +#endif call_matcher(call_matcher &&r) = delete; @@ -4857,8 +4865,8 @@ template return ::trompeloeil::mock_func( \ TROMPELOEIL_LINE_ID(cardinality_match){}, \ TROMPELOEIL_LINE_ID(expectations), \ - #name, \ - #sig \ +#name, \ +#sig \ TROMPELOEIL_PARAMS(num)); \ } \ \ @@ -4906,7 +4914,14 @@ template auto TROMPELOEIL_COUNT_ID(call_obj) = \ TROMPELOEIL_REQUIRE_CALL_V_LAMBDA(obj, func, #obj, #func, __VA_ARGS__) - +#if TROMPELOEIL_GCC +// This is highly unfortunate. Conversion warnings are desired here, but there +// are situations when the wildcard _ uses conversion when creating an +// expectation. It would be much better if the warning could be suppressed only +// for that type. See https://github.com/rollbear/trompeloeil/issues/293 +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic push +#endif #define TROMPELOEIL_REQUIRE_CALL_V_LAMBDA(obj, func, obj_s, func_s, ...) \ [&] \ { \ @@ -4919,8 +4934,9 @@ template __VA_ARGS__ \ ; \ }() - - +#if TROMPELOEIL_GCC +#pragma GCC diagnostic pop +#endif #define TROMPELOEIL_REQUIRE_CALL_LAMBDA_OBJ(obj, func, obj_s, func_s) \ ::trompeloeil::call_validator_t{(obj)} + \ ::trompeloeil::detail::conditional_t trompeloeil_e_t> \ {__FILE__, static_cast(__LINE__), obj_s "." func_s}.func - #define TROMPELOEIL_NAMED_REQUIRE_CALL_V(...) \ TROMPELOEIL_IDENTITY(TROMPELOEIL_NAMED_REQUIRE_CALL_IMPL TROMPELOEIL_LPAREN \ TROMPELOEIL_MORE_THAN_TWO_ARGS(__VA_ARGS__), __VA_ARGS__)) diff --git a/test/compiling_tests_14.cpp b/test/compiling_tests_14.cpp index 29db73ab..69356b51 100644 --- a/test/compiling_tests_14.cpp +++ b/test/compiling_tests_14.cpp @@ -1242,6 +1242,30 @@ TEST_CASE_METHOD( REQUIRE(reports.empty()); } +struct promiscuous +{ + template + promiscuous(T&&) {} +}; + +struct with_promiscuous +{ + MAKE_MOCK1(func, void(promiscuous)); +}; + +TEST_CASE_METHOD( + Fixture, + "C++14: wildcard matches parameter constructible from any type", + "[C++14][matching]") +{ + { + with_promiscuous obj; + REQUIRE_CALL(obj, func(_)); + obj.func(1); + } + REQUIRE(reports.empty()); +} + TEST_CASE_METHOD( Fixture, "C++14: ANY can match unique_ptr<> by value",