From 51f8ad47df298964f48cb89e1d7bf953f49e6731 Mon Sep 17 00:00:00 2001 From: Victor Costan Date: Fri, 6 Apr 2018 17:17:35 -0700 Subject: [PATCH] Sync gmock-generated-nice-strict.h.pump with gmock-generated-nice-strict.h. Commit fe402c27790ff1cc9a7e17c5d0aea4ebe7fd8a71 published the changes in internal CL 156157936, but missed the diff in gmock-generated-nice-strict.h.pump. This makes it difficult to reason about the change, because the .pump file is more concise than the generated file. This PR was tested by re-generating the .h file using the command below and checking the git diff. ./googletest/scripts/pump.py \ googlemock/include/gmock/gmock-generated-nice-strict.h.pump --- .../gmock/gmock-generated-nice-strict.h.pump | 92 ++++++++++++------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/googlemock/include/gmock/gmock-generated-nice-strict.h.pump b/googlemock/include/gmock/gmock-generated-nice-strict.h.pump index 3ee1ce7f..4973c356 100644 --- a/googlemock/include/gmock/gmock-generated-nice-strict.h.pump +++ b/googlemock/include/gmock/gmock-generated-nice-strict.h.pump @@ -52,10 +52,9 @@ $var n = 10 $$ The maximum arity we support. // NiceMock. // // NiceMock, NaggyMock, and StrictMock "inherit" the constructors of -// their respective base class, with up-to $n arguments. Therefore -// you can write NiceMock(5, "a") to construct a nice mock -// where MockFoo has a constructor that accepts (int, const char*), -// for example. +// their respective base class. Therefore you can write +// NiceMock(5, "a") to construct a nice mock where MockFoo +// has a constructor that accepts (int, const char*), for example. // // A known limitation is that NiceMock, NaggyMock, // and StrictMock only works for mock methods defined using @@ -64,10 +63,6 @@ $var n = 10 $$ The maximum arity we support. // or "strict" modifier may not affect it, depending on the compiler. // In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT // supported. -// -// Another known limitation is that the constructors of the base mock -// cannot have arguments passed by non-const reference, which are -// banned by the Google C++ style guide anyway. #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ @@ -88,44 +83,79 @@ $var method=[[$if kind==0 [[AllowUninterestingCalls]] $elif kind==1 [[WarnUninterestingCalls]] $else [[FailUninterestingCalls]]]] -template -class $clazz : public MockClass { - public: - // We don't factor out the constructor body to a common method, as - // we have to avoid a possible clash with members of MockClass. - $clazz() { - ::testing::Mock::$method( - internal::ImplicitCast_(this)); - } +namespace internal { - // C++ doesn't (yet) allow inheritance of constructors, so we have - // to define it for each arity. +// $clazz[[]]Base serves as a mix-in to establish the "uninteresting call" +// behavior for $clazz on construction. It accomplishes this via CRTP to get +// access to the derived MockClass. +template +class $clazz[[]]Base { + protected: + $clazz[[]]Base(); + + ~$clazz[[]]Base(); +}; + +} // namespace internal + +template +class $clazz : public MockClass, public internal::$clazz[[]]Base { + public: + $clazz() : MockClass() {} + +#if GTEST_LANG_CXX11 + // Ideally, we would inherit base class's constructors through a using + // declaration, which would preserve their visibility. However, many existing + // tests rely on the fact that current implementation reexports protected + // constructors as public. These tests would need to be cleaned up first. + + // Single argument constructor is special-cased so that it can be + // made explicit. + template + explicit $clazz(A&& arg) : MockClass(std::forward(arg)) {} + + template + $clazz(A1&& arg1, A2&& arg2, An&&... args) + : MockClass(std::forward(arg1), std::forward(arg2), + std::forward(args)...) {} +#else + // C++98 doesn't have variadic templates, so we have to define one + // for each arity. template - explicit $clazz(const A1& a1) : MockClass(a1) { - ::testing::Mock::$method( - internal::ImplicitCast_(this)); - } + explicit $clazz(const A1& a1) : MockClass(a1) {} $range i 2..n $for i [[ $range j 1..i template <$for j, [[typename A$j]]> - $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) { - ::testing::Mock::$method( - internal::ImplicitCast_(this)); - } + $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {} ]] - virtual ~$clazz() { - ::testing::Mock::UnregisterCallReaction( - internal::ImplicitCast_(this)); - } +#endif // GTEST_LANG_CXX11 private: GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz); }; +namespace internal { + +template +$clazz[[]]Base::$clazz[[]]Base() { + ::testing::Mock::$method( + internal::ImplicitCast_( + static_cast<$clazz *>(this))); +} + +template +$clazz[[]]Base::~$clazz[[]]Base() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_( + static_cast<$clazz*>(this))); +} + +} // namespace internal + ]] // The following specializations catch some (relatively more common)