Skip to content

Commit

Permalink
wildcard matches objects constructible from anything
Browse files Browse the repository at this point in the history
Unfortunately have to silence warnings when matching creating
expectations.
  • Loading branch information
rollbear committed Apr 9, 2023
1 parent 9565937 commit 3d7aa24
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 38 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion compilation_errors/value_from_wildcard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* Project home: https://github.com/rollbear/trompeloeil
*/

// exception: clang++-3
// exception: g++-[678]
// pass: value from wildcard

#include <trompeloeil.hpp>
Expand Down
89 changes: 52 additions & 37 deletions include/trompeloeil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1091,38 +1091,39 @@ namespace trompeloeil

struct wildcard : public matcher
{
template <typename T
#if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 50000
,detail::enable_if_t<!std::is_convertible<wildcard&, T>{}>* = nullptr
#endif
>
operator T&&()
const
template <typename T>
struct wrapper {
operator T() {
static_assert(std::is_same<T, void>{},
"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 <typename T, typename std::enable_if<!std::is_convertible<wildcard&, T>{}>::type* = nullptr>
operator T()
{
#if !TROMPELOEIL_CLANG || TROMPELOEIL_CLANG_VERSION >= 40000
return wrapper<T>{};
}

static_assert(std::is_same<T, void>{},
"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 <typename T>
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<T &&>{};
#else
return *this;
#endif
}

template <typename T
#if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 50000
,detail::enable_if_t<!std::is_convertible<wildcard&, T>{}>* = nullptr
#endif
>
operator T&()
volatile const // less preferred than T&& above
template <typename T>
operator T&() const volatile
{
static_assert(std::is_same<T, void>{},
"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<T&>{};
}

template <typename T>
constexpr
bool
Expand Down Expand Up @@ -1511,8 +1512,8 @@ template <typename T>
static
void
print(
std::ostream& os,
wildcard const&)
std::ostream& os,
wildcard const&)
{
os << " matching _";
}
Expand Down Expand Up @@ -2354,7 +2355,7 @@ template <typename T>
// 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 <typename X, typename Y> \
auto operator()(X const& x, Y const& y) const -> decltype(x op y) \
Expand All @@ -2369,7 +2370,7 @@ template <typename T>
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.

Expand All @@ -2395,7 +2396,7 @@ template <typename T>

// 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 <typename T> \
Expand All @@ -2415,7 +2416,7 @@ template <typename T>
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

}

Expand Down Expand Up @@ -4019,6 +4020,10 @@ template <typename T>
using call_matcher_base<Sig>::name;
using call_matcher_base<Sig>::loc;

#if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 70000 && TROMPEOLEIL_GCC_VERSION < 80000
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic push
#endif
template <typename ... U>
call_matcher(
char const *file,
Expand All @@ -4028,6 +4033,9 @@ template <typename T>
: call_matcher_base<Sig>(location{file, line}, call_string)
, val(std::forward<U>(u)...)
{}
#if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 70000 && TROMPEOLEIL_GCC_VERSION < 80000
#pragma GCC diagnostic pop
#endif

call_matcher(call_matcher &&r) = delete;

Expand Down Expand Up @@ -4857,8 +4865,8 @@ template <typename T>
return ::trompeloeil::mock_func<trompeloeil_movable_mock, TROMPELOEIL_REMOVE_PAREN(sig)>( \
TROMPELOEIL_LINE_ID(cardinality_match){}, \
TROMPELOEIL_LINE_ID(expectations), \
#name, \
#sig \
#name, \
#sig \
TROMPELOEIL_PARAMS(num)); \
} \
\
Expand Down Expand Up @@ -4906,7 +4914,14 @@ template <typename T>
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, ...) \
[&] \
{ \
Expand All @@ -4919,16 +4934,16 @@ template <typename T>
__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<trompeloeil_s_t>{(obj)} + \
::trompeloeil::detail::conditional_t<false, \
decltype((obj).func), \
trompeloeil_e_t> \
{__FILE__, static_cast<unsigned long>(__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__))
Expand Down
24 changes: 24 additions & 0 deletions test/compiling_tests_14.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,30 @@ TEST_CASE_METHOD(
REQUIRE(reports.empty());
}

struct promiscuous
{
template <typename T>
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",
Expand Down

0 comments on commit 3d7aa24

Please sign in to comment.