diff --git a/include/gmock/gmock-actions.h b/include/gmock/gmock-actions.h
index f88ac80d..af3483f7 100644
--- a/include/gmock/gmock-actions.h
+++ b/include/gmock/gmock-actions.h
@@ -59,9 +59,6 @@ namespace testing {
 
 namespace internal {
 
-template <typename F>
-class MonomorphicDoDefaultActionImpl;
-
 template <typename F1, typename F2>
 class ActionAdaptor;
 
@@ -255,8 +252,7 @@ class ActionInterface {
   typedef typename internal::Function<F>::Result Result;
   typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
 
-  ActionInterface() : is_do_default_(false) {}
-
+  ActionInterface() {}
   virtual ~ActionInterface() {}
 
   // Performs the action.  This method is not const, as in general an
@@ -265,21 +261,7 @@ class ActionInterface {
   // remember the current element.
   virtual Result Perform(const ArgumentTuple& args) = 0;
 
-  // Returns true iff this is the DoDefault() action.
-  bool IsDoDefault() const { return is_do_default_; }
-
  private:
-  template <typename Function>
-  friend class internal::MonomorphicDoDefaultActionImpl;
-
-  // This private constructor is reserved for implementing
-  // DoDefault(), the default action for a given mock function.
-  explicit ActionInterface(bool is_do_default)
-      : is_do_default_(is_do_default) {}
-
-  // True iff this action is DoDefault().
-  const bool is_do_default_;
-
   GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface);
 };
 
@@ -302,7 +284,8 @@ class Action {
   // STL containers.
   Action() : impl_(NULL) {}
 
-  // Constructs an Action from its implementation.
+  // Constructs an Action from its implementation.  A NULL impl is
+  // used to represent the "do-default" action.
   explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
 
   // Copy constructor.
@@ -316,7 +299,7 @@ class Action {
   explicit Action(const Action<Func>& action);
 
   // Returns true iff this is the DoDefault() action.
-  bool IsDoDefault() const { return impl_->IsDoDefault(); }
+  bool IsDoDefault() const { return impl_.get() == NULL; }
 
   // Performs the action.  Note that this method is const even though
   // the corresponding method in ActionInterface is not.  The reason
@@ -325,6 +308,13 @@ class Action {
   // cannot change state.  (Think of the difference between a const
   // pointer and a pointer to const.)
   Result Perform(const ArgumentTuple& args) const {
+    internal::Assert(
+        !IsDoDefault(), __FILE__, __LINE__,
+        "You are using DoDefault() inside a composite action like "
+        "DoAll() or WithArgs().  This is not supported for technical "
+        "reasons.  Please instead spell out the default action, or "
+        "assign the default action to an Action variable and use "
+        "the variable in various places.");
     return impl_->Perform(args);
   }
 
@@ -633,42 +623,13 @@ class ReturnRefOfCopyAction {
   GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction);
 };
 
-// Implements the DoDefault() action for a particular function type F.
-template <typename F>
-class MonomorphicDoDefaultActionImpl : public ActionInterface<F> {
- public:
-  typedef typename Function<F>::Result Result;
-  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
-
-  MonomorphicDoDefaultActionImpl() : ActionInterface<F>(true) {}
-
-  // For technical reasons, DoDefault() cannot be used inside a
-  // composite action (e.g. DoAll(...)).  It can only be used at the
-  // top level in an EXPECT_CALL().  If this function is called, the
-  // user must be using DoDefault() inside a composite action, and we
-  // have to generate a run-time error.
-  virtual Result Perform(const ArgumentTuple&) {
-    Assert(false, __FILE__, __LINE__,
-           "You are using DoDefault() inside a composite action like "
-           "DoAll() or WithArgs().  This is not supported for technical "
-           "reasons.  Please instead spell out the default action, or "
-           "assign the default action to an Action variable and use "
-           "the variable in various places.");
-    return internal::Invalid<Result>();
-    // The above statement will never be reached, but is required in
-    // order for this function to compile.
-  }
-};
-
 // Implements the polymorphic DoDefault() action.
 class DoDefaultAction {
  public:
   // This template type conversion operator allows DoDefault() to be
   // used in any function.
   template <typename F>
-  operator Action<F>() const {
-    return Action<F>(new MonomorphicDoDefaultActionImpl<F>);
-  }
+  operator Action<F>() const { return Action<F>(NULL); }
 };
 
 // Implements the Assign action to set a given pointer referent to a
diff --git a/include/gmock/gmock-generated-function-mockers.h b/include/gmock/gmock-generated-function-mockers.h
index 7b334e42..509d46cb 100644
--- a/include/gmock/gmock-generated-function-mockers.h
+++ b/include/gmock/gmock-generated-function-mockers.h
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+//     pump.py gmock-generated-function-mockers.h.pump
+// DO NOT EDIT BY HAND!!!
 
 // Copyright 2007, Google Inc.
 // All rights reserved.
@@ -352,7 +354,8 @@ using internal::FunctionMocker;
   } \
   ::testing::MockSpec<F>& \
       gmock_##Method() constness { \
-    return GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this).With(); \
+    GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(0, constness, Method).With(); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(0, constness, Method)
 
@@ -367,8 +370,8 @@ using internal::FunctionMocker;
   } \
   ::testing::MockSpec<F>& \
       gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1) constness { \
-    return GMOCK_MOCKER_(1, constness, \
-        Method).RegisterOwner(this).With(gmock_a1); \
+    GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(1, constness, Method)
 
@@ -385,8 +388,8 @@ using internal::FunctionMocker;
   ::testing::MockSpec<F>& \
       gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
                      GMOCK_MATCHER_(tn, F, 2) gmock_a2) constness { \
-    return GMOCK_MOCKER_(2, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2); \
+    GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(2, constness, Method)
 
@@ -406,8 +409,9 @@ using internal::FunctionMocker;
       gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
                      GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
                      GMOCK_MATCHER_(tn, F, 3) gmock_a3) constness { \
-    return GMOCK_MOCKER_(3, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3); \
+    GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(3, constness, Method)
 
@@ -429,9 +433,9 @@ using internal::FunctionMocker;
                      GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
                      GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
                      GMOCK_MATCHER_(tn, F, 4) gmock_a4) constness { \
-    return GMOCK_MOCKER_(4, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
-        gmock_a4); \
+    GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(4, constness, Method)
 
@@ -455,9 +459,9 @@ using internal::FunctionMocker;
                      GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
                      GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
                      GMOCK_MATCHER_(tn, F, 5) gmock_a5) constness { \
-    return GMOCK_MOCKER_(5, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
-        gmock_a4, gmock_a5); \
+    GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(5, constness, Method)
 
@@ -483,9 +487,9 @@ using internal::FunctionMocker;
                      GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
                      GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
                      GMOCK_MATCHER_(tn, F, 6) gmock_a6) constness { \
-    return GMOCK_MOCKER_(6, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
-        gmock_a4, gmock_a5, gmock_a6); \
+    GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(6, constness, Method)
 
@@ -513,9 +517,9 @@ using internal::FunctionMocker;
                      GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
                      GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
                      GMOCK_MATCHER_(tn, F, 7) gmock_a7) constness { \
-    return GMOCK_MOCKER_(7, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
-        gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+    GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(7, constness, Method)
 
@@ -545,9 +549,9 @@ using internal::FunctionMocker;
                      GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
                      GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
                      GMOCK_MATCHER_(tn, F, 8) gmock_a8) constness { \
-    return GMOCK_MOCKER_(8, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
-        gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+    GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(8, constness, Method)
 
@@ -580,9 +584,10 @@ using internal::FunctionMocker;
                      GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
                      GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
                      GMOCK_MATCHER_(tn, F, 9) gmock_a9) constness { \
-    return GMOCK_MOCKER_(9, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
-        gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9); \
+    GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+        gmock_a9); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(9, constness, Method)
 
@@ -617,9 +622,9 @@ using internal::FunctionMocker;
                      GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
                      GMOCK_MATCHER_(tn, F, 9) gmock_a9, \
                      GMOCK_MATCHER_(tn, F, 10) gmock_a10) constness { \
-    return GMOCK_MOCKER_(10, constness, \
-        Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
-        gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+    GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
         gmock_a10); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(10, constness, Method)
diff --git a/include/gmock/gmock-generated-function-mockers.h.pump b/include/gmock/gmock-generated-function-mockers.h.pump
index 50b369bb..4f82d622 100644
--- a/include/gmock/gmock-generated-function-mockers.h.pump
+++ b/include/gmock/gmock-generated-function-mockers.h.pump
@@ -140,7 +140,8 @@ $var matcher_as = [[$for j, \
   } \
   ::testing::MockSpec<F>& \
       gmock_##Method($matcher_as) constness { \
-    return GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this).With($as); \
+    GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_($i, constness, Method).With($as); \
   } \
   mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_($i, constness, Method)
 
diff --git a/include/gmock/gmock-spec-builders.h b/include/gmock/gmock-spec-builders.h
index 4f0b0725..9e185085 100644
--- a/include/gmock/gmock-spec-builders.h
+++ b/include/gmock/gmock-spec-builders.h
@@ -113,53 +113,190 @@ template <typename F> class FunctionMockerBase;
 // calls to ensure the integrity of the mock objects' states.
 GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex);
 
+// Untyped base class for ActionResultHolder<R>.
+class UntypedActionResultHolderBase;
+
 // Abstract base class of FunctionMockerBase.  This is the
 // type-agnostic part of the function mocker interface.  Its pure
 // virtual methods are implemented by FunctionMockerBase.
 class UntypedFunctionMockerBase {
  public:
-  virtual ~UntypedFunctionMockerBase() {}
+  UntypedFunctionMockerBase();
+  virtual ~UntypedFunctionMockerBase();
 
   // Verifies that all expectations on this mock function have been
   // satisfied.  Reports one or more Google Test non-fatal failures
   // and returns false if not.
   // L >= g_gmock_mutex
-  virtual bool VerifyAndClearExpectationsLocked() = 0;
+  bool VerifyAndClearExpectationsLocked();
 
   // Clears the ON_CALL()s set on this mock function.
   // L >= g_gmock_mutex
   virtual void ClearDefaultActionsLocked() = 0;
+
+  // In all of the following Untyped* functions, it's the caller's
+  // responsibility to guarantee the correctness of the arguments'
+  // types.
+
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,
+      const string& call_description) const = 0;
+
+  // Performs the given action with the given arguments and returns
+  // the action's result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action,
+      const void* untyped_args) const = 0;
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  // L < g_gmock_mutex
+  virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                                ::std::ostream* os) const = 0;
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  // L < g_gmock_mutex
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why) = 0;
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const = 0;
+
+  // Sets the mock object this mock method belongs to, and registers
+  // this information in the global mock registry.  Will be called
+  // whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+  // method.
+  // TODO(wan@google.com): rename to SetAndRegisterOwner().
+  // L < g_gmock_mutex
+  void RegisterOwner(const void* mock_obj);
+
+  // Sets the mock object this mock method belongs to, and sets the
+  // name of the mock function.  Will be called upon each invocation
+  // of this mock function.
+  // L < g_gmock_mutex
+  void SetOwnerAndName(const void* mock_obj, const char* name);
+
+  // Returns the mock object this mock method belongs to.  Must be
+  // called after RegisterOwner() or SetOwnerAndName() has been
+  // called.
+  // L < g_gmock_mutex
+  const void* MockObject() const;
+
+  // Returns the name of this mock method.  Must be called after
+  // SetOwnerAndName() has been called.
+  // L < g_gmock_mutex
+  const char* Name() const;
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.  The caller is responsible for deleting the
+  // result.
+  // L < g_gmock_mutex
+  const UntypedActionResultHolderBase* UntypedInvokeWith(
+      const void* untyped_args);
+
+ protected:
+  typedef std::vector<const void*> UntypedOnCallSpecs;
+
+  typedef std::vector<internal::linked_ptr<ExpectationBase> >
+  UntypedExpectations;
+
+  // Returns an Expectation object that references and co-owns exp,
+  // which must be an expectation on this mock function.
+  Expectation GetHandleOf(ExpectationBase* exp);
+
+  // Address of the mock object this mock method belongs to.  Only
+  // valid after this mock method has been called or
+  // ON_CALL/EXPECT_CALL has been invoked on it.
+  const void* mock_obj_;  // Protected by g_gmock_mutex.
+
+  // Name of the function being mocked.  Only valid after this mock
+  // method has been called.
+  const char* name_;  // Protected by g_gmock_mutex.
+
+  // All default action specs for this function mocker.
+  UntypedOnCallSpecs untyped_on_call_specs_;
+
+  // All expectations for this function mocker.
+  UntypedExpectations untyped_expectations_;
 };  // class UntypedFunctionMockerBase
 
-// This template class implements a default action spec (i.e. an
-// ON_CALL() statement).
-template <typename F>
-class DefaultActionSpec {
+// Untyped base class for OnCallSpec<F>.
+class UntypedOnCallSpecBase {
  public:
-  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
-  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
-
-  // Constructs a DefaultActionSpec object from the information inside
-  // the parenthesis of an ON_CALL() statement.
-  DefaultActionSpec(const char* a_file, int a_line,
-                    const ArgumentMatcherTuple& matchers)
-      : file_(a_file),
-        line_(a_line),
-        matchers_(matchers),
-        // By default, extra_matcher_ should match anything.  However,
-        // we cannot initialize it with _ as that triggers a compiler
-        // bug in Symbian's C++ compiler (cannot decide between two
-        // overloaded constructors of Matcher<const ArgumentTuple&>).
-        extra_matcher_(A<const ArgumentTuple&>()),
-        last_clause_(kNone) {
-  }
+  // The arguments are the location of the ON_CALL() statement.
+  UntypedOnCallSpecBase(const char* a_file, int a_line)
+      : file_(a_file), line_(a_line), last_clause_(kNone) {}
 
   // Where in the source file was the default action spec defined?
   const char* file() const { return file_; }
   int line() const { return line_; }
 
+ protected:
+  // Gives each clause in the ON_CALL() statement a name.
+  enum Clause {
+    // Do not change the order of the enum members!  The run-time
+    // syntax checking relies on it.
+    kNone,
+    kWith,
+    kWillByDefault,
+  };
+
+  // Asserts that the ON_CALL() statement has a certain property.
+  void AssertSpecProperty(bool property, const string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the ON_CALL() statement has a certain property.
+  void ExpectSpecProperty(bool property, const string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  const char* file_;
+  int line_;
+
+  // The last clause in the ON_CALL() statement as seen so far.
+  // Initially kNone and changes as the statement is parsed.
+  Clause last_clause_;
+};  // class UntypedOnCallSpecBase
+
+// This template class implements an ON_CALL spec.
+template <typename F>
+class OnCallSpec : public UntypedOnCallSpecBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  // Constructs an OnCallSpec object from the information inside
+  // the parenthesis of an ON_CALL() statement.
+  OnCallSpec(const char* a_file, int a_line,
+             const ArgumentMatcherTuple& matchers)
+      : UntypedOnCallSpecBase(a_file, a_line),
+        matchers_(matchers),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that triggers a compiler
+        // bug in Symbian's C++ compiler (cannot decide between two
+        // overloaded constructors of Matcher<const ArgumentTuple&>).
+        extra_matcher_(A<const ArgumentTuple&>()) {
+  }
+
   // Implements the .With() clause.
-  DefaultActionSpec& With(const Matcher<const ArgumentTuple&>& m) {
+  OnCallSpec& With(const Matcher<const ArgumentTuple&>& m) {
     // Makes sure this is called at most once.
     ExpectSpecProperty(last_clause_ < kWith,
                        ".With() cannot appear "
@@ -171,7 +308,7 @@ class DefaultActionSpec {
   }
 
   // Implements the .WillByDefault() clause.
-  DefaultActionSpec& WillByDefault(const Action<F>& action) {
+  OnCallSpec& WillByDefault(const Action<F>& action) {
     ExpectSpecProperty(last_clause_ < kWillByDefault,
                        ".WillByDefault() must appear "
                        "exactly once in an ON_CALL().");
@@ -197,25 +334,6 @@ class DefaultActionSpec {
   }
 
  private:
-  // Gives each clause in the ON_CALL() statement a name.
-  enum Clause {
-    // Do not change the order of the enum members!  The run-time
-    // syntax checking relies on it.
-    kNone,
-    kWith,
-    kWillByDefault,
-  };
-
-  // Asserts that the ON_CALL() statement has a certain property.
-  void AssertSpecProperty(bool property, const string& failure_message) const {
-    Assert(property, file_, line_, failure_message);
-  }
-
-  // Expects that the ON_CALL() statement has a certain property.
-  void ExpectSpecProperty(bool property, const string& failure_message) const {
-    Expect(property, file_, line_, failure_message);
-  }
-
   // The information in statement
   //
   //   ON_CALL(mock_object, Method(matchers))
@@ -229,16 +347,10 @@ class DefaultActionSpec {
   //   matchers                                => matchers_
   //   multi-argument-matcher                  => extra_matcher_
   //   action                                  => action_
-  const char* file_;
-  int line_;
   ArgumentMatcherTuple matchers_;
   Matcher<const ArgumentTuple&> extra_matcher_;
   Action<F> action_;
-
-  // The last clause in the ON_CALL() statement as seen so far.
-  // Initially kNone and changes as the statement is parsed.
-  Clause last_clause_;
-};  // class DefaultActionSpec
+};  // class OnCallSpec
 
 // Possible reactions on uninteresting calls.  TODO(wan@google.com):
 // rename the enum values to the kFoo style.
@@ -269,6 +381,8 @@ class Mock {
   // verification was successful.
   static bool VerifyAndClear(void* mock_obj);
  private:
+  friend class internal::UntypedFunctionMockerBase;
+
   // Needed for a function mocker to register itself (so that we know
   // how to clear a mock object).
   template <typename F>
@@ -389,6 +503,7 @@ class Expectation {
   friend class ExpectationSet;
   friend class Sequence;
   friend class ::testing::internal::ExpectationBase;
+  friend class ::testing::internal::UntypedFunctionMockerBase;
 
   template <typename F>
   friend class ::testing::internal::FunctionMockerBase;
@@ -581,10 +696,15 @@ class ExpectationBase {
   // Describes how many times a function call matching this
   // expectation has occurred.
   // L >= g_gmock_mutex
-  virtual void DescribeCallCountTo(::std::ostream* os) const = 0;
+  void DescribeCallCountTo(::std::ostream* os) const;
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) = 0;
 
  protected:
   friend class ::testing::Expectation;
+  friend class UntypedFunctionMockerBase;
 
   enum Clause {
     // Don't change the order of the enum members!
@@ -598,6 +718,8 @@ class ExpectationBase {
     kRetiresOnSaturation,
   };
 
+  typedef std::vector<const void*> UntypedActions;
+
   // Returns an Expectation object that references and co-owns this
   // expectation.
   virtual Expectation GetHandle() = 0;
@@ -690,13 +812,22 @@ class ExpectationBase {
     call_count_++;
   }
 
- private:
+  // Checks the action count (i.e. the number of WillOnce() and
+  // WillRepeatedly() clauses) against the cardinality if this hasn't
+  // been done before.  Prints a warning if there are too many or too
+  // few actions.
+  // L < mutex_
+  void CheckActionCountIfNotDone() const;
+
   friend class ::testing::Sequence;
   friend class ::testing::internal::ExpectationTester;
 
   template <typename Function>
   friend class TypedExpectation;
 
+  // Implements the .Times() clause.
+  void UntypedTimes(const Cardinality& a_cardinality);
+
   // This group of fields are part of the spec and won't change after
   // an EXPECT_CALL() statement finishes.
   const char* file_;          // The file that contains the expectation.
@@ -717,6 +848,13 @@ class ExpectationBase {
   // and can change as the mock function is called.
   int call_count_;  // How many times this expectation has been invoked.
   bool retired_;    // True iff this expectation has retired.
+  UntypedActions untyped_actions_;
+  bool extra_matcher_specified_;
+  bool repeated_action_specified_;  // True if a WillRepeatedly() was specified.
+  bool retires_on_saturation_;
+  Clause last_clause_;
+  mutable bool action_count_checked_;  // Under mutex_.
+  mutable Mutex mutex_;  // Protects action_count_checked_.
 
   GTEST_DISALLOW_ASSIGN_(ExpectationBase);
 };  // class ExpectationBase
@@ -735,22 +873,21 @@ class TypedExpectation : public ExpectationBase {
       : ExpectationBase(a_file, a_line, a_source_text),
         owner_(owner),
         matchers_(m),
-        extra_matcher_specified_(false),
         // By default, extra_matcher_ should match anything.  However,
         // we cannot initialize it with _ as that triggers a compiler
         // bug in Symbian's C++ compiler (cannot decide between two
         // overloaded constructors of Matcher<const ArgumentTuple&>).
         extra_matcher_(A<const ArgumentTuple&>()),
-        repeated_action_specified_(false),
-        repeated_action_(DoDefault()),
-        retires_on_saturation_(false),
-        last_clause_(kNone),
-        action_count_checked_(false) {}
+        repeated_action_(DoDefault()) {}
 
   virtual ~TypedExpectation() {
     // Check the validity of the action count if it hasn't been done
     // yet (for example, if the expectation was never used).
     CheckActionCountIfNotDone();
+    for (UntypedActions::const_iterator it = untyped_actions_.begin();
+         it != untyped_actions_.end(); ++it) {
+      delete static_cast<const Action<F>*>(*it);
+    }
   }
 
   // Implements the .With() clause.
@@ -773,19 +910,7 @@ class TypedExpectation : public ExpectationBase {
 
   // Implements the .Times() clause.
   TypedExpectation& Times(const Cardinality& a_cardinality) {
-    if (last_clause_ ==kTimes) {
-      ExpectSpecProperty(false,
-                         ".Times() cannot appear "
-                         "more than once in an EXPECT_CALL().");
-    } else {
-      ExpectSpecProperty(last_clause_ < kTimes,
-                         ".Times() cannot appear after "
-                         ".InSequence(), .WillOnce(), .WillRepeatedly(), "
-                         "or .RetiresOnSaturation().");
-    }
-    last_clause_ = kTimes;
-
-    ExpectationBase::SpecifyCardinality(a_cardinality);
+    ExpectationBase::UntypedTimes(a_cardinality);
     return *this;
   }
 
@@ -859,9 +984,9 @@ class TypedExpectation : public ExpectationBase {
                        ".WillRepeatedly() or .RetiresOnSaturation().");
     last_clause_ = kWillOnce;
 
-    actions_.push_back(action);
+    untyped_actions_.push_back(new Action<F>(action));
     if (!cardinality_specified()) {
-      set_cardinality(Exactly(static_cast<int>(actions_.size())));
+      set_cardinality(Exactly(static_cast<int>(untyped_actions_.size())));
     }
     return *this;
   }
@@ -882,7 +1007,7 @@ class TypedExpectation : public ExpectationBase {
 
     repeated_action_ = action;
     if (!cardinality_specified()) {
-      set_cardinality(AtLeast(static_cast<int>(actions_.size())));
+      set_cardinality(AtLeast(static_cast<int>(untyped_actions_.size())));
     }
 
     // Now that no more action clauses can be specified, we check
@@ -916,38 +1041,12 @@ class TypedExpectation : public ExpectationBase {
     return extra_matcher_;
   }
 
-  // Returns the sequence of actions specified by the .WillOnce() clause.
-  const std::vector<Action<F> >& actions() const { return actions_; }
-
   // Returns the action specified by the .WillRepeatedly() clause.
   const Action<F>& repeated_action() const { return repeated_action_; }
 
-  // Returns true iff the .RetiresOnSaturation() clause was specified.
-  bool retires_on_saturation() const { return retires_on_saturation_; }
-
-  // Describes how many times a function call matching this
-  // expectation has occurred (implements
-  // ExpectationBase::DescribeCallCountTo()).
-  // L >= g_gmock_mutex
-  virtual void DescribeCallCountTo(::std::ostream* os) const {
-    g_gmock_mutex.AssertHeld();
-
-    // Describes how many times the function is expected to be called.
-    *os << "         Expected: to be ";
-    cardinality().DescribeTo(os);
-    *os << "\n           Actual: ";
-    Cardinality::DescribeActualCallCountTo(call_count(), os);
-
-    // Describes the state of the expectation (e.g. is it satisfied?
-    // is it active?).
-    *os << " - " << (IsOverSaturated() ? "over-saturated" :
-                     IsSaturated() ? "saturated" :
-                     IsSatisfied() ? "satisfied" : "unsatisfied")
-        << " and "
-        << (is_retired() ? "retired" : "active");
-  }
-
-  void MaybeDescribeExtraMatcherTo(::std::ostream* os) {
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) {
     if (extra_matcher_specified_) {
       *os << "    Expected args: ";
       extra_matcher_.DescribeTo(os);
@@ -1044,7 +1143,7 @@ class TypedExpectation : public ExpectationBase {
            "call_count() is <= 0 when GetCurrentAction() is "
            "called - this should never happen.");
 
-    const int action_count = static_cast<int>(actions().size());
+    const int action_count = static_cast<int>(untyped_actions_.size());
     if (action_count > 0 && !repeated_action_specified_ &&
         count > action_count) {
       // If there is at least one WillOnce() and no WillRepeatedly(),
@@ -1059,7 +1158,9 @@ class TypedExpectation : public ExpectationBase {
       Log(WARNING, ss.str(), 1);
     }
 
-    return count <= action_count ? actions()[count - 1] : repeated_action();
+    return count <= action_count ?
+        *static_cast<const Action<F>*>(untyped_actions_[count - 1]) :
+        repeated_action();
   }
 
   // Given the arguments of a mock function call, if the call will
@@ -1067,12 +1168,13 @@ class TypedExpectation : public ExpectationBase {
   // otherwise, returns the next action in this expectation.  Also
   // describes *what* happened to 'what', and explains *why* Google
   // Mock does it to 'why'.  This method is not const as it calls
-  // IncrementCallCount().
+  // IncrementCallCount().  A return value of NULL means the default
+  // action.
   // L >= g_gmock_mutex
-  Action<F> GetActionForArguments(const FunctionMockerBase<F>* mocker,
-                                  const ArgumentTuple& args,
-                                  ::std::ostream* what,
-                                  ::std::ostream* why) {
+  const Action<F>* GetActionForArguments(const FunctionMockerBase<F>* mocker,
+                                         const ArgumentTuple& args,
+                                         ::std::ostream* what,
+                                         ::std::ostream* why) {
     g_gmock_mutex.AssertHeld();
     if (IsSaturated()) {
       // We have an excessive call.
@@ -1081,92 +1183,30 @@ class TypedExpectation : public ExpectationBase {
       mocker->DescribeDefaultActionTo(args, what);
       DescribeCallCountTo(why);
 
-      // TODO(wan): allow the user to control whether unexpected calls
-      // should fail immediately or continue using a flag
-      // --gmock_unexpected_calls_are_fatal.
-      return DoDefault();
+      // TODO(wan@google.com): allow the user to control whether
+      // unexpected calls should fail immediately or continue using a
+      // flag --gmock_unexpected_calls_are_fatal.
+      return NULL;
     }
 
     IncrementCallCount();
     RetireAllPreRequisites();
 
-    if (retires_on_saturation() && IsSaturated()) {
+    if (retires_on_saturation_ && IsSaturated()) {
       Retire();
     }
 
     // Must be done after IncrementCount()!
     *what << "Mock function call matches " << source_text() <<"...\n";
-    return GetCurrentAction(mocker, args);
-  }
-
-  // Checks the action count (i.e. the number of WillOnce() and
-  // WillRepeatedly() clauses) against the cardinality if this hasn't
-  // been done before.  Prints a warning if there are too many or too
-  // few actions.
-  // L < mutex_
-  void CheckActionCountIfNotDone() const {
-    bool should_check = false;
-    {
-      MutexLock l(&mutex_);
-      if (!action_count_checked_) {
-        action_count_checked_ = true;
-        should_check = true;
-      }
-    }
-
-    if (should_check) {
-      if (!cardinality_specified_) {
-        // The cardinality was inferred - no need to check the action
-        // count against it.
-        return;
-      }
-
-      // The cardinality was explicitly specified.
-      const int action_count = static_cast<int>(actions_.size());
-      const int upper_bound = cardinality().ConservativeUpperBound();
-      const int lower_bound = cardinality().ConservativeLowerBound();
-      bool too_many;  // True if there are too many actions, or false
-                      // if there are too few.
-      if (action_count > upper_bound ||
-          (action_count == upper_bound && repeated_action_specified_)) {
-        too_many = true;
-      } else if (0 < action_count && action_count < lower_bound &&
-                 !repeated_action_specified_) {
-        too_many = false;
-      } else {
-        return;
-      }
-
-      ::std::stringstream ss;
-      DescribeLocationTo(&ss);
-      ss << "Too " << (too_many ? "many" : "few")
-         << " actions specified in " << source_text() << "...\n"
-         << "Expected to be ";
-      cardinality().DescribeTo(&ss);
-      ss << ", but has " << (too_many ? "" : "only ")
-         << action_count << " WillOnce()"
-         << (action_count == 1 ? "" : "s");
-      if (repeated_action_specified_) {
-        ss << " and a WillRepeatedly()";
-      }
-      ss << ".";
-      Log(WARNING, ss.str(), -1);  // -1 means "don't print stack trace".
-    }
+    return &(GetCurrentAction(mocker, args));
   }
 
   // All the fields below won't change once the EXPECT_CALL()
   // statement finishes.
   FunctionMockerBase<F>* const owner_;
   ArgumentMatcherTuple matchers_;
-  bool extra_matcher_specified_;
   Matcher<const ArgumentTuple&> extra_matcher_;
-  std::vector<Action<F> > actions_;
-  bool repeated_action_specified_;  // True if a WillRepeatedly() was specified.
   Action<F> repeated_action_;
-  bool retires_on_saturation_;
-  Clause last_clause_;
-  mutable bool action_count_checked_;  // Under mutex_.
-  mutable Mutex mutex_;  // Protects action_count_checked_.
 
   GTEST_DISALLOW_COPY_AND_ASSIGN_(TypedExpectation);
 };  // class TypedExpectation
@@ -1181,6 +1221,11 @@ class TypedExpectation : public ExpectationBase {
 // template.  To workaround this compiler bug, we define MockSpec in
 // ::testing::internal and import it into ::testing.
 
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+                     const char* file, int line,
+                     const string& message);
+
 template <typename F>
 class MockSpec {
  public:
@@ -1195,11 +1240,11 @@ class MockSpec {
 
   // Adds a new default action spec to the function mocker and returns
   // the newly created spec.
-  internal::DefaultActionSpec<F>& InternalDefaultActionSetAt(
+  internal::OnCallSpec<F>& InternalDefaultActionSetAt(
       const char* file, int line, const char* obj, const char* call) {
     LogWithLocation(internal::INFO, file, line,
         string("ON_CALL(") + obj + ", " + call + ") invoked");
-    return function_mocker_->AddNewDefaultActionSpec(file, line, matchers_);
+    return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
   }
 
   // Adds a new expectation spec to the function mocker and returns
@@ -1220,15 +1265,6 @@ class MockSpec {
     matchers_ = matchers;
   }
 
-  // Logs a message including file and line number information.
-  void LogWithLocation(testing::internal::LogSeverity severity,
-                       const char* file, int line,
-                       const string& message) {
-    ::std::ostringstream s;
-    s << file << ":" << line << ": " << message << ::std::endl;
-    Log(severity, s.str(), 0);
-  }
-
   // The function mocker that owns this spec.
   internal::FunctionMockerBase<F>* const function_mocker_;
   // The argument matchers specified in the spec.
@@ -1253,42 +1289,58 @@ class MockSpec {
 // copyable type or void (T doesn't need to be default-constructable).
 // It hides the syntactic difference between void and other types, and
 // is used to unify the code for invoking both void-returning and
-// non-void-returning mock functions.  This generic definition is used
-// when T is not void.
+// non-void-returning mock functions.
+
+// Untyped base class for ActionResultHolder<T>.
+class UntypedActionResultHolderBase {
+ public:
+  virtual ~UntypedActionResultHolderBase() {}
+
+  // Prints the held value as an action's result to os.
+  virtual void PrintAsActionResult(::std::ostream* os) const = 0;
+};
+
+// This generic definition is used when T is not void.
 template <typename T>
-class ActionResultHolder {
+class ActionResultHolder : public UntypedActionResultHolderBase {
  public:
   explicit ActionResultHolder(T a_value) : value_(a_value) {}
 
   // The compiler-generated copy constructor and assignment operator
   // are exactly what we need, so we don't need to define them.
 
-  T value() const { return value_; }
+  // Returns the held value and deletes this object.
+  T GetValueAndDelete() const {
+    T retval(value_);
+    delete this;
+    return retval;
+  }
 
   // Prints the held value as an action's result to os.
-  void PrintAsActionResult(::std::ostream* os) const {
+  virtual void PrintAsActionResult(::std::ostream* os) const {
     *os << "\n          Returns: ";
     // T may be a reference type, so we don't use UniversalPrint().
     UniversalPrinter<T>::Print(value_, os);
   }
 
   // Performs the given mock function's default action and returns the
-  // result in a ActionResultHolder.
-  template <typename Function, typename Arguments>
-  static ActionResultHolder PerformDefaultAction(
-      const FunctionMockerBase<Function>* func_mocker,
-      const Arguments& args,
+  // result in a new-ed ActionResultHolder.
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
       const string& call_description) {
-    return ActionResultHolder(
+    return new ActionResultHolder(
         func_mocker->PerformDefaultAction(args, call_description));
   }
 
-  // Performs the given action and returns the result in a
+  // Performs the given action and returns the result in a new-ed
   // ActionResultHolder.
-  template <typename Function, typename Arguments>
-  static ActionResultHolder PerformAction(const Action<Function>& action,
-                                          const Arguments& args) {
-    return ActionResultHolder(action.Perform(args));
+  template <typename F>
+  static ActionResultHolder*
+  PerformAction(const Action<F>& action,
+                const typename Function<F>::ArgumentTuple& args) {
+    return new ActionResultHolder(action.Perform(args));
   }
 
  private:
@@ -1300,26 +1352,29 @@ class ActionResultHolder {
 
 // Specialization for T = void.
 template <>
-class ActionResultHolder<void> {
+class ActionResultHolder<void> : public UntypedActionResultHolderBase {
  public:
-  ActionResultHolder() {}
-  void value() const {}
-  void PrintAsActionResult(::std::ostream* /* os */) const {}
+  void GetValueAndDelete() const { delete this; }
 
-  template <typename Function, typename Arguments>
-  static ActionResultHolder PerformDefaultAction(
-      const FunctionMockerBase<Function>* func_mocker,
-      const Arguments& args,
+  virtual void PrintAsActionResult(::std::ostream* /* os */) const {}
+
+  // Performs the given mock function's default action and returns NULL;
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
       const string& call_description) {
     func_mocker->PerformDefaultAction(args, call_description);
-    return ActionResultHolder();
+    return NULL;
   }
 
-  template <typename Function, typename Arguments>
-  static ActionResultHolder PerformAction(const Action<Function>& action,
-                                          const Arguments& args) {
+  // Performs the given action and returns NULL.
+  template <typename F>
+  static ActionResultHolder* PerformAction(
+      const Action<F>& action,
+      const typename Function<F>::ArgumentTuple& args) {
     action.Perform(args);
-    return ActionResultHolder();
+    return NULL;
   }
 };
 
@@ -1333,7 +1388,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
   typedef typename Function<F>::ArgumentTuple ArgumentTuple;
   typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
 
-  FunctionMockerBase() : mock_obj_(NULL), name_(""), current_spec_(this) {}
+  FunctionMockerBase() : current_spec_(this) {}
 
   // The destructor verifies that all expectations on this mock
   // function have been satisfied.  If not, it will report Google Test
@@ -1343,19 +1398,20 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
     MutexLock l(&g_gmock_mutex);
     VerifyAndClearExpectationsLocked();
     Mock::UnregisterLocked(this);
+    ClearDefaultActionsLocked();
   }
 
   // Returns the ON_CALL spec that matches this mock function with the
   // given arguments; returns NULL if no matching ON_CALL is found.
   // L = *
-  const DefaultActionSpec<F>* FindDefaultActionSpec(
+  const OnCallSpec<F>* FindOnCallSpec(
       const ArgumentTuple& args) const {
-    for (typename std::vector<DefaultActionSpec<F> >::const_reverse_iterator it
-             = default_actions_.rbegin();
-         it != default_actions_.rend(); ++it) {
-      const DefaultActionSpec<F>& spec = *it;
-      if (spec.Matches(args))
-        return &spec;
+    for (UntypedOnCallSpecs::const_reverse_iterator it
+             = untyped_on_call_specs_.rbegin();
+         it != untyped_on_call_specs_.rend(); ++it) {
+      const OnCallSpec<F>* spec = static_cast<const OnCallSpec<F>*>(*it);
+      if (spec->Matches(args))
+        return spec;
     }
 
     return NULL;
@@ -1368,7 +1424,8 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
   // L = *
   Result PerformDefaultAction(const ArgumentTuple& args,
                               const string& call_description) const {
-    const DefaultActionSpec<F>* const spec = FindDefaultActionSpec(args);
+    const OnCallSpec<F>* const spec =
+        this->FindOnCallSpec(args);
     if (spec != NULL) {
       return spec->GetAction().Perform(args);
     }
@@ -1378,91 +1435,70 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
     return DefaultValue<Result>::Get();
   }
 
-  // Registers this function mocker and the mock object owning it;
-  // returns a reference to the function mocker object.  This is only
-  // called by the ON_CALL() and EXPECT_CALL() macros.
-  // L < g_gmock_mutex
-  FunctionMocker<F>& RegisterOwner(const void* mock_obj) {
-    {
-      MutexLock l(&g_gmock_mutex);
-      mock_obj_ = mock_obj;
-    }
-    Mock::Register(mock_obj, this);
-    return *::testing::internal::DownCast_<FunctionMocker<F>*>(this);
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.  The caller is responsible for deleting the result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,  // must point to an ArgumentTuple
+      const string& call_description) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformDefaultAction(this, args, call_description);
   }
 
-  // The following two functions are from UntypedFunctionMockerBase.
+  // Performs the given action with the given arguments and returns
+  // the action's result.  The caller is responsible for deleting the
+  // result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action, const void* untyped_args) const {
+    // Make a copy of the action before performing it, in case the
+    // action deletes the mock object (and thus deletes itself).
+    const Action<F> action = *static_cast<const Action<F>*>(untyped_action);
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformAction(action, args);
+  }
 
-  // Verifies that all expectations on this mock function have been
-  // satisfied.  Reports one or more Google Test non-fatal failures
-  // and returns false if not.
-  // L >= g_gmock_mutex
-  virtual bool VerifyAndClearExpectationsLocked();
-
-  // Clears the ON_CALL()s set on this mock function.
+  // Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
+  // clears the ON_CALL()s set on this mock function.
   // L >= g_gmock_mutex
   virtual void ClearDefaultActionsLocked() {
     g_gmock_mutex.AssertHeld();
-    default_actions_.clear();
-  }
-
-  // Sets the name of the function being mocked.  Will be called upon
-  // each invocation of this mock function.
-  // L < g_gmock_mutex
-  void SetOwnerAndName(const void* mock_obj, const char* name) {
-    // We protect name_ under g_gmock_mutex in case this mock function
-    // is called from two threads concurrently.
-    MutexLock l(&g_gmock_mutex);
-    mock_obj_ = mock_obj;
-    name_ = name;
-  }
-
-  // Returns the address of the mock object this method belongs to.
-  // Must be called after SetOwnerAndName() has been called.
-  // L < g_gmock_mutex
-  const void* MockObject() const {
-    const void* mock_obj;
-    {
-      // We protect mock_obj_ under g_gmock_mutex in case this mock
-      // function is called from two threads concurrently.
-      MutexLock l(&g_gmock_mutex);
-      mock_obj = mock_obj_;
+    for (UntypedOnCallSpecs::const_iterator it =
+             untyped_on_call_specs_.begin();
+         it != untyped_on_call_specs_.end(); ++it) {
+      delete static_cast<const OnCallSpec<F>*>(*it);
     }
-    return mock_obj;
-  }
-
-  // Returns the name of the function being mocked.  Must be called
-  // after SetOwnerAndName() has been called.
-  // L < g_gmock_mutex
-  const char* Name() const {
-    const char* name;
-    {
-      // We protect name_ under g_gmock_mutex in case this mock
-      // function is called from two threads concurrently.
-      MutexLock l(&g_gmock_mutex);
-      name = name_;
-    }
-    return name;
+    untyped_on_call_specs_.clear();
   }
 
  protected:
   template <typename Function>
   friend class MockSpec;
 
+  typedef ActionResultHolder<Result> ResultHolder;
+
   // Returns the result of invoking this mock function with the given
   // arguments.  This function can be safely called from multiple
   // threads concurrently.
   // L < g_gmock_mutex
-  Result InvokeWith(const ArgumentTuple& args);
+  Result InvokeWith(const ArgumentTuple& args) {
+    return static_cast<const ResultHolder*>(
+        this->UntypedInvokeWith(&args))->GetValueAndDelete();
+  }
 
   // Adds and returns a default action spec for this mock function.
   // L < g_gmock_mutex
-  DefaultActionSpec<F>& AddNewDefaultActionSpec(
+  OnCallSpec<F>& AddNewOnCallSpec(
       const char* file, int line,
       const ArgumentMatcherTuple& m) {
     Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
-    default_actions_.push_back(DefaultActionSpec<F>(file, line, m));
-    return default_actions_.back();
+    OnCallSpec<F>* const on_call_spec = new OnCallSpec<F>(file, line, m);
+    untyped_on_call_specs_.push_back(on_call_spec);
+    return *on_call_spec;
   }
 
   // Adds and returns an expectation spec for this mock function.
@@ -1473,14 +1509,15 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
       const string& source_text,
       const ArgumentMatcherTuple& m) {
     Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
-    const linked_ptr<TypedExpectation<F> > expectation(
-        new TypedExpectation<F>(this, file, line, source_text, m));
-    expectations_.push_back(expectation);
+    TypedExpectation<F>* const expectation =
+        new TypedExpectation<F>(this, file, line, source_text, m);
+    const linked_ptr<ExpectationBase> untyped_expectation(expectation);
+    untyped_expectations_.push_back(untyped_expectation);
 
     // Adds this expectation into the implicit sequence if there is one.
     Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
     if (implicit_sequence != NULL) {
-      implicit_sequence->AddExpectation(Expectation(expectation));
+      implicit_sequence->AddExpectation(Expectation(untyped_expectation));
     }
 
     return *expectation;
@@ -1493,33 +1530,14 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
  private:
   template <typename Func> friend class TypedExpectation;
 
-  typedef std::vector<internal::linked_ptr<TypedExpectation<F> > >
-  TypedExpectations;
-
-  // Returns an Expectation object that references and co-owns exp,
-  // which must be an expectation on this mock function.
-  Expectation GetHandleOf(TypedExpectation<F>* exp) {
-    for (typename TypedExpectations::const_iterator it = expectations_.begin();
-         it != expectations_.end(); ++it) {
-      if (it->get() == exp) {
-        return Expectation(*it);
-      }
-    }
-
-    Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
-    return Expectation();
-    // The above statement is just to make the code compile, and will
-    // never be executed.
-  }
-
-  // Some utilities needed for implementing InvokeWith().
+  // Some utilities needed for implementing UntypedInvokeWith().
 
   // Describes what default action will be performed for the given
   // arguments.
   // L = *
   void DescribeDefaultActionTo(const ArgumentTuple& args,
                                ::std::ostream* os) const {
-    const DefaultActionSpec<F>* const spec = FindDefaultActionSpec(args);
+    const OnCallSpec<F>* const spec = FindOnCallSpec(args);
 
     if (spec == NULL) {
       *os << (internal::type_equals<Result, void>::value ?
@@ -1535,14 +1553,23 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
   // explicitly expected nor explicitly unexpected) to the given
   // ostream.
   // L < g_gmock_mutex
-  void DescribeUninterestingCall(const ArgumentTuple& args,
-                                 ::std::ostream* os) const {
+  virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                                ::std::ostream* os) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
     *os << "Uninteresting mock function call - ";
     DescribeDefaultActionTo(args, os);
     *os << "    Function call: " << Name();
     UniversalPrint(args, os);
   }
 
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  //
   // Critical section: We must find the matching expectation and the
   // corresponding action that needs to be taken in an ATOMIC
   // transaction.  Otherwise another thread may call this mock
@@ -1553,23 +1580,36 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
   // action does (it can invoke an arbitrary user function or even a
   // mock function) and excessive locking could cause a dead lock.
   // L < g_gmock_mutex
-  bool FindMatchingExpectationAndAction(
-      const ArgumentTuple& args, TypedExpectation<F>** exp, Action<F>* action,
-      bool* is_excessive, ::std::ostream* what, ::std::ostream* why) {
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why) {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
     MutexLock l(&g_gmock_mutex);
-    *exp = this->FindMatchingExpectationLocked(args);
-    if (*exp == NULL) {  // A match wasn't found.
-      *action = DoDefault();
+    TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
+    if (exp == NULL) {  // A match wasn't found.
       this->FormatUnexpectedCallMessageLocked(args, what, why);
-      return false;
+      return NULL;
     }
 
     // This line must be done before calling GetActionForArguments(),
     // which will increment the call count for *exp and thus affect
     // its saturation status.
-    *is_excessive = (*exp)->IsSaturated();
-    *action = (*exp)->GetActionForArguments(this, args, what, why);
-    return true;
+    *is_excessive = exp->IsSaturated();
+    const Action<F>* action = exp->GetActionForArguments(this, args, what, why);
+    if (action != NULL && action->IsDoDefault())
+      action = NULL;  // Normalize "do default" to NULL.
+    *untyped_action = action;
+    return exp;
+  }
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    UniversalPrint(args, os);
   }
 
   // Returns the expectation that matches the arguments, or NULL if no
@@ -1578,10 +1618,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
   TypedExpectation<F>* FindMatchingExpectationLocked(
       const ArgumentTuple& args) const {
     g_gmock_mutex.AssertHeld();
-    for (typename TypedExpectations::const_reverse_iterator it =
-             expectations_.rbegin();
-         it != expectations_.rend(); ++it) {
-      TypedExpectation<F>* const exp = it->get();
+    for (typename UntypedExpectations::const_reverse_iterator it =
+             untyped_expectations_.rbegin();
+         it != untyped_expectations_.rend(); ++it) {
+      TypedExpectation<F>* const exp =
+          static_cast<TypedExpectation<F>*>(it->get());
       if (exp->ShouldHandleArguments(args)) {
         return exp;
       }
@@ -1606,41 +1647,29 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
   void PrintTriedExpectationsLocked(const ArgumentTuple& args,
                                     ::std::ostream* why) const {
     g_gmock_mutex.AssertHeld();
-    const int count = static_cast<int>(expectations_.size());
+    const int count = static_cast<int>(untyped_expectations_.size());
     *why << "Google Mock tried the following " << count << " "
          << (count == 1 ? "expectation, but it didn't match" :
              "expectations, but none matched")
          << ":\n";
     for (int i = 0; i < count; i++) {
+      TypedExpectation<F>* const expectation =
+          static_cast<TypedExpectation<F>*>(untyped_expectations_[i].get());
       *why << "\n";
-      expectations_[i]->DescribeLocationTo(why);
+      expectation->DescribeLocationTo(why);
       if (count > 1) {
         *why << "tried expectation #" << i << ": ";
       }
-      *why << expectations_[i]->source_text() << "...\n";
-      expectations_[i]->ExplainMatchResultTo(args, why);
-      expectations_[i]->DescribeCallCountTo(why);
+      *why << expectation->source_text() << "...\n";
+      expectation->ExplainMatchResultTo(args, why);
+      expectation->DescribeCallCountTo(why);
     }
   }
 
-  // Address of the mock object this mock method belongs to.  Only
-  // valid after this mock method has been called or
-  // ON_CALL/EXPECT_CALL has been invoked on it.
-  const void* mock_obj_;  // Protected by g_gmock_mutex.
-
-  // Name of the function being mocked.  Only valid after this mock
-  // method has been called.
-  const char* name_;  // Protected by g_gmock_mutex.
-
   // The current spec (either default action spec or expectation spec)
   // being described on this function mocker.
   MockSpec<F> current_spec_;
 
-  // All default action specs for this function mocker.
-  std::vector<DefaultActionSpec<F> > default_actions_;
-  // All expectations for this function mocker.
-  TypedExpectations expectations_;
-
   // There is no generally useful and implementable semantics of
   // copying a mock object, so copying a mock is usually a user error.
   // Thus we disallow copying function mockers.  If the user really
@@ -1666,144 +1695,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
 // satisfied.  Reports one or more Google Test non-fatal failures and
 // returns false if not.
 // L >= g_gmock_mutex
-template <typename F>
-bool FunctionMockerBase<F>::VerifyAndClearExpectationsLocked() {
-  g_gmock_mutex.AssertHeld();
-  bool expectations_met = true;
-  for (typename TypedExpectations::const_iterator it = expectations_.begin();
-       it != expectations_.end(); ++it) {
-    TypedExpectation<F>* const exp = it->get();
-
-    if (exp->IsOverSaturated()) {
-      // There was an upper-bound violation.  Since the error was
-      // already reported when it occurred, there is no need to do
-      // anything here.
-      expectations_met = false;
-    } else if (!exp->IsSatisfied()) {
-      expectations_met = false;
-      ::std::stringstream ss;
-      ss  << "Actual function call count doesn't match "
-          << exp->source_text() << "...\n";
-      // No need to show the source file location of the expectation
-      // in the description, as the Expect() call that follows already
-      // takes care of it.
-      exp->MaybeDescribeExtraMatcherTo(&ss);
-      exp->DescribeCallCountTo(&ss);
-      Expect(false, exp->file(), exp->line(), ss.str());
-    }
-  }
-  expectations_.clear();
-  return expectations_met;
-}
 
 // Reports an uninteresting call (whose description is in msg) in the
 // manner specified by 'reaction'.
 void ReportUninterestingCall(CallReaction reaction, const string& msg);
 
-// Calculates the result of invoking this mock function with the given
-// arguments, prints it, and returns it.
-// L < g_gmock_mutex
-template <typename F>
-typename Function<F>::Result FunctionMockerBase<F>::InvokeWith(
-    const typename Function<F>::ArgumentTuple& args) {
-  typedef ActionResultHolder<Result> ResultHolder;
-
-  if (expectations_.size() == 0) {
-    // No expectation is set on this mock method - we have an
-    // uninteresting call.
-
-    // We must get Google Mock's reaction on uninteresting calls
-    // made on this mock object BEFORE performing the action,
-    // because the action may DELETE the mock object and make the
-    // following expression meaningless.
-    const CallReaction reaction =
-        Mock::GetReactionOnUninterestingCalls(MockObject());
-
-    // True iff we need to print this call's arguments and return
-    // value.  This definition must be kept in sync with
-    // the behavior of ReportUninterestingCall().
-    const bool need_to_report_uninteresting_call =
-        // If the user allows this uninteresting call, we print it
-        // only when he wants informational messages.
-        reaction == ALLOW ? LogIsVisible(INFO) :
-        // If the user wants this to be a warning, we print it only
-        // when he wants to see warnings.
-        reaction == WARN ? LogIsVisible(WARNING) :
-        // Otherwise, the user wants this to be an error, and we
-        // should always print detailed information in the error.
-        true;
-
-    if (!need_to_report_uninteresting_call) {
-      // Perform the action without printing the call information.
-      return PerformDefaultAction(args, "");
-    }
-
-    // Warns about the uninteresting call.
-    ::std::stringstream ss;
-    DescribeUninterestingCall(args, &ss);
-
-    // Calculates the function result.
-    const ResultHolder result =
-        ResultHolder::PerformDefaultAction(this, args, ss.str());
-
-    // Prints the function result.
-    result.PrintAsActionResult(&ss);
-
-    ReportUninterestingCall(reaction, ss.str());
-    return result.value();
-  }
-
-  bool is_excessive = false;
-  ::std::stringstream ss;
-  ::std::stringstream why;
-  ::std::stringstream loc;
-  Action<F> action;
-  TypedExpectation<F>* exp;
-
-  // The FindMatchingExpectationAndAction() function acquires and
-  // releases g_gmock_mutex.
-  const bool found = FindMatchingExpectationAndAction(
-      args, &exp, &action, &is_excessive, &ss, &why);
-
-  // True iff we need to print the call's arguments and return value.
-  // This definition must be kept in sync with the uses of Expect()
-  // and Log() in this function.
-  const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO);
-  if (!need_to_report_call) {
-    // Perform the action without printing the call information.
-    return action.IsDoDefault() ? PerformDefaultAction(args, "") :
-        action.Perform(args);
-  }
-
-  ss << "    Function call: " << Name();
-  UniversalPrint(args, &ss);
-
-  // In case the action deletes a piece of the expectation, we
-  // generate the message beforehand.
-  if (found && !is_excessive) {
-    exp->DescribeLocationTo(&loc);
-  }
-
-  const ResultHolder result = action.IsDoDefault() ?
-      ResultHolder::PerformDefaultAction(this, args, ss.str()) :
-      ResultHolder::PerformAction(action, args);
-  result.PrintAsActionResult(&ss);
-  ss << "\n" << why.str();
-
-  if (!found) {
-    // No expectation matches this call - reports a failure.
-    Expect(false, NULL, -1, ss.str());
-  } else if (is_excessive) {
-    // We had an upper-bound violation and the failure message is in ss.
-    Expect(false, exp->file(), exp->line(), ss.str());
-  } else {
-    // We had an expected call and the matching expectation is
-    // described in ss.
-    Log(INFO, loc.str() + ss.str(), 2);
-  }
-  return result.value();
-}
-
 }  // namespace internal
 
 // The style guide prohibits "using" statements in a namespace scope
diff --git a/scripts/gmock_doctor.py b/scripts/gmock_doctor.py
index f7932b5e..ab923efb 100755
--- a/scripts/gmock_doctor.py
+++ b/scripts/gmock_doctor.py
@@ -261,8 +261,8 @@ def _IncompleteByReferenceArgumentDiagnoser(msg):
                  r'(.*\n)*?' +
                  _CLANG_NON_GMOCK_FILE_LINE_RE +
                  r'note: in instantiation of member function '
-                 r'\'testing::internal::FunctionMocker<.*>::Invoke\' '
-                 r'requested here')
+                 r'\'testing::internal2::TypeWithoutFormatter<.*>::'
+                 r'PrintValue\' requested here')
   diagnosis = """
 In order to mock this function, Google Mock needs to see the definition
 of type "%(type)s" - declaration alone is not enough.  Either #include
diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc
index 0d40d9cd..a99caef2 100644
--- a/src/gmock-spec-builders.cc
+++ b/src/gmock-spec-builders.cc
@@ -55,6 +55,15 @@ namespace internal {
 // mockers, and all expectations.
 GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
 
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+                     const char* file, int line,
+                     const string& message) {
+  ::std::ostringstream s;
+  s << file << ":" << line << ": " << message << ::std::endl;
+  Log(severity, s.str(), 0);
+}
+
 // Constructs an ExpectationBase object.
 ExpectationBase::ExpectationBase(const char* a_file,
                                  int a_line,
@@ -65,8 +74,12 @@ ExpectationBase::ExpectationBase(const char* a_file,
       cardinality_specified_(false),
       cardinality_(Exactly(1)),
       call_count_(0),
-      retired_(false) {
-}
+      retired_(false),
+      extra_matcher_specified_(false),
+      repeated_action_specified_(false),
+      retires_on_saturation_(false),
+      last_clause_(kNone),
+      action_count_checked_(false) {}
 
 // Destructs an ExpectationBase object.
 ExpectationBase::~ExpectationBase() {}
@@ -132,6 +145,99 @@ void ExpectationBase::FindUnsatisfiedPrerequisites(
   }
 }
 
+// Describes how many times a function call matching this
+// expectation has occurred.
+// L >= g_gmock_mutex
+void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const {
+  g_gmock_mutex.AssertHeld();
+
+  // Describes how many times the function is expected to be called.
+  *os << "         Expected: to be ";
+  cardinality().DescribeTo(os);
+  *os << "\n           Actual: ";
+  Cardinality::DescribeActualCallCountTo(call_count(), os);
+
+  // Describes the state of the expectation (e.g. is it satisfied?
+  // is it active?).
+  *os << " - " << (IsOverSaturated() ? "over-saturated" :
+                   IsSaturated() ? "saturated" :
+                   IsSatisfied() ? "satisfied" : "unsatisfied")
+      << " and "
+      << (is_retired() ? "retired" : "active");
+}
+
+// Checks the action count (i.e. the number of WillOnce() and
+// WillRepeatedly() clauses) against the cardinality if this hasn't
+// been done before.  Prints a warning if there are too many or too
+// few actions.
+// L < mutex_
+void ExpectationBase::CheckActionCountIfNotDone() const {
+  bool should_check = false;
+  {
+    MutexLock l(&mutex_);
+    if (!action_count_checked_) {
+      action_count_checked_ = true;
+      should_check = true;
+    }
+  }
+
+  if (should_check) {
+    if (!cardinality_specified_) {
+      // The cardinality was inferred - no need to check the action
+      // count against it.
+      return;
+    }
+
+    // The cardinality was explicitly specified.
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    const int upper_bound = cardinality().ConservativeUpperBound();
+    const int lower_bound = cardinality().ConservativeLowerBound();
+    bool too_many;  // True if there are too many actions, or false
+    // if there are too few.
+    if (action_count > upper_bound ||
+        (action_count == upper_bound && repeated_action_specified_)) {
+      too_many = true;
+    } else if (0 < action_count && action_count < lower_bound &&
+               !repeated_action_specified_) {
+      too_many = false;
+    } else {
+      return;
+    }
+
+    ::std::stringstream ss;
+    DescribeLocationTo(&ss);
+    ss << "Too " << (too_many ? "many" : "few")
+       << " actions specified in " << source_text() << "...\n"
+       << "Expected to be ";
+    cardinality().DescribeTo(&ss);
+    ss << ", but has " << (too_many ? "" : "only ")
+       << action_count << " WillOnce()"
+       << (action_count == 1 ? "" : "s");
+    if (repeated_action_specified_) {
+      ss << " and a WillRepeatedly()";
+    }
+    ss << ".";
+    Log(WARNING, ss.str(), -1);  // -1 means "don't print stack trace".
+  }
+}
+
+// Implements the .Times() clause.
+void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
+  if (last_clause_ == kTimes) {
+    ExpectSpecProperty(false,
+                       ".Times() cannot appear "
+                       "more than once in an EXPECT_CALL().");
+  } else {
+    ExpectSpecProperty(last_clause_ < kTimes,
+                       ".Times() cannot appear after "
+                       ".InSequence(), .WillOnce(), .WillRepeatedly(), "
+                       "or .RetiresOnSaturation().");
+  }
+  last_clause_ = kTimes;
+
+  SpecifyCardinality(a_cardinality);
+}
+
 // Points to the implicit sequence introduced by a living InSequence
 // object (if any) in the current thread or NULL.
 ThreadLocal<Sequence*> g_gmock_implicit_sequence;
@@ -151,6 +257,233 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) {
   }
 }
 
+UntypedFunctionMockerBase::UntypedFunctionMockerBase()
+    : mock_obj_(NULL), name_("") {}
+
+UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {}
+
+// Sets the mock object this mock method belongs to, and registers
+// this information in the global mock registry.  Will be called
+// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+// method.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) {
+  {
+    MutexLock l(&g_gmock_mutex);
+    mock_obj_ = mock_obj;
+  }
+  Mock::Register(mock_obj, this);
+}
+
+// Sets the mock object this mock method belongs to, and sets the name
+// of the mock function.  Will be called upon each invocation of this
+// mock function.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::SetOwnerAndName(
+    const void* mock_obj, const char* name) {
+  // We protect name_ under g_gmock_mutex in case this mock function
+  // is called from two threads concurrently.
+  MutexLock l(&g_gmock_mutex);
+  mock_obj_ = mock_obj;
+  name_ = name;
+}
+
+// Returns the name of the function being mocked.  Must be called
+// after RegisterOwner() or SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const void* UntypedFunctionMockerBase::MockObject() const {
+  const void* mock_obj;
+  {
+    // We protect mock_obj_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(mock_obj_ != NULL, __FILE__, __LINE__,
+           "MockObject() must not be called before RegisterOwner() or "
+           "SetOwnerAndName() has been called.");
+    mock_obj = mock_obj_;
+  }
+  return mock_obj;
+}
+
+// Returns the name of this mock method.  Must be called after
+// SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const char* UntypedFunctionMockerBase::Name() const {
+  const char* name;
+  {
+    // We protect name_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(name_ != NULL, __FILE__, __LINE__,
+           "Name() must not be called before SetOwnerAndName() has "
+           "been called.");
+    name = name_;
+  }
+  return name;
+}
+
+// Calculates the result of invoking this mock function with the given
+// arguments, prints it, and returns it.  The caller is responsible
+// for deleting the result.
+// L < g_gmock_mutex
+const UntypedActionResultHolderBase*
+UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) {
+  if (untyped_expectations_.size() == 0) {
+    // No expectation is set on this mock method - we have an
+    // uninteresting call.
+
+    // We must get Google Mock's reaction on uninteresting calls
+    // made on this mock object BEFORE performing the action,
+    // because the action may DELETE the mock object and make the
+    // following expression meaningless.
+    const CallReaction reaction =
+        Mock::GetReactionOnUninterestingCalls(MockObject());
+
+    // True iff we need to print this call's arguments and return
+    // value.  This definition must be kept in sync with
+    // the behavior of ReportUninterestingCall().
+    const bool need_to_report_uninteresting_call =
+        // If the user allows this uninteresting call, we print it
+        // only when he wants informational messages.
+        reaction == ALLOW ? LogIsVisible(INFO) :
+        // If the user wants this to be a warning, we print it only
+        // when he wants to see warnings.
+        reaction == WARN ? LogIsVisible(WARNING) :
+        // Otherwise, the user wants this to be an error, and we
+        // should always print detailed information in the error.
+        true;
+
+    if (!need_to_report_uninteresting_call) {
+      // Perform the action without printing the call information.
+      return this->UntypedPerformDefaultAction(untyped_args, "");
+    }
+
+    // Warns about the uninteresting call.
+    ::std::stringstream ss;
+    this->UntypedDescribeUninterestingCall(untyped_args, &ss);
+
+    // Calculates the function result.
+    const UntypedActionResultHolderBase* const result =
+        this->UntypedPerformDefaultAction(untyped_args, ss.str());
+
+    // Prints the function result.
+    if (result != NULL)
+      result->PrintAsActionResult(&ss);
+
+    ReportUninterestingCall(reaction, ss.str());
+    return result;
+  }
+
+  bool is_excessive = false;
+  ::std::stringstream ss;
+  ::std::stringstream why;
+  ::std::stringstream loc;
+  const void* untyped_action = NULL;
+
+  // The UntypedFindMatchingExpectation() function acquires and
+  // releases g_gmock_mutex.
+  const ExpectationBase* const untyped_expectation =
+      this->UntypedFindMatchingExpectation(
+          untyped_args, &untyped_action, &is_excessive,
+          &ss, &why);
+  const bool found = untyped_expectation != NULL;
+
+  // True iff we need to print the call's arguments and return value.
+  // This definition must be kept in sync with the uses of Expect()
+  // and Log() in this function.
+  const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO);
+  if (!need_to_report_call) {
+    // Perform the action without printing the call information.
+    return
+        untyped_action == NULL ?
+        this->UntypedPerformDefaultAction(untyped_args, "") :
+        this->UntypedPerformAction(untyped_action, untyped_args);
+  }
+
+  ss << "    Function call: " << Name();
+  this->UntypedPrintArgs(untyped_args, &ss);
+
+  // In case the action deletes a piece of the expectation, we
+  // generate the message beforehand.
+  if (found && !is_excessive) {
+    untyped_expectation->DescribeLocationTo(&loc);
+  }
+
+  const UntypedActionResultHolderBase* const result =
+      untyped_action == NULL ?
+      this->UntypedPerformDefaultAction(untyped_args, ss.str()) :
+      this->UntypedPerformAction(untyped_action, untyped_args);
+  if (result != NULL)
+    result->PrintAsActionResult(&ss);
+  ss << "\n" << why.str();
+
+  if (!found) {
+    // No expectation matches this call - reports a failure.
+    Expect(false, NULL, -1, ss.str());
+  } else if (is_excessive) {
+    // We had an upper-bound violation and the failure message is in ss.
+    Expect(false, untyped_expectation->file(),
+           untyped_expectation->line(), ss.str());
+  } else {
+    // We had an expected call and the matching expectation is
+    // described in ss.
+    Log(INFO, loc.str() + ss.str(), 2);
+  }
+
+  return result;
+}
+
+// Returns an Expectation object that references and co-owns exp,
+// which must be an expectation on this mock function.
+Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    if (it->get() == exp) {
+      return Expectation(*it);
+    }
+  }
+
+  Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
+  return Expectation();
+  // The above statement is just to make the code compile, and will
+  // never be executed.
+}
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures
+// and returns false if not.
+// L >= g_gmock_mutex
+bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() {
+  g_gmock_mutex.AssertHeld();
+  bool expectations_met = true;
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    ExpectationBase* const untyped_expectation = it->get();
+    if (untyped_expectation->IsOverSaturated()) {
+      // There was an upper-bound violation.  Since the error was
+      // already reported when it occurred, there is no need to do
+      // anything here.
+      expectations_met = false;
+    } else if (!untyped_expectation->IsSatisfied()) {
+      expectations_met = false;
+      ::std::stringstream ss;
+      ss  << "Actual function call count doesn't match "
+          << untyped_expectation->source_text() << "...\n";
+      // No need to show the source file location of the expectation
+      // in the description, as the Expect() call that follows already
+      // takes care of it.
+      untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
+      untyped_expectation->DescribeCallCountTo(&ss);
+      Expect(false, untyped_expectation->file(),
+             untyped_expectation->line(), ss.str());
+    }
+  }
+  untyped_expectations_.clear();
+  return expectations_met;
+}
+
 }  // namespace internal
 
 // Class Mock.
@@ -190,7 +523,6 @@ class MockObjectRegistry {
   // object alive.  Therefore we report any living object as test
   // failure, unless the user explicitly asked us to ignore it.
   ~MockObjectRegistry() {
-
     // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
     // a macro.
 
diff --git a/test/gmock-actions_test.cc b/test/gmock-actions_test.cc
index e12402b9..b3f8d52b 100644
--- a/test/gmock-actions_test.cc
+++ b/test/gmock-actions_test.cc
@@ -334,8 +334,7 @@ class MyActionImpl : public ActionInterface<MyFunction> {
 
 TEST(ActionInterfaceTest, CanBeImplementedByDefiningPerform) {
   MyActionImpl my_action_impl;
-
-  EXPECT_FALSE(my_action_impl.IsDoDefault());
+  (void)my_action_impl;
 }
 
 TEST(ActionInterfaceTest, MakeAction) {
diff --git a/test/gmock-spec-builders_test.cc b/test/gmock-spec-builders_test.cc
index 737bcfff..aea5228b 100644
--- a/test/gmock-spec-builders_test.cc
+++ b/test/gmock-spec-builders_test.cc
@@ -103,6 +103,34 @@ using testing::internal::CaptureStdout;
 using testing::internal::GetCapturedStdout;
 #endif
 
+class Incomplete;
+
+class MockIncomplete {
+ public:
+  // This line verifies that a mock method can take a by-reference
+  // argument of an incomplete type.
+  MOCK_METHOD1(ByRefFunc, void(const Incomplete& x));
+};
+
+// Tells Google Mock how to print a value of type Incomplete.
+void PrintTo(const Incomplete& x, ::std::ostream* os);
+
+TEST(MockMethodTest, CanInstantiateWithIncompleteArgType) {
+  // Even though this mock class contains a mock method that takes
+  // by-reference an argument whose type is incomplete, we can still
+  // use the mock, as long as Google Mock knows how to print the
+  // argument.
+  MockIncomplete incomplete;
+  EXPECT_CALL(incomplete, ByRefFunc(_))
+      .Times(AnyNumber());
+}
+
+// The definition of the printer for the argument type doesn't have to
+// be visible where the mock is used.
+void PrintTo(const Incomplete& /* x */, ::std::ostream* os) {
+  *os << "incomplete";
+}
+
 class Result {};
 
 class MockA {
@@ -1327,12 +1355,33 @@ TEST(SequenceTest, Retirement) {
 TEST(ExpectationTest, ConstrutorsWork) {
   MockA a;
   Expectation e1;  // Default ctor.
-  Expectation e2 = EXPECT_CALL(a, DoA(1));  // Ctor from EXPECT_CALL.
-  Expectation e3 = e2;  // Copy ctor.
+
+  // Ctor from various forms of EXPECT_CALL.
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  Expectation e3 = EXPECT_CALL(a, DoA(3)).With(_);
+  {
+    Sequence s;
+    Expectation e4 = EXPECT_CALL(a, DoA(4)).Times(1);
+    Expectation e5 = EXPECT_CALL(a, DoA(5)).InSequence(s);
+  }
+  Expectation e6 = EXPECT_CALL(a, DoA(6)).After(e2);
+  Expectation e7 = EXPECT_CALL(a, DoA(7)).WillOnce(Return());
+  Expectation e8 = EXPECT_CALL(a, DoA(8)).WillRepeatedly(Return());
+  Expectation e9 = EXPECT_CALL(a, DoA(9)).RetiresOnSaturation();
+
+  Expectation e10 = e2;  // Copy ctor.
 
   EXPECT_THAT(e1, Ne(e2));
-  EXPECT_THAT(e2, Eq(e3));
-  a.DoA(1);
+  EXPECT_THAT(e2, Eq(e10));
+
+  a.DoA(2);
+  a.DoA(3);
+  a.DoA(4);
+  a.DoA(5);
+  a.DoA(6);
+  a.DoA(7);
+  a.DoA(8);
+  a.DoA(9);
 }
 
 TEST(ExpectationTest, AssignmentWorks) {