Adds more tests for using SetArgumentPointee with protobufs; works around a compiler bug on Symbian that gmock-printers.h triggers; reduces template code bloat in gmock-matchers.h; avoids RTTI when it's disabled.
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index 5700fb2..bf049d4 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -960,10 +960,35 @@
 
 #undef GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
 
-// TODO(vladl@google.com): Move Impl outside of NotMatcher and rename it
-// NotMatcherImpl to reduce compilation overhead and the size of the binary.
-// This also applies to BothOfMatcher::Impl and EitherOfMatcher::Impl.
-//
+// Implements the Not(...) matcher for a particular argument type T.
+// We do not nest it inside the NotMatcher class template, as that
+// will prevent different instantiations of NotMatcher from sharing
+// the same NotMatcherImpl<T> class.
+template <typename T>
+class NotMatcherImpl : public MatcherInterface<T> {
+ public:
+  explicit NotMatcherImpl(const Matcher<T>& matcher)
+      : matcher_(matcher) {}
+
+  virtual bool Matches(T x) const {
+    return !matcher_.Matches(x);
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    matcher_.DescribeNegationTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    matcher_.DescribeTo(os);
+  }
+
+  virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
+    matcher_.ExplainMatchResultTo(x, os);
+  }
+ private:
+  const Matcher<T> matcher_;
+};
+
 // Implements the Not(m) matcher, which matches a value that doesn't
 // match matcher m.
 template <typename InnerMatcher>
@@ -975,38 +1000,74 @@
   // to match any type m can match.
   template <typename T>
   operator Matcher<T>() const {
-    return Matcher<T>(new Impl<T>(matcher_));
+    return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_)));
   }
  private:
-  // Implements the Not(...) matcher for a particular argument type T.
-  template <typename T>
-  class Impl : public MatcherInterface<T> {
-   public:
-    explicit Impl(InnerMatcher matcher)
-        : matcher_(SafeMatcherCast<T>(matcher)) {}
-
-    virtual bool Matches(T x) const {
-      return !matcher_.Matches(x);
-    }
-
-    virtual void DescribeTo(::std::ostream* os) const {
-      matcher_.DescribeNegationTo(os);
-    }
-
-    virtual void DescribeNegationTo(::std::ostream* os) const {
-      matcher_.DescribeTo(os);
-    }
-
-    virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
-      matcher_.ExplainMatchResultTo(x, os);
-    }
-   private:
-    const Matcher<T> matcher_;
-  };
-
   InnerMatcher matcher_;
 };
 
+// Implements the AllOf(m1, m2) matcher for a particular argument type
+// T. We do not nest it inside the BothOfMatcher class template, as
+// that will prevent different instantiations of BothOfMatcher from
+// sharing the same BothOfMatcherImpl<T> class.
+template <typename T>
+class BothOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  virtual bool Matches(T x) const {
+    return matcher1_.Matches(x) && matcher2_.Matches(x);
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") and (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "not ";
+    DescribeTo(os);
+  }
+
+  virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
+    if (Matches(x)) {
+      // When both matcher1_ and matcher2_ match x, we need to
+      // explain why *both* of them match.
+      ::std::stringstream ss1;
+      matcher1_.ExplainMatchResultTo(x, &ss1);
+      const internal::string s1 = ss1.str();
+
+      ::std::stringstream ss2;
+      matcher2_.ExplainMatchResultTo(x, &ss2);
+      const internal::string s2 = ss2.str();
+
+      if (s1 == "") {
+        *os << s2;
+      } else {
+        *os << s1;
+        if (s2 != "") {
+          *os << "; " << s2;
+        }
+      }
+    } else {
+      // Otherwise we only need to explain why *one* of them fails
+      // to match.
+      if (!matcher1_.Matches(x)) {
+        matcher1_.ExplainMatchResultTo(x, os);
+      } else {
+        matcher2_.ExplainMatchResultTo(x, os);
+      }
+    }
+  }
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
+};
+
 // Used for implementing the AllOf(m_1, ..., m_n) matcher, which
 // matches a value that matches all of the matchers m_1, ..., and m_n.
 template <typename Matcher1, typename Matcher2>
@@ -1020,72 +1081,73 @@
   // both Matcher1 and Matcher2 can match.
   template <typename T>
   operator Matcher<T>() const {
-    return Matcher<T>(new Impl<T>(matcher1_, matcher2_));
+    return Matcher<T>(new BothOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_),
+                                               SafeMatcherCast<T>(matcher2_)));
   }
  private:
-  // Implements the AllOf(m1, m2) matcher for a particular argument
-  // type T.
-  template <typename T>
-  class Impl : public MatcherInterface<T> {
-   public:
-    Impl(Matcher1 matcher1, Matcher2 matcher2)
-        : matcher1_(SafeMatcherCast<T>(matcher1)),
-          matcher2_(SafeMatcherCast<T>(matcher2)) {}
+  Matcher1 matcher1_;
+  Matcher2 matcher2_;
+};
 
-    virtual bool Matches(T x) const {
-      return matcher1_.Matches(x) && matcher2_.Matches(x);
-    }
+// Implements the AnyOf(m1, m2) matcher for a particular argument type
+// T.  We do not nest it inside the AnyOfMatcher class template, as
+// that will prevent different instantiations of AnyOfMatcher from
+// sharing the same EitherOfMatcherImpl<T> class.
+template <typename T>
+class EitherOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
 
-    virtual void DescribeTo(::std::ostream* os) const {
-      *os << "(";
-      matcher1_.DescribeTo(os);
-      *os << ") and (";
-      matcher2_.DescribeTo(os);
-      *os << ")";
-    }
+  virtual bool Matches(T x) const {
+    return matcher1_.Matches(x) || matcher2_.Matches(x);
+  }
 
-    virtual void DescribeNegationTo(::std::ostream* os) const {
-      *os << "not ";
-      DescribeTo(os);
-    }
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") or (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
 
-    virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
-      if (Matches(x)) {
-        // When both matcher1_ and matcher2_ match x, we need to
-        // explain why *both* of them match.
-        ::std::stringstream ss1;
-        matcher1_.ExplainMatchResultTo(x, &ss1);
-        const internal::string s1 = ss1.str();
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "not ";
+    DescribeTo(os);
+  }
 
-        ::std::stringstream ss2;
-        matcher2_.ExplainMatchResultTo(x, &ss2);
-        const internal::string s2 = ss2.str();
-
-        if (s1 == "") {
-          *os << s2;
-        } else {
-          *os << s1;
-          if (s2 != "") {
-            *os << "; " << s2;
-          }
-        }
+  virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
+    if (Matches(x)) {
+      // If either matcher1_ or matcher2_ matches x, we just need
+      // to explain why *one* of them matches.
+      if (matcher1_.Matches(x)) {
+        matcher1_.ExplainMatchResultTo(x, os);
       } else {
-        // Otherwise we only need to explain why *one* of them fails
-        // to match.
-        if (!matcher1_.Matches(x)) {
-          matcher1_.ExplainMatchResultTo(x, os);
-        } else {
-          matcher2_.ExplainMatchResultTo(x, os);
+        matcher2_.ExplainMatchResultTo(x, os);
+      }
+    } else {
+      // Otherwise we need to explain why *neither* matches.
+      ::std::stringstream ss1;
+      matcher1_.ExplainMatchResultTo(x, &ss1);
+      const internal::string s1 = ss1.str();
+
+      ::std::stringstream ss2;
+      matcher2_.ExplainMatchResultTo(x, &ss2);
+      const internal::string s2 = ss2.str();
+
+      if (s1 == "") {
+        *os << s2;
+      } else {
+        *os << s1;
+        if (s2 != "") {
+          *os << "; " << s2;
         }
       }
     }
-   private:
-    const Matcher<T> matcher1_;
-    const Matcher<T> matcher2_;
-  };
-
-  Matcher1 matcher1_;
-  Matcher2 matcher2_;
+  }
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
 };
 
 // Used for implementing the AnyOf(m_1, ..., m_n) matcher, which
@@ -1102,69 +1164,10 @@
   // both Matcher1 and Matcher2 can match.
   template <typename T>
   operator Matcher<T>() const {
-    return Matcher<T>(new Impl<T>(matcher1_, matcher2_));
+    return Matcher<T>(new EitherOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_),
+                                                 SafeMatcherCast<T>(matcher2_)));
   }
  private:
-  // Implements the AnyOf(m1, m2) matcher for a particular argument
-  // type T.
-  template <typename T>
-  class Impl : public MatcherInterface<T> {
-   public:
-    Impl(Matcher1 matcher1, Matcher2 matcher2)
-        : matcher1_(SafeMatcherCast<T>(matcher1)),
-          matcher2_(SafeMatcherCast<T>(matcher2)) {}
-
-    virtual bool Matches(T x) const {
-      return matcher1_.Matches(x) || matcher2_.Matches(x);
-    }
-
-    virtual void DescribeTo(::std::ostream* os) const {
-      *os << "(";
-      matcher1_.DescribeTo(os);
-      *os << ") or (";
-      matcher2_.DescribeTo(os);
-      *os << ")";
-    }
-
-    virtual void DescribeNegationTo(::std::ostream* os) const {
-      *os << "not ";
-      DescribeTo(os);
-    }
-
-    virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
-      if (Matches(x)) {
-        // If either matcher1_ or matcher2_ matches x, we just need
-        // to explain why *one* of them matches.
-        if (matcher1_.Matches(x)) {
-          matcher1_.ExplainMatchResultTo(x, os);
-        } else {
-          matcher2_.ExplainMatchResultTo(x, os);
-        }
-      } else {
-        // Otherwise we need to explain why *neither* matches.
-        ::std::stringstream ss1;
-        matcher1_.ExplainMatchResultTo(x, &ss1);
-        const internal::string s1 = ss1.str();
-
-        ::std::stringstream ss2;
-        matcher2_.ExplainMatchResultTo(x, &ss2);
-        const internal::string s2 = ss2.str();
-
-        if (s1 == "") {
-          *os << s2;
-        } else {
-          *os << s1;
-          if (s2 != "") {
-            *os << "; " << s2;
-          }
-        }
-      }
-    }
-   private:
-    const Matcher<T> matcher1_;
-    const Matcher<T> matcher2_;
-  };
-
   Matcher1 matcher1_;
   Matcher2 matcher2_;
 };
diff --git a/include/gmock/gmock-printers.h b/include/gmock/gmock-printers.h
index bbe44c3..6997a6c 100644
--- a/include/gmock/gmock-printers.h
+++ b/include/gmock/gmock-printers.h
@@ -211,7 +211,9 @@
 // Used to print an STL-style container when the user doesn't define
 // a PrintTo() for it.
 template <typename C>
-void DefaultPrintTo(IsContainer, const C& container, ::std::ostream* os) {
+void DefaultPrintTo(IsContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const C& container, ::std::ostream* os) {
   const size_t kMaxCount = 32;  // The maximum number of elements to print.
   *os << '{';
   size_t count = 0;
@@ -234,9 +236,31 @@
   *os << '}';
 }
 
-// Used to print a value when the user doesn't define PrintTo() for it.
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
 template <typename T>
-void DefaultPrintTo(IsNotContainer, const T& value, ::std::ostream* os) {
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    true_type /* is a pointer */,
+                    T* p, ::std::ostream* os) {
+  if (p == NULL) {
+    *os << "NULL";
+  } else {
+    // We cannot use implicit_cast or static_cast here, as they don't
+    // work when p is a function pointer.
+    *os << reinterpret_cast<const void*>(p);
+  }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const T& value, ::std::ostream* os) {
   ::testing_internal::DefaultPrintNonContainerTo(value, os);
 }
 
@@ -253,10 +277,11 @@
 // wants).
 template <typename T>
 void PrintTo(const T& value, ::std::ostream* os) {
-  // DefaultPrintTo() is overloaded.  The type of its first argument
-  // determines which version will be picked.  If T is an STL-style
-  // container, the version for container will be called.  Otherwise
-  // the generic version will be called.
+  // DefaultPrintTo() is overloaded.  The type of its first two
+  // arguments determine which version will be picked.  If T is an
+  // STL-style container, the version for container will be called; if
+  // T is a pointer, the pointer version will be called; otherwise the
+  // generic version will be called.
   //
   // Note that we check for container types here, prior to we check
   // for protocol message types in our operator<<.  The rationale is:
@@ -267,7 +292,14 @@
   // incompatible with Google Mock's format for the container
   // elements; therefore we check for container types here to ensure
   // that our format is used.
-  DefaultPrintTo(IsContainerTest<T>(0), value, os);
+  //
+  // The second argument of DefaultPrintTo() is needed to bypass a bug
+  // in Symbian's C++ compiler that prevents it from picking the right
+  // overload between:
+  //
+  //   PrintTo(const T& x, ...);
+  //   PrintTo(T* x, ...);
+  DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
 }
 
 // The following list of PrintTo() overloads tells
@@ -323,22 +355,6 @@
 }
 #endif
 
-// Overload for pointers that are neither char pointers nor member
-// pointers.  (A member variable pointer or member function pointer
-// doesn't really points to a location in the address space.  Their
-// representation is implementation-defined.  Therefore they will be
-// printed as raw bytes.)
-template <typename T>
-void PrintTo(T* p, ::std::ostream* os) {
-  if (p == NULL) {
-    *os << "NULL";
-  } else {
-    // We cannot use implicit_cast or static_cast here, as they don't
-    // work when p is a function pointer.
-    *os << reinterpret_cast<const void*>(p);
-  }
-}
-
 // Overload for C arrays.  Multi-dimensional arrays are printed
 // properly.
 
diff --git a/include/gmock/internal/gmock-port.h b/include/gmock/internal/gmock-port.h
index d242c8e..75be9ed 100644
--- a/include/gmock/internal/gmock-port.h
+++ b/include/gmock/internal/gmock-port.h
@@ -162,7 +162,9 @@
     implicit_cast<From*, To>(0);
   }
 
+#if GTEST_HAS_RTTI
   assert(f == NULL || dynamic_cast<To>(f) != NULL);  // RTTI: debug mode only!
+#endif
   return static_cast<To>(f);
 }
 
diff --git a/test/gmock-actions_test.cc b/test/gmock-actions_test.cc
index e4939e1..2446260 100644
--- a/test/gmock-actions_test.cc
+++ b/test/gmock-actions_test.cc
@@ -646,16 +646,15 @@
 
 #if GMOCK_HAS_PROTOBUF_
 
-// Tests that SetArgumentPointee<N>(proto_buffer) sets the variable
-// pointed to by the N-th (0-based) argument to proto_buffer.
+// Tests that SetArgumentPointee<N>(proto_buffer) sets the v1 protobuf
+// variable pointed to by the N-th (0-based) argument to proto_buffer.
 TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProtoBufferType) {
-  typedef void MyFunction(bool, TestMessage*);
   TestMessage* const msg = new TestMessage;
   msg->set_member("yes");
   TestMessage orig_msg;
   orig_msg.CopyFrom(*msg);
 
-  Action<MyFunction> a = SetArgumentPointee<1>(*msg);
+  Action<void(bool, TestMessage*)> a = SetArgumentPointee<1>(*msg);
   // SetArgumentPointee<N>(proto_buffer) makes a copy of proto_buffer
   // s.t. the action works even when the original proto_buffer has
   // died.  We ensure this behavior by deleting msg before using the
@@ -668,18 +667,41 @@
   EXPECT_TRUE(orig_msg.Equals(dest));
 }
 
-// Tests that SetArgumentPointee<N>(proto2_buffer) sets the variable
-// pointed to by the N-th (0-based) argument to proto2_buffer.
+// Tests that SetArgumentPointee<N>(proto_buffer) sets the
+// ::ProtocolMessage variable pointed to by the N-th (0-based)
+// argument to proto_buffer.
+TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProtoBufferBaseType) {
+  TestMessage* const msg = new TestMessage;
+  msg->set_member("yes");
+  TestMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, ::ProtocolMessage*)> a = SetArgumentPointee<1>(*msg);
+  // SetArgumentPointee<N>(proto_buffer) makes a copy of proto_buffer
+  // s.t. the action works even when the original proto_buffer has
+  // died.  We ensure this behavior by deleting msg before using the
+  // action.
+  delete msg;
+
+  TestMessage dest;
+  ::ProtocolMessage* const dest_base = &dest;
+  EXPECT_FALSE(orig_msg.Equals(dest));
+  a.Perform(make_tuple(true, dest_base));
+  EXPECT_TRUE(orig_msg.Equals(dest));
+}
+
+// Tests that SetArgumentPointee<N>(proto2_buffer) sets the v2
+// protobuf variable pointed to by the N-th (0-based) argument to
+// proto2_buffer.
 TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProto2BufferType) {
   using testing::internal::FooMessage;
-  typedef void MyFunction(bool, FooMessage*);
   FooMessage* const msg = new FooMessage;
   msg->set_int_field(2);
   msg->set_string_field("hi");
   FooMessage orig_msg;
   orig_msg.CopyFrom(*msg);
 
-  Action<MyFunction> a = SetArgumentPointee<1>(*msg);
+  Action<void(bool, FooMessage*)> a = SetArgumentPointee<1>(*msg);
   // SetArgumentPointee<N>(proto2_buffer) makes a copy of
   // proto2_buffer s.t. the action works even when the original
   // proto2_buffer has died.  We ensure this behavior by deleting msg
@@ -693,6 +715,32 @@
   EXPECT_EQ("hi", dest.string_field());
 }
 
+// Tests that SetArgumentPointee<N>(proto2_buffer) sets the
+// proto2::Message variable pointed to by the N-th (0-based) argument
+// to proto2_buffer.
+TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProto2BufferBaseType) {
+  using testing::internal::FooMessage;
+  FooMessage* const msg = new FooMessage;
+  msg->set_int_field(2);
+  msg->set_string_field("hi");
+  FooMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, ::proto2::Message*)> a = SetArgumentPointee<1>(*msg);
+  // SetArgumentPointee<N>(proto2_buffer) makes a copy of
+  // proto2_buffer s.t. the action works even when the original
+  // proto2_buffer has died.  We ensure this behavior by deleting msg
+  // before using the action.
+  delete msg;
+
+  FooMessage dest;
+  dest.set_int_field(0);
+  ::proto2::Message* const dest_base = &dest;
+  a.Perform(make_tuple(true, dest_base));
+  EXPECT_EQ(2, dest.int_field());
+  EXPECT_EQ("hi", dest.string_field());
+}
+
 #endif  // GMOCK_HAS_PROTOBUF_
 
 // Tests that SetArrayArgument<N>(first, last) sets the elements of the array