Merge pull request #2527 from PiotrNycz:gmock_prevent_return_ref_to_store_temporaries_2
PiperOrigin-RevId: 277061341
This commit is contained in:
		@@ -1052,6 +1052,10 @@ inline internal::ReturnRefAction<R> ReturnRef(R& x) {  // NOLINT
 | 
				
			|||||||
  return internal::ReturnRefAction<R>(x);
 | 
					  return internal::ReturnRefAction<R>(x);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Prevent using ReturnRef on reference to temporary.
 | 
				
			||||||
 | 
					template <typename R, R* = nullptr>
 | 
				
			||||||
 | 
					internal::ReturnRefAction<R> ReturnRef(R&&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Creates an action that returns the reference to a copy of the
 | 
					// Creates an action that returns the reference to a copy of the
 | 
				
			||||||
// argument.  The copy is created when the action is constructed and
 | 
					// argument.  The copy is created when the action is constructed and
 | 
				
			||||||
// lives as long as the action.
 | 
					// lives as long as the action.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,7 @@
 | 
				
			|||||||
#include <iterator>
 | 
					#include <iterator>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
#include "gmock/gmock.h"
 | 
					#include "gmock/gmock.h"
 | 
				
			||||||
#include "gmock/internal/gmock-port.h"
 | 
					#include "gmock/internal/gmock-port.h"
 | 
				
			||||||
#include "gtest/gtest.h"
 | 
					#include "gtest/gtest.h"
 | 
				
			||||||
@@ -647,6 +648,41 @@ TEST(ReturnRefTest, IsCovariant) {
 | 
				
			|||||||
  EXPECT_EQ(&derived, &a.Perform(std::make_tuple()));
 | 
					  EXPECT_EQ(&derived, &a.Perform(std::make_tuple()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T, typename = decltype(ReturnRef(std::declval<T&&>()))>
 | 
				
			||||||
 | 
					bool CanCallReturnRef(T&&) { return true; }
 | 
				
			||||||
 | 
					bool CanCallReturnRef(Unused) { return false; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Tests that ReturnRef(v) is working with non-temporaries (T&)
 | 
				
			||||||
 | 
					TEST(ReturnRefTest, WorksForNonTemporary) {
 | 
				
			||||||
 | 
					  int scalar_value = 123;
 | 
				
			||||||
 | 
					  EXPECT_TRUE(CanCallReturnRef(scalar_value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::string non_scalar_value("ABC");
 | 
				
			||||||
 | 
					  EXPECT_TRUE(CanCallReturnRef(non_scalar_value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const int const_scalar_value{321};
 | 
				
			||||||
 | 
					  EXPECT_TRUE(CanCallReturnRef(const_scalar_value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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 scalar_value = []()  -> int { return 123; };
 | 
				
			||||||
 | 
					  EXPECT_FALSE(CanCallReturnRef(scalar_value()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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<const int>(321)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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.
 | 
					// Tests that ReturnRefOfCopy(v) works for reference types.
 | 
				
			||||||
TEST(ReturnRefOfCopyTest, WorksForReference) {
 | 
					TEST(ReturnRefOfCopyTest, WorksForReference) {
 | 
				
			||||||
  int n = 42;
 | 
					  int n = 42;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user