diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index aa3a5eb16..c6b8c93b2 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -2217,7 +2217,8 @@ class PropertyMatcher { *listener << whose_property_ << "is "; // Cannot pass the return value (for example, int) to MatchPrintAndExplain, // which takes a non-const reference as argument. - RefToConstProperty result = (obj.*property_)(); + // Use std::invoke to handle potential default arguments. + RefToConstProperty result = std::invoke(property_, obj); return MatchPrintAndExplain(result, matcher_, listener); } @@ -2225,11 +2226,10 @@ class PropertyMatcher { MatchResultListener* listener) const { if (p == nullptr) return false; - *listener << "which points to an object "; - // Since *p has a property method, it must be a class/struct/union - // type and thus cannot be a pointer. Therefore we pass - // false_type() as the first argument. - return MatchAndExplainImpl(std::false_type(), *p, listener); + *listener << "which points to an object " << whose_property_ << "is "; + // Use std::invoke to handle potential default arguments with pointers. + RefToConstProperty result = std::invoke(property_, p); + return MatchPrintAndExplain(result, matcher_, listener); } Property property_; diff --git a/googlemock/test/gmock-matchers-containers_test.cc b/googlemock/test/gmock-matchers-containers_test.cc index e9f1a02d8..603e75662 100644 --- a/googlemock/test/gmock-matchers-containers_test.cc +++ b/googlemock/test/gmock-matchers-containers_test.cc @@ -45,8 +45,8 @@ #include #include "gmock/gmock.h" -#include "test/gmock-matchers_test.h" #include "gtest/gtest.h" +#include "test/gmock-matchers_test.h" // Silence warning C4244: 'initializing': conversion from 'int' to 'short', // possible loss of data and C4100, unreferenced local parameter @@ -3439,8 +3439,51 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) { EXPECT_THAT(a, Contains(Not(Contains(5)))); } +#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L + +#include + +class SourceLocationClass { + public: + const std::source_location& GetLocation( + std::source_location sl = std::source_location::current()) const { + last_location_ = sl; // Store it to check later + return last_location_; + } + + private: + mutable std::source_location last_location_; +}; + +MATCHER_P(LocationFunctionName, expected_function_name, "") { + return std::string(arg.function_name()) == expected_function_name; +} + +TEST(PropertyTest, WorksWithSourceLocationDefaultArgument) { + SourceLocationClass obj; + const char* expected_func = ""; +#if defined(__GNUC__) || defined(__clang__) + expected_func = + "testing::gmock_matchers_containers_test::" + "PropertyTest_WorksWithSourceLocationDefaultArgument_Test::TestBody()"; +#elif defined(_MSC_VER) + expected_func = + "testing::gmock_matchers_containers_test::" + "PropertyTest_WorksWithSourceLocationDefaultArgument_Test::TestBody"; // No parentheses usually +#else + expected_func = "TestBody"; +#endif + + Matcher m = Property( + &SourceLocationClass::GetLocation, LocationFunctionName(expected_func)); + + EXPECT_TRUE(m.Matches(obj)); + + const auto& loc = obj.GetLocation(); + EXPECT_STREQ(expected_func, loc.function_name()); +} + +#endif // __cpp_lib_source_location } // namespace } // namespace gmock_matchers_test } // namespace testing - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4244 4100