From b11fb80e9e94384589037ecd0595b96105906bbc Mon Sep 17 00:00:00 2001 From: Piotr Nycz Date: Tue, 22 Oct 2019 15:58:00 +0200 Subject: Prevent using ReturnRef on reference to temporary Fixed issue: 2471 --- googlemock/include/gmock/gmock-actions.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index f12d39b..931e69a 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -1022,6 +1022,10 @@ inline internal::ReturnRefAction ReturnRef(R& x) { // NOLINT return internal::ReturnRefAction(x); } +// Prevent using ReturnRef on reference to temporary. +template +internal::ReturnRefAction ReturnRef(R&&) = delete; + // Creates an action that returns the reference to a copy of the // argument. The copy is created when the action is constructed and // lives as long as the action. -- cgit v0.12 From 19a3bbce512dc2c4959769134fddd52b27989003 Mon Sep 17 00:00:00 2001 From: Piotr Nycz Date: Tue, 22 Oct 2019 18:41:35 +0200 Subject: Added tests verifying that temporaries are accepted by ReturnRef Issue no 2527 --- googlemock/test/gmock-actions_test.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index f63c8c5..99d273a 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -646,6 +646,30 @@ TEST(ReturnRefTest, IsCovariant) { EXPECT_EQ(&derived, &a.Perform(std::make_tuple())); } +namespace +{ +template ()))> +bool CanCallReturnRef(T&&) { return true; } +bool CanCallReturnRef(Unused) { return false; } +} + +// Tests that ReturnRef(v) is not working with temporaries (T&&) +TEST(ReturnRefTest, WillNotAcceptTemporaryAkaRValueRef) { + int value = 13; + EXPECT_TRUE(CanCallReturnRef(value)); + EXPECT_FALSE(CanCallReturnRef(std::move(value))); + EXPECT_FALSE(CanCallReturnRef(value + 1)); + EXPECT_FALSE(CanCallReturnRef(123)); +} + +// Tests that ReturnRef(v) is not working with const temporaries (const T&&) +TEST(ReturnRefTest, WillNotAcceptConstTemporaryAkaContRValueRef) { + const int value = 42; + EXPECT_TRUE(CanCallReturnRef(value)); + EXPECT_FALSE(CanCallReturnRef(std::move(value))); +} + + // Tests that ReturnRefOfCopy(v) works for reference types. TEST(ReturnRefOfCopyTest, WorksForReference) { int n = 42; -- cgit v0.12 From 37590da6c08f062c511211462d2a13b57eedcd59 Mon Sep 17 00:00:00 2001 From: Piotr Nycz Date: Wed, 23 Oct 2019 10:12:48 +0200 Subject: Added more tests to verify: ReturnRef not accept temporary Issue 2471 --- googlemock/test/gmock-actions_test.cc | 72 +++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index 99d273a..86f570f 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -46,6 +46,7 @@ #include #include #include +#include #include "gmock/gmock.h" #include "gmock/internal/gmock-port.h" #include "gtest/gtest.h" @@ -646,29 +647,70 @@ TEST(ReturnRefTest, IsCovariant) { EXPECT_EQ(&derived, &a.Perform(std::make_tuple())); } -namespace -{ template ()))> bool CanCallReturnRef(T&&) { return true; } bool CanCallReturnRef(Unused) { return false; } + +// Defined here, because gmock has to work with C++11 (std::void_t is from C++17) +template struct precpp17_make_void { typedef void type;}; +template using precpp17_void_t = typename precpp17_make_void::type; + +template +struct HasReturnRefAction : std::false_type {}; +template +struct HasReturnRefAction()))>> + : std::true_type {}; + +// Just an example of non-POD type +class MyNonPodType { + public: + MyNonPodType(int a_value) : value_(a_value) {} + + private: + int value_; +}; +// Just an example of POD type +using MyPodType = int; + +// Tests that ReturnRef(v) is working with non-temporaries (T&) +TEST(ReturnRefTest, IsAcceptingNonTemporary) { + EXPECT_TRUE(HasReturnRefAction::value); + EXPECT_TRUE(HasReturnRefAction::value); + EXPECT_TRUE(HasReturnRefAction::value); + EXPECT_TRUE(HasReturnRefAction::value); + + MyNonPodType nonPodValue{123}; + EXPECT_TRUE(CanCallReturnRef(nonPodValue)); + + MyPodType podValue{321}; + EXPECT_TRUE(CanCallReturnRef(podValue)); + + const MyNonPodType constNonPodValue{123}; + EXPECT_TRUE(CanCallReturnRef(constNonPodValue)); + + const MyPodType constPodValue{321}; + EXPECT_TRUE(CanCallReturnRef(constPodValue)); } // Tests that ReturnRef(v) is not working with temporaries (T&&) -TEST(ReturnRefTest, WillNotAcceptTemporaryAkaRValueRef) { - int value = 13; - EXPECT_TRUE(CanCallReturnRef(value)); - EXPECT_FALSE(CanCallReturnRef(std::move(value))); - EXPECT_FALSE(CanCallReturnRef(value + 1)); - EXPECT_FALSE(CanCallReturnRef(123)); -} +TEST(ReturnRefTest, IsNotAcceptingTemporary) { + EXPECT_FALSE(HasReturnRefAction::value); + EXPECT_FALSE(HasReturnRefAction::value); + EXPECT_FALSE(HasReturnRefAction::value); + EXPECT_FALSE(HasReturnRefAction::value); -// Tests that ReturnRef(v) is not working with const temporaries (const T&&) -TEST(ReturnRefTest, WillNotAcceptConstTemporaryAkaContRValueRef) { - const int value = 42; - EXPECT_TRUE(CanCallReturnRef(value)); - EXPECT_FALSE(CanCallReturnRef(std::move(value))); -} + auto nonPodValue = []() -> MyNonPodType { return MyNonPodType{123}; }; + EXPECT_FALSE(CanCallReturnRef(nonPodValue())); + + auto podValue = []() -> MyPodType { return MyPodType{321}; }; + EXPECT_FALSE(CanCallReturnRef(podValue())); + auto constNonPodValue = []() -> const MyNonPodType { return MyNonPodType{123}; }; + EXPECT_FALSE(CanCallReturnRef(constNonPodValue())); + + // cannot use here callable returning "const POD" because C++ ignores such const for POD return type, so the static_cast + EXPECT_FALSE(CanCallReturnRef(static_cast(42))); +} // Tests that ReturnRefOfCopy(v) works for reference types. TEST(ReturnRefOfCopyTest, WorksForReference) { -- cgit v0.12 From d072682119f8673e090e2985f2cb5eb6a7b09fe0 Mon Sep 17 00:00:00 2001 From: Piotr Nycz Date: Thu, 24 Oct 2019 10:22:09 +0200 Subject: Tests simplified and names corrected (POD->scalar) Issue 2527 --- googlemock/test/gmock-actions_test.cc | 67 ++++++++++------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index 86f570f..52f140d 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -651,65 +651,34 @@ template ()))> bool CanCallReturnRef(T&&) { return true; } bool CanCallReturnRef(Unused) { return false; } -// Defined here, because gmock has to work with C++11 (std::void_t is from C++17) -template struct precpp17_make_void { typedef void type;}; -template using precpp17_void_t = typename precpp17_make_void::type; - -template -struct HasReturnRefAction : std::false_type {}; -template -struct HasReturnRefAction()))>> - : std::true_type {}; - -// Just an example of non-POD type -class MyNonPodType { - public: - MyNonPodType(int a_value) : value_(a_value) {} - - private: - int value_; -}; -// Just an example of POD type -using MyPodType = int; - // Tests that ReturnRef(v) is working with non-temporaries (T&) -TEST(ReturnRefTest, IsAcceptingNonTemporary) { - EXPECT_TRUE(HasReturnRefAction::value); - EXPECT_TRUE(HasReturnRefAction::value); - EXPECT_TRUE(HasReturnRefAction::value); - EXPECT_TRUE(HasReturnRefAction::value); +TEST(ReturnRefTest, WorksForNonTemporary) { + int scalarValue = 123; + EXPECT_TRUE(CanCallReturnRef(scalarValue)); - MyNonPodType nonPodValue{123}; - EXPECT_TRUE(CanCallReturnRef(nonPodValue)); + std::string nonScalarValue("ABC"); + EXPECT_TRUE(CanCallReturnRef(nonScalarValue)); - MyPodType podValue{321}; - EXPECT_TRUE(CanCallReturnRef(podValue)); + const int constScalarValue{321}; + EXPECT_TRUE(CanCallReturnRef(constScalarValue)); - const MyNonPodType constNonPodValue{123}; - EXPECT_TRUE(CanCallReturnRef(constNonPodValue)); - - const MyPodType constPodValue{321}; - EXPECT_TRUE(CanCallReturnRef(constPodValue)); + const std::string constNonScalarValue("CBA"); + EXPECT_TRUE(CanCallReturnRef(constNonScalarValue)); } // Tests that ReturnRef(v) is not working with temporaries (T&&) -TEST(ReturnRefTest, IsNotAcceptingTemporary) { - EXPECT_FALSE(HasReturnRefAction::value); - EXPECT_FALSE(HasReturnRefAction::value); - EXPECT_FALSE(HasReturnRefAction::value); - EXPECT_FALSE(HasReturnRefAction::value); - - auto nonPodValue = []() -> MyNonPodType { return MyNonPodType{123}; }; - EXPECT_FALSE(CanCallReturnRef(nonPodValue())); +TEST(ReturnRefTest, DoesNotWorkForTemporary) { + auto scalarValue = []() -> int { return 123; }; + EXPECT_FALSE(CanCallReturnRef(scalarValue())); - auto podValue = []() -> MyPodType { return MyPodType{321}; }; - EXPECT_FALSE(CanCallReturnRef(podValue())); + auto nonScalarValue = []() -> std::string { return "ABC"; }; + EXPECT_FALSE(CanCallReturnRef(nonScalarValue())); - auto constNonPodValue = []() -> const MyNonPodType { return MyNonPodType{123}; }; - EXPECT_FALSE(CanCallReturnRef(constNonPodValue())); + // cannot use here callable returning "const scalar type" because C++ ignores such const for scalar return type, so the static_cast + EXPECT_FALSE(CanCallReturnRef(static_cast(321))); - // cannot use here callable returning "const POD" because C++ ignores such const for POD return type, so the static_cast - EXPECT_FALSE(CanCallReturnRef(static_cast(42))); + auto constNonScalarValue = []() -> const std::string { return "CBA"; }; + EXPECT_FALSE(CanCallReturnRef(constNonScalarValue())); } // Tests that ReturnRefOfCopy(v) works for reference types. -- cgit v0.12 From 5ff72f5295f315a23f83ce4cc86380d5bfed0787 Mon Sep 17 00:00:00 2001 From: Piotr Nycz Date: Fri, 25 Oct 2019 10:29:15 +0200 Subject: Apply 80chars limit Issue 2527 --- googlemock/test/gmock-actions_test.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index 52f140d..e3c1d6c 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -674,7 +674,8 @@ TEST(ReturnRefTest, DoesNotWorkForTemporary) { auto nonScalarValue = []() -> std::string { return "ABC"; }; EXPECT_FALSE(CanCallReturnRef(nonScalarValue())); - // cannot use here callable returning "const scalar type" because C++ ignores such const for scalar return type, so the static_cast + // cannot use here callable returning "const scalar type", + // because such const for scalar return type is ignored EXPECT_FALSE(CanCallReturnRef(static_cast(321))); auto constNonScalarValue = []() -> const std::string { return "CBA"; }; -- cgit v0.12 From 208c2f6b6076c7386faed78ee570cca87c6d3964 Mon Sep 17 00:00:00 2001 From: Piotr Nycz Date: Fri, 25 Oct 2019 16:14:18 +0200 Subject: variable names corrected (followed google coding style) Issue 2527 --- googlemock/test/gmock-actions_test.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index e3c1d6c..a1b6f11 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -653,33 +653,33 @@ bool CanCallReturnRef(Unused) { return false; } // Tests that ReturnRef(v) is working with non-temporaries (T&) TEST(ReturnRefTest, WorksForNonTemporary) { - int scalarValue = 123; - EXPECT_TRUE(CanCallReturnRef(scalarValue)); + int scalar_value = 123; + EXPECT_TRUE(CanCallReturnRef(scalar_value)); - std::string nonScalarValue("ABC"); - EXPECT_TRUE(CanCallReturnRef(nonScalarValue)); + std::string non_scalar_value("ABC"); + EXPECT_TRUE(CanCallReturnRef(non_scalar_value)); - const int constScalarValue{321}; - EXPECT_TRUE(CanCallReturnRef(constScalarValue)); + const int const_scalar_value{321}; + EXPECT_TRUE(CanCallReturnRef(const_scalar_value)); - const std::string constNonScalarValue("CBA"); - EXPECT_TRUE(CanCallReturnRef(constNonScalarValue)); + const std::string const_non_scalar_value("CBA"); + EXPECT_TRUE(CanCallReturnRef(const_non_scalar_value)); } // Tests that ReturnRef(v) is not working with temporaries (T&&) TEST(ReturnRefTest, DoesNotWorkForTemporary) { - auto scalarValue = []() -> int { return 123; }; - EXPECT_FALSE(CanCallReturnRef(scalarValue())); + auto scalar_value = []() -> int { return 123; }; + EXPECT_FALSE(CanCallReturnRef(scalar_value())); - auto nonScalarValue = []() -> std::string { return "ABC"; }; - EXPECT_FALSE(CanCallReturnRef(nonScalarValue())); + auto non_scalar_value = []() -> std::string { return "ABC"; }; + EXPECT_FALSE(CanCallReturnRef(non_scalar_value())); // cannot use here callable returning "const scalar type", // because such const for scalar return type is ignored EXPECT_FALSE(CanCallReturnRef(static_cast(321))); - auto constNonScalarValue = []() -> const std::string { return "CBA"; }; - EXPECT_FALSE(CanCallReturnRef(constNonScalarValue())); + auto const_non_scalar_value = []() -> const std::string { return "CBA"; }; + EXPECT_FALSE(CanCallReturnRef(const_non_scalar_value())); } // Tests that ReturnRefOfCopy(v) works for reference types. -- cgit v0.12