diff --git a/include/gmock/gmock-generated-matchers.h b/include/gmock/gmock-generated-matchers.h
index afe1bd48..f3484cb4 100644
--- a/include/gmock/gmock-generated-matchers.h
+++ b/include/gmock/gmock-generated-matchers.h
@@ -50,7 +50,10 @@ template <typename Container>
 class ElementsAreMatcherImpl : public MatcherInterface<Container> {
  public:
   typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
-  typedef typename RawContainer::value_type Element;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
 
   // Constructs the matcher from a sequence of element values or
   // element matchers.
@@ -65,12 +68,13 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
 
   // Returns true iff 'container' matches.
   virtual bool Matches(Container container) const {
-    if (container.size() != count())
+    StlContainerReference stl_container = View::ConstReference(container);
+    if (stl_container.size() != count())
       return false;
 
-    typename RawContainer::const_iterator container_iter = container.begin();
-    for (size_t i = 0; i != count();  ++container_iter, ++i) {
-      if (!matchers_[i].Matches(*container_iter))
+    typename StlContainer::const_iterator it = stl_container.begin();
+    for (size_t i = 0; i != count();  ++it, ++i) {
+      if (!matchers_[i].Matches(*it))
         return false;
     }
 
@@ -116,15 +120,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
   // Explains why 'container' matches, or doesn't match, this matcher.
   virtual void ExplainMatchResultTo(Container container,
                                     ::std::ostream* os) const {
+    StlContainerReference stl_container = View::ConstReference(container);
     if (Matches(container)) {
       // We need to explain why *each* element matches (the obvious
       // ones can be skipped).
 
       bool reason_printed = false;
-      typename RawContainer::const_iterator container_iter = container.begin();
-      for (size_t i = 0; i != count(); ++container_iter, ++i) {
+      typename StlContainer::const_iterator it = stl_container.begin();
+      for (size_t i = 0; i != count(); ++it, ++i) {
         ::std::stringstream ss;
-        matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
+        matchers_[i].ExplainMatchResultTo(*it, &ss);
 
         const string s = ss.str();
         if (!s.empty()) {
@@ -137,7 +142,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
       }
     } else {
       // We need to explain why the container doesn't match.
-      const size_t actual_count = container.size();
+      const size_t actual_count = stl_container.size();
       if (actual_count != count()) {
         // The element count doesn't match.  If the container is
         // empty, there's no need to explain anything as Google Mock
@@ -152,16 +157,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
       // The container has the right size but at least one element
       // doesn't match expectation.  We need to find this element and
       // explain why it doesn't match.
-      typename RawContainer::const_iterator container_iter = container.begin();
-      for (size_t i = 0; i != count(); ++container_iter, ++i) {
-        if (matchers_[i].Matches(*container_iter)) {
+      typename StlContainer::const_iterator it = stl_container.begin();
+      for (size_t i = 0; i != count(); ++it, ++i) {
+        if (matchers_[i].Matches(*it)) {
           continue;
         }
 
         *os << "element " << i << " doesn't match";
 
         ::std::stringstream ss;
-        matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
+        matchers_[i].ExplainMatchResultTo(*it, &ss);
         const string s = ss.str();
         if (!s.empty()) {
           *os << " (" << s << ")";
@@ -190,7 +195,8 @@ class ElementsAreMatcher0 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&>* const matchers = NULL;
     return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
@@ -206,7 +212,8 @@ class ElementsAreMatcher1 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -228,7 +235,8 @@ class ElementsAreMatcher2 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -253,7 +261,8 @@ class ElementsAreMatcher3 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -280,7 +289,8 @@ class ElementsAreMatcher4 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -309,7 +319,8 @@ class ElementsAreMatcher5 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -342,7 +353,8 @@ class ElementsAreMatcher6 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -377,7 +389,8 @@ class ElementsAreMatcher7 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -414,7 +427,8 @@ class ElementsAreMatcher8 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -454,7 +468,8 @@ class ElementsAreMatcher9 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -496,7 +511,8 @@ class ElementsAreMatcher10 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
       MatcherCast<const Element&>(e1_),
@@ -538,7 +554,8 @@ class ElementsAreArrayMatcher {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
   }
@@ -1573,45 +1590,4 @@ string FormatMatcherDescription(
       p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>::\
       gmock_Impl<arg_type>::Matches(arg_type arg) const
 
-namespace testing {
-namespace internal {
-
-// Returns true iff element is in the STL-style container.
-template <typename Container, typename Element>
-inline bool Contains(const Container& container, const Element& element) {
-  return ::std::find(container.begin(), container.end(), element) !=
-      container.end();
-}
-
-// Returns true iff element is in the C-style array.
-template <typename ArrayElement, size_t N, typename Element>
-inline bool Contains(const ArrayElement (&array)[N], const Element& element) {
-  return ::std::find(array, array + N, element) != array + N;
-}
-
-}  // namespace internal
-
-// Matches an STL-style container or a C-style array that contains the given
-// element.
-//
-// Examples:
-//   ::std::set<int> page_ids;
-//   page_ids.insert(3);
-//   page_ids.insert(1);
-//   EXPECT_THAT(page_ids, Contains(1));
-//   EXPECT_THAT(page_ids, Contains(3.0));
-//   EXPECT_THAT(page_ids, Not(Contains(4)));
-//
-//   ::std::map<int, size_t> page_lengths;
-//   page_lengths[1] = 100;
-//   EXPECT_THAT(map_int, Contains(::std::pair<const int, size_t>(1, 100)));
-//
-//   const char* user_ids[] = { "joe", "mike", "tom" };
-//   EXPECT_THAT(user_ids, Contains(::std::string("tom")));
-MATCHER_P(Contains, element, "") {
-  return internal::Contains(arg, element);
-}
-
-}  // namespace testing
-
 #endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
diff --git a/include/gmock/gmock-generated-matchers.h.pump b/include/gmock/gmock-generated-matchers.h.pump
index 09dfedfc..4495547d 100644
--- a/include/gmock/gmock-generated-matchers.h.pump
+++ b/include/gmock/gmock-generated-matchers.h.pump
@@ -53,7 +53,10 @@ template <typename Container>
 class ElementsAreMatcherImpl : public MatcherInterface<Container> {
  public:
   typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
-  typedef typename RawContainer::value_type Element;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
 
   // Constructs the matcher from a sequence of element values or
   // element matchers.
@@ -68,12 +71,13 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
 
   // Returns true iff 'container' matches.
   virtual bool Matches(Container container) const {
-    if (container.size() != count())
+    StlContainerReference stl_container = View::ConstReference(container);
+    if (stl_container.size() != count())
       return false;
 
-    typename RawContainer::const_iterator container_iter = container.begin();
-    for (size_t i = 0; i != count();  ++container_iter, ++i) {
-      if (!matchers_[i].Matches(*container_iter))
+    typename StlContainer::const_iterator it = stl_container.begin();
+    for (size_t i = 0; i != count();  ++it, ++i) {
+      if (!matchers_[i].Matches(*it))
         return false;
     }
 
@@ -119,15 +123,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
   // Explains why 'container' matches, or doesn't match, this matcher.
   virtual void ExplainMatchResultTo(Container container,
                                     ::std::ostream* os) const {
+    StlContainerReference stl_container = View::ConstReference(container);
     if (Matches(container)) {
       // We need to explain why *each* element matches (the obvious
       // ones can be skipped).
 
       bool reason_printed = false;
-      typename RawContainer::const_iterator container_iter = container.begin();
-      for (size_t i = 0; i != count(); ++container_iter, ++i) {
+      typename StlContainer::const_iterator it = stl_container.begin();
+      for (size_t i = 0; i != count(); ++it, ++i) {
         ::std::stringstream ss;
-        matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
+        matchers_[i].ExplainMatchResultTo(*it, &ss);
 
         const string s = ss.str();
         if (!s.empty()) {
@@ -140,7 +145,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
       }
     } else {
       // We need to explain why the container doesn't match.
-      const size_t actual_count = container.size();
+      const size_t actual_count = stl_container.size();
       if (actual_count != count()) {
         // The element count doesn't match.  If the container is
         // empty, there's no need to explain anything as Google Mock
@@ -155,16 +160,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
       // The container has the right size but at least one element
       // doesn't match expectation.  We need to find this element and
       // explain why it doesn't match.
-      typename RawContainer::const_iterator container_iter = container.begin();
-      for (size_t i = 0; i != count(); ++container_iter, ++i) {
-        if (matchers_[i].Matches(*container_iter)) {
+      typename StlContainer::const_iterator it = stl_container.begin();
+      for (size_t i = 0; i != count(); ++it, ++i) {
+        if (matchers_[i].Matches(*it)) {
           continue;
         }
 
         *os << "element " << i << " doesn't match";
 
         ::std::stringstream ss;
-        matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
+        matchers_[i].ExplainMatchResultTo(*it, &ss);
         const string s = ss.str();
         if (!s.empty()) {
           *os << " (" << s << ")";
@@ -193,7 +198,8 @@ class ElementsAreMatcher0 {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&>* const matchers = NULL;
     return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
@@ -214,7 +220,8 @@ class ElementsAreMatcher$i {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     const Matcher<const Element&> matchers[] = {
 
@@ -248,7 +255,8 @@ class ElementsAreArrayMatcher {
   operator Matcher<Container>() const {
     typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
         RawContainer;
-    typedef typename RawContainer::value_type Element;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
 
     return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
   }
@@ -590,45 +598,4 @@ $var param_field_decls2 = [[$for j
 ]]
 
 
-namespace testing {
-namespace internal {
-
-// Returns true iff element is in the STL-style container.
-template <typename Container, typename Element>
-inline bool Contains(const Container& container, const Element& element) {
-  return ::std::find(container.begin(), container.end(), element) !=
-      container.end();
-}
-
-// Returns true iff element is in the C-style array.
-template <typename ArrayElement, size_t N, typename Element>
-inline bool Contains(const ArrayElement (&array)[N], const Element& element) {
-  return ::std::find(array, array + N, element) != array + N;
-}
-
-}  // namespace internal
-
-// Matches an STL-style container or a C-style array that contains the given
-// element.
-//
-// Examples:
-//   ::std::set<int> page_ids;
-//   page_ids.insert(3);
-//   page_ids.insert(1);
-//   EXPECT_THAT(page_ids, Contains(1));
-//   EXPECT_THAT(page_ids, Contains(3.0));
-//   EXPECT_THAT(page_ids, Not(Contains(4)));
-//
-//   ::std::map<int, size_t> page_lengths;
-//   page_lengths[1] = 100;
-//   EXPECT_THAT(map_int, Contains(::std::pair<const int, size_t>(1, 100)));
-//
-//   const char* user_ids[] = { "joe", "mike", "tom" };
-//   EXPECT_THAT(user_ids, Contains(::std::string("tom")));
-MATCHER_P(Contains, element, "") {
-  return internal::Contains(arg, element);
-}
-
-}  // namespace testing
-
 #endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index 0497be27..ce7a2fe9 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -1709,60 +1709,164 @@ void ExplainMatchResultTo(const ResultOfMatcher<Callable>& matcher,
 template <typename Container>
 class ContainerEqMatcher {
  public:
-  explicit ContainerEqMatcher(const Container& rhs) : rhs_(rhs) {}
-  bool Matches(const Container& lhs) const { return lhs == rhs_; }
+  typedef internal::StlContainerView<Container> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+
+  // We make a copy of rhs in case the elements in it are modified
+  // after this matcher is created.
+  explicit ContainerEqMatcher(const Container& rhs) : rhs_(View::Copy(rhs)) {
+    // Makes sure the user doesn't instantiate this class template
+    // with a const or reference type.
+    testing::StaticAssertTypeEq<Container,
+        GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))>();
+  }
+
+  template <typename LhsContainer>
+  bool Matches(const LhsContainer& lhs) const {
+    // GMOCK_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug
+    // that causes LhsContainer to be a const type sometimes.
+    typedef internal::StlContainerView<GMOCK_REMOVE_CONST_(LhsContainer)>
+        LhsView;
+    StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+    return lhs_stl_container == rhs_;
+  }
   void DescribeTo(::std::ostream* os) const {
     *os << "equals ";
-    UniversalPrinter<Container>::Print(rhs_, os);
+    UniversalPrinter<StlContainer>::Print(rhs_, os);
   }
   void DescribeNegationTo(::std::ostream* os) const {
     *os << "does not equal ";
-    UniversalPrinter<Container>::Print(rhs_, os);
+    UniversalPrinter<StlContainer>::Print(rhs_, os);
   }
 
-  void ExplainMatchResultTo(const Container& lhs,
+  template <typename LhsContainer>
+  void ExplainMatchResultTo(const LhsContainer& lhs,
                             ::std::ostream* os) const {
+    // GMOCK_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug
+    // that causes LhsContainer to be a const type sometimes.
+    typedef internal::StlContainerView<GMOCK_REMOVE_CONST_(LhsContainer)>
+        LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+
     // Something is different. Check for missing values first.
     bool printed_header = false;
-    for (typename Container::const_iterator it = lhs.begin();
-         it != lhs.end(); ++it) {
-      if (std::find(rhs_.begin(), rhs_.end(), *it) == rhs_.end()) {
+    for (typename LhsStlContainer::const_iterator it =
+             lhs_stl_container.begin();
+         it != lhs_stl_container.end(); ++it) {
+      if (internal::ArrayAwareFind(rhs_.begin(), rhs_.end(), *it) ==
+          rhs_.end()) {
         if (printed_header) {
           *os << ", ";
         } else {
           *os << "Only in actual: ";
           printed_header = true;
         }
-        UniversalPrinter<typename Container::value_type>::Print(*it, os);
+        UniversalPrinter<typename LhsStlContainer::value_type>::Print(*it, os);
       }
     }
 
     // Now check for extra values.
     bool printed_header2 = false;
-    for (typename Container::const_iterator it = rhs_.begin();
+    for (typename StlContainer::const_iterator it = rhs_.begin();
          it != rhs_.end(); ++it) {
-      if (std::find(lhs.begin(), lhs.end(), *it) == lhs.end()) {
+      if (internal::ArrayAwareFind(
+              lhs_stl_container.begin(), lhs_stl_container.end(), *it) ==
+          lhs_stl_container.end()) {
         if (printed_header2) {
           *os << ", ";
         } else {
           *os << (printed_header ? "; not" : "Not") << " in actual: ";
           printed_header2 = true;
         }
-        UniversalPrinter<typename Container::value_type>::Print(*it, os);
+        UniversalPrinter<typename StlContainer::value_type>::Print(*it, os);
       }
     }
   }
  private:
-  const Container rhs_;
+  const StlContainer rhs_;
 };
 
-template <typename Container>
+template <typename LhsContainer, typename Container>
 void ExplainMatchResultTo(const ContainerEqMatcher<Container>& matcher,
-                          const Container& lhs,
+                          const LhsContainer& lhs,
                           ::std::ostream* os) {
   matcher.ExplainMatchResultTo(lhs, os);
 }
 
+// Implements Contains(element_matcher) for the given argument type Container.
+template <typename Container>
+class ContainsMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
+  typedef StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  template <typename InnerMatcher>
+  explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+          testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
+
+  // Returns true iff 'container' matches.
+  virtual bool Matches(Container container) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    for (typename StlContainer::const_iterator it = stl_container.begin();
+         it != stl_container.end(); ++it) {
+      if (inner_matcher_.Matches(*it))
+        return true;
+    }
+    return false;
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "contains at least one element that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't contain any element that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  // Explains why 'container' matches, or doesn't match, this matcher.
+  virtual void ExplainMatchResultTo(Container container,
+                                    ::std::ostream* os) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+
+    // We need to explain which (if any) element matches inner_matcher_.
+    typename StlContainer::const_iterator it = stl_container.begin();
+    for (size_t i = 0; it != stl_container.end(); ++it, ++i) {
+      if (inner_matcher_.Matches(*it)) {
+        *os << "element " << i << " matches";
+        return;
+      }
+    }
+  }
+
+ private:
+  const Matcher<const Element&> inner_matcher_;
+};
+
+// Implements polymorphic Contains(element_matcher).
+template <typename M>
+class ContainsMatcher {
+ public:
+  explicit ContainsMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new ContainsMatcherImpl<Container>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+};
+
 }  // namespace internal
 
 // Implements MatcherCast().
@@ -2206,9 +2310,35 @@ Truly(Predicate pred) {
 // values that are included in one container but not the other. (Duplicate
 // values and order differences are not explained.)
 template <typename Container>
-inline PolymorphicMatcher<internal::ContainerEqMatcher<Container> >
+inline PolymorphicMatcher<internal::ContainerEqMatcher<
+                            GMOCK_REMOVE_CONST_(Container)> >
     ContainerEq(const Container& rhs) {
-  return MakePolymorphicMatcher(internal::ContainerEqMatcher<Container>(rhs));
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes Container to be a const type sometimes.
+  typedef GMOCK_REMOVE_CONST_(Container) RawContainer;
+  return MakePolymorphicMatcher(internal::ContainerEqMatcher<RawContainer>(rhs));
+}
+
+// Matches an STL-style container or a native array that contains at
+// least one element matching the given value or matcher.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   page_ids.insert(3);
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Contains(1));
+//   EXPECT_THAT(page_ids, Contains(Gt(2)));
+//   EXPECT_THAT(page_ids, Not(Contains(4)));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   EXPECT_THAT(map_int, Contains(::std::pair<const int, size_t>(1, 100)));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom"))));
+template <typename M>
+inline internal::ContainsMatcher<M> Contains(M matcher) {
+  return internal::ContainsMatcher<M>(matcher);
 }
 
 // Returns a predicate that is satisfied by anything that matches the
@@ -2218,6 +2348,12 @@ inline internal::MatcherAsPredicate<M> Matches(M matcher) {
   return internal::MatcherAsPredicate<M>(matcher);
 }
 
+// Returns true iff the value matches the matcher.
+template <typename T, typename M>
+inline bool Value(const T& value, M matcher) {
+  return testing::Matches(matcher)(value);
+}
+
 // These macros allow using matchers to check values in Google Test
 // tests.  ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
 // succeed iff the value matches the matcher.  If the assertion fails,
diff --git a/include/gmock/gmock-printers.h b/include/gmock/gmock-printers.h
index e233ef3e..561de3d9 100644
--- a/include/gmock/gmock-printers.h
+++ b/include/gmock/gmock-printers.h
@@ -66,10 +66,28 @@
 //   // printed.
 //   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
 //
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
 //   // Prints the fields of a tuple tersely to a string vector, one
 //   // element for each field.
 //   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
 //       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
 
 #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
 #define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
@@ -208,6 +226,9 @@ namespace internal {
 template <typename T>
 class UniversalPrinter;
 
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
 // Used to print an STL-style container when the user doesn't define
 // a PrintTo() for it.
 template <typename C>
@@ -227,7 +248,9 @@ void DefaultPrintTo(IsContainer /* dummy */,
       }
     }
     *os << ' ';
-    PrintTo(*it, os);
+    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+    // handle *it being a native array.
+    internal::UniversalPrint(*it, os);
   }
 
   if (count > 0) {
@@ -683,6 +706,15 @@ inline void UniversalTersePrint(char* str, ::std::ostream* os) {
   UniversalTersePrint(static_cast<const char*>(str), os);
 }
 
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  UniversalPrinter<T>::Print(value, os);
+}
+
 // Prints the fields of a tuple tersely to a string vector, one
 // element for each field.  See the comment before
 // UniversalTersePrint() for how we define "tersely".
diff --git a/include/gmock/internal/gmock-internal-utils.h b/include/gmock/internal/gmock-internal-utils.h
index b5e38db3..ee6aa1e2 100644
--- a/include/gmock/internal/gmock-internal-utils.h
+++ b/include/gmock/internal/gmock-internal-utils.h
@@ -99,6 +99,17 @@ struct RemoveConst { typedef T type; };  // NOLINT
 template <typename T>
 struct RemoveConst<const T> { typedef T type; };  // NOLINT
 
+// MSVC 8.0 has a bug which causes the above definition to fail to
+// remove the const in 'const int[3]'.  The following specialization
+// works around the bug.  However, it causes trouble with gcc and thus
+// needs to be conditionally compiled.
+#ifdef _MSC_VER
+template <typename T, size_t N>
+struct RemoveConst<T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+#endif  // _MSC_VER
+
 // A handy wrapper around RemoveConst that works when the argument
 // T depends on template parameters.
 #define GMOCK_REMOVE_CONST_(T) \
@@ -451,10 +462,6 @@ bool LogIsVisible(LogSeverity severity);
 // conservative.
 void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
 
-// The universal value printer (public/gmock-printers.h) needs this
-// to declare an unused << operator in the global namespace.
-struct Unused {};
-
 // TODO(wan@google.com): group all type utilities together.
 
 // Type traits.
@@ -482,6 +489,238 @@ inline T Invalid() {
 template <>
 inline void Invalid<void>() {}
 
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+  kReference,  // The NativeArray references the native array.
+  kCopy        // The NativeArray makes a copy of the native array and
+               // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array passed by reference.
+  template <size_t N>
+  NativeArray(const Element (&array)[N], RelationToSource relation) {
+    Init(array, N, relation);
+  }
+
+  // Constructs from a native array passed by a pointer and a size.
+  // For generality we don't artificially restrict the types of the
+  // pointer and the size.
+  template <typename Pointer, typename Size>
+  NativeArray(const ::std::tr1::tuple<Pointer, Size>& array,
+              RelationToSource relation) {
+    Init(internal::GetRawPointer(::std::tr1::get<0>(array)),
+         ::std::tr1::get<1>(array),
+         relation);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+  }
+
+  ~NativeArray() {
+    // Ensures that the user doesn't instantiate NativeArray with a
+    // const or reference type.
+    testing::StaticAssertTypeEq<Element,
+        GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Element))>();
+    if (relation_to_source_ == kCopy)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  // Not implemented as we don't want to support assignment.
+  void operator=(const NativeArray& rhs);
+
+  // Initializes this object; makes a copy of the input array if
+  // 'relation' is kCopy.
+  void Init(const Element* array, size_t size, RelationToSource relation) {
+    if (relation == kReference) {
+      array_ = array;
+    } else {
+      Element* const copy = new Element[size];
+      CopyArray(array, size, copy);
+      array_ = copy;
+    }
+    size_ = size;
+    relation_to_source_ = relation;
+  }
+
+  const Element* array_;
+  size_t size_;
+  RelationToSource relation_to_source_;
+};
+
+// Given a raw type (i.e. having no top-level reference or const
+// modifier) RawContainer that's either an STL-style container or a
+// native array, class StlContainerView<RawContainer> has the
+// following members:
+//
+//   - type is a type that provides an STL-style container view to
+//     (i.e. implements the STL container concept for) RawContainer;
+//   - const_reference is a type that provides a reference to a const
+//     RawContainer;
+//   - ConstReference(raw_container) returns a const reference to an STL-style
+//     container view to raw_container, which is a RawContainer.
+//   - Copy(raw_container) returns an STL-style container view of a
+//     copy of raw_container, which is a RawContainer.
+//
+// This generic version is used when RawContainer itself is already an
+// STL-style container.
+template <class RawContainer>
+class StlContainerView {
+ public:
+  typedef RawContainer type;
+  typedef const type& const_reference;
+
+  static const_reference ConstReference(const RawContainer& container) {
+    // Ensures that RawContainer is not a const type.
+    testing::StaticAssertTypeEq<RawContainer,
+        GMOCK_REMOVE_CONST_(RawContainer)>();
+    return container;
+  }
+  static type Copy(const RawContainer& container) { return container; }
+};
+
+// This specialization is used when RawContainer is a native array type.
+template <typename Element, size_t N>
+class StlContainerView<Element[N]> {
+ public:
+  typedef GMOCK_REMOVE_CONST_(Element) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  // NativeArray<T> can represent a native array either by value or by
+  // reference (selected by a constructor argument), so 'const type'
+  // can be used to reference a const native array.  We cannot
+  // 'typedef const type& const_reference' here, as that would mean
+  // ConstReference() has to return a reference to a local variable.
+  typedef const type const_reference;
+
+  static const_reference ConstReference(const Element (&array)[N]) {
+    // Ensures that Element is not a const type.
+    testing::StaticAssertTypeEq<Element, RawElement>();
+    return type(array, kReference);
+  }
+  static type Copy(const Element (&array)[N]) {
+    return type(array, kCopy);
+  }
+};
+
+// This specialization is used when RawContainer is a native array
+// represented as a (pointer, size) tuple.
+template <typename ElementPointer, typename Size>
+class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
+ public:
+  typedef GMOCK_REMOVE_CONST_(
+      typename internal::PointeeOf<ElementPointer>::type) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  typedef const type const_reference;
+
+  static const_reference ConstReference(
+      const ::std::tr1::tuple<ElementPointer, Size>& array) {
+    return type(array, kReference);
+  }
+  static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
+    return type(array, kCopy);
+  }
+};
+
+// The following specialization prevents the user from instantiating
+// StlContainer with a reference type.
+template <typename T> class StlContainerView<T&>;
+
 }  // namespace internal
 }  // namespace testing
 
diff --git a/scripts/generator/README b/scripts/generator/README
index 071bf0fb..d6f95974 100644
--- a/scripts/generator/README
+++ b/scripts/generator/README
@@ -23,7 +23,7 @@ the environment.  For example to use an indent of 4 spaces:
 
 INDENT=4 gmock_gen.py header-file.h ClassName
 
-This version was made from SVN revision 279 in the cppclean repository.
+This version was made from SVN revision 281 in the cppclean repository.
 
 Known Limitations
 -----------------
diff --git a/scripts/generator/cpp/gmock_class_test.py b/scripts/generator/cpp/gmock_class_test.py
index 0132eef4..ae00800f 100755
--- a/scripts/generator/cpp/gmock_class_test.py
+++ b/scripts/generator/cpp/gmock_class_test.py
@@ -25,7 +25,7 @@ import sys
 import unittest
 
 # Allow the cpp imports below to work when run as a standalone script.
-sys.path.append(os.path.dirname(os.path.dirname(__file__)))
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
 
 from cpp import ast
 from cpp import gmock_class
diff --git a/scripts/gmock_doctor.py b/scripts/gmock_doctor.py
index 1980977c..05e42585 100755
--- a/scripts/gmock_doctor.py
+++ b/scripts/gmock_doctor.py
@@ -36,7 +36,7 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
 import re
 import sys
 
-_VERSION = '1.0.1'
+_VERSION = '1.0.3'
 
 _COMMON_GMOCK_SYMBOLS = [
     # Matchers
@@ -63,6 +63,7 @@ _COMMON_GMOCK_SYMBOLS = [
     'Le',
     'Lt',
     'MatcherCast',
+    'Matches',
     'MatchesRegex',
     'NanSensitiveDoubleEq',
     'NanSensitiveFloatEq',
@@ -82,6 +83,7 @@ _COMMON_GMOCK_SYMBOLS = [
     'StrNe',
     'Truly',
     'TypedEq',
+    'Value',
 
     # Actions
     'Assign',
@@ -171,7 +173,7 @@ def _NeedToReturnSomethingDiagnoser(msg):
 
   regex = (_FILE_LINE_RE +
            r'(instantiated from here\n.'
-           r'*gmock-actions\.h.*error: void value not ignored)'
+           r'*gmock.*actions\.h.*error: void value not ignored)'
            r'|(error: control reaches end of non-void function)')
   diagnosis = """
 You are using an action that returns void, but it needs to return
@@ -346,6 +348,60 @@ Note: the line number may be off; please fix all instances of Return(NULL)."""
                            regex, diagnosis, msg)
 
 
+_TTB_DIAGNOSIS = """
+In a mock class template, types or typedefs defined in the base class
+template are *not* automatically visible.  This is how C++ works.  Before
+you can use a type or typedef named %(type)s defined in base class Base<T>, you
+need to make it visible.  One way to do it is:
+
+  typedef typename Base<T>::%(type)s %(type)s;"""
+
+
+def _TypeInTemplatedBaseDiagnoser1(msg):
+  """Diagnoses the TTB disease, given the error messages by gcc.
+
+  This version works when the type is used as the mock function's return
+  type.
+  """
+
+  regex = (r'In member function \'int .*\n' + _FILE_LINE_RE +
+           r'error: a function call cannot appear in a constant-expression')
+  diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'}
+  return _GenericDiagnoser('TTB', 'Type in Template Base',
+                           regex, diagnosis, msg)
+
+
+def _TypeInTemplatedBaseDiagnoser2(msg):
+  """Diagnoses the TTB disease, given the error messages by gcc.
+
+  This version works when the type is used as the mock function's sole
+  parameter type.
+  """
+
+  regex = (r'In member function \'int .*\n'
+           + _FILE_LINE_RE +
+           r'error: \'(?P<type>.+)\' was not declared in this scope\n'
+           r'.*error: template argument 1 is invalid\n')
+  return _GenericDiagnoser('TTB', 'Type in Template Base',
+                           regex, _TTB_DIAGNOSIS, msg)
+
+
+def _TypeInTemplatedBaseDiagnoser3(msg):
+  """Diagnoses the TTB disease, given the error messages by gcc.
+
+  This version works when the type is used as a parameter of a mock
+  function that has multiple parameters.
+  """
+
+  regex = (r'error: expected `;\' before \'::\' token\n'
+           + _FILE_LINE_RE +
+           r'error: \'(?P<type>.+)\' was not declared in this scope\n'
+           r'.*error: template argument 1 is invalid\n'
+           r'.*error: \'.+\' was not declared in this scope')
+  return _GenericDiagnoser('TTB', 'Type in Template Base',
+                           regex, _TTB_DIAGNOSIS, msg)
+
+
 def _WrongMockMethodMacroDiagnoser(msg):
   """Diagnoses the WMM disease, given the error messages by gcc."""
 
@@ -357,7 +413,7 @@ def _WrongMockMethodMacroDiagnoser(msg):
 You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
 %(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
 MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
-  return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn macro',
+  return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
                            regex, diagnosis, msg)
 
 
@@ -373,7 +429,7 @@ The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
   EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
 instead of:
   EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
-  return _GenericDiagnoser('WPP', 'Wrong parenthesis position',
+  return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
                            regex, diagnosis, msg)
 
 
@@ -389,6 +445,9 @@ _DIAGNOSERS = [
     _OverloadedFunctionMatcherDiagnoser,
     _OverloadedMethodActionDiagnoser1,
     _OverloadedMethodActionDiagnoser2,
+    _TypeInTemplatedBaseDiagnoser1,
+    _TypeInTemplatedBaseDiagnoser2,
+    _TypeInTemplatedBaseDiagnoser3,
     _WrongMockMethodMacroDiagnoser,
     _WrongParenPositionDiagnoser,
     ]
diff --git a/test/gmock-generated-matchers_test.cc b/test/gmock-generated-matchers_test.cc
index 669652b9..26814463 100644
--- a/test/gmock-generated-matchers_test.cc
+++ b/test/gmock-generated-matchers_test.cc
@@ -53,6 +53,7 @@ using std::pair;
 using std::set;
 using std::stringstream;
 using std::vector;
+using std::tr1::make_tuple;
 using testing::_;
 using testing::Contains;
 using testing::ElementsAre;
@@ -60,6 +61,7 @@ using testing::ElementsAreArray;
 using testing::Eq;
 using testing::Ge;
 using testing::Gt;
+using testing::Lt;
 using testing::MakeMatcher;
 using testing::Matcher;
 using testing::MatcherInterface;
@@ -69,6 +71,7 @@ using testing::Pointee;
 using testing::Ref;
 using testing::StaticAssertTypeEq;
 using testing::StrEq;
+using testing::Value;
 using testing::internal::string;
 
 // Returns the description of the given matcher.
@@ -330,6 +333,39 @@ TEST(ElementsAreTest, WorksWithContainerPointerUsingPointee) {
   EXPECT_THAT(&v, Not(Pointee(ElementsAre(0, _, 3))));
 }
 
+TEST(ElementsAreTest, WorksWithNativeArrayPassedByReference) {
+  int array[] = { 0, 1, 2 };
+  EXPECT_THAT(array, ElementsAre(0, 1, _));
+  EXPECT_THAT(array, Not(ElementsAre(1, _, _)));
+  EXPECT_THAT(array, Not(ElementsAre(0, _)));
+}
+
+class NativeArrayPassedAsPointerAndSize {
+ public:
+  MOCK_METHOD2(Helper, void(int* array, int size));
+};
+
+TEST(ElementsAreTest, WorksWithNativeArrayPassedAsPointerAndSize) {
+  int array[] = { 0, 1 };
+  ::std::tr1::tuple<int*, size_t> array_as_tuple(array, 2);
+  EXPECT_THAT(array_as_tuple, ElementsAre(0, 1));
+  EXPECT_THAT(array_as_tuple, Not(ElementsAre(0)));
+
+  NativeArrayPassedAsPointerAndSize helper;
+  EXPECT_CALL(helper, Helper(_, _))
+      .WithArguments(ElementsAre(0, 1));
+  helper.Helper(array, 2);
+}
+
+TEST(ElementsAreTest, WorksWithTwoDimensionalNativeArray) {
+  const char a2[][3] = { "hi", "lo" };
+  EXPECT_THAT(a2, ElementsAre(ElementsAre('h', 'i', '\0'),
+                              ElementsAre('l', 'o', '\0')));
+  EXPECT_THAT(a2, ElementsAre(StrEq("hi"), StrEq("lo")));
+  EXPECT_THAT(a2, ElementsAre(Not(ElementsAre('h', 'o', '\0')),
+                              ElementsAre('l', 'o', '\0')));
+}
+
 // Tests for ElementsAreArray().  Since ElementsAreArray() shares most
 // of the implementation with ElementsAre(), we don't test it as
 // thoroughly here.
@@ -379,6 +415,17 @@ TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) {
   EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray)));
 }
 
+// Since ElementsAre() and ElementsAreArray() share much of the
+// implementation, we only do a sanity test for native arrays here.
+TEST(ElementsAreArrayTest, WorksWithNativeArray) {
+  ::std::string a[] = { "hi", "ho" };
+  ::std::string b[] = { "hi", "ho" };
+
+  EXPECT_THAT(a, ElementsAreArray(b));
+  EXPECT_THAT(a, ElementsAreArray(b, 2));
+  EXPECT_THAT(a, Not(ElementsAreArray(b, 1)));
+}
+
 // Tests for the MATCHER*() macro family.
 
 // Tests that a simple MATCHER() definition works.
@@ -443,12 +490,23 @@ namespace matcher_test {
 MATCHER(IsOdd, "") { return (arg % 2) != 0; }
 }  // namespace matcher_test
 
-TEST(MatcherTest, WorksInNamespace) {
+TEST(MatcherMacroTest, WorksInNamespace) {
   Matcher<int> m = matcher_test::IsOdd();
   EXPECT_FALSE(m.Matches(4));
   EXPECT_TRUE(m.Matches(5));
 }
 
+// Tests that Value() can be used to compose matchers.
+MATCHER(IsPositiveOdd, "") {
+  return Value(arg, matcher_test::IsOdd()) && arg > 0;
+}
+
+TEST(MatcherMacroTest, CanBeComposedUsingValue) {
+  EXPECT_THAT(3, IsPositiveOdd());
+  EXPECT_THAT(4, Not(IsPositiveOdd()));
+  EXPECT_THAT(-1, Not(IsPositiveOdd()));
+}
+
 // Tests that a simple MATCHER_P() definition works.
 
 MATCHER_P(IsGreaterThan32And, n, "") { return arg > 32 && arg > n; }
@@ -742,14 +800,31 @@ TEST(MatcherPnMacroTest, TypesAreCorrect) {
       EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, 9, '0');
 }
 
+// Tests that matcher-typed parameters can be used in Value() inside a
+// MATCHER_Pn definition.
+
+// Succeeds if arg matches exactly 2 of the 3 matchers.
+MATCHER_P3(TwoOf, m1, m2, m3, "") {
+  const int count = static_cast<int>(Value(arg, m1))
+      + static_cast<int>(Value(arg, m2)) + static_cast<int>(Value(arg, m3));
+  return count == 2;
+}
+
+TEST(MatcherPnMacroTest, CanUseMatcherTypedParameterInValue) {
+  EXPECT_THAT(42, TwoOf(Gt(0), Lt(50), Eq(10)));
+  EXPECT_THAT(0, Not(TwoOf(Gt(-1), Lt(1), Eq(0))));
+}
+
+// Tests Contains().
+
 TEST(ContainsTest, ListMatchesWhenElementIsInContainer) {
   list<int> some_list;
   some_list.push_back(3);
   some_list.push_back(1);
   some_list.push_back(2);
   EXPECT_THAT(some_list, Contains(1));
-  EXPECT_THAT(some_list, Contains(3.0));
-  EXPECT_THAT(some_list, Contains(2.0f));
+  EXPECT_THAT(some_list, Contains(Gt(2.5)));
+  EXPECT_THAT(some_list, Contains(Eq(2.0f)));
 
   list<string> another_list;
   another_list.push_back("fee");
@@ -771,8 +846,8 @@ TEST(ContainsTest, SetMatchesWhenElementIsInContainer) {
   some_set.insert(3);
   some_set.insert(1);
   some_set.insert(2);
-  EXPECT_THAT(some_set, Contains(1.0));
-  EXPECT_THAT(some_set, Contains(3.0f));
+  EXPECT_THAT(some_set, Contains(Eq(1.0)));
+  EXPECT_THAT(some_set, Contains(Eq(3.0f)));
   EXPECT_THAT(some_set, Contains(2));
 
   set<const char*> another_set;
@@ -780,7 +855,7 @@ TEST(ContainsTest, SetMatchesWhenElementIsInContainer) {
   another_set.insert("fie");
   another_set.insert("foe");
   another_set.insert("fum");
-  EXPECT_THAT(another_set, Contains(string("fum")));
+  EXPECT_THAT(another_set, Contains(Eq(string("fum"))));
 }
 
 TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
@@ -795,8 +870,20 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
 }
 
 TEST(ContainsTest, DescribesItselfCorrectly) {
+  const int a[2] = { 1, 2 };
+  Matcher<const int(&)[2]> m = Contains(2);
+  EXPECT_EQ("element 1 matches", Explain(m, a));
+
+  m = Contains(3);
+  EXPECT_EQ("", Explain(m, a));
+}
+
+TEST(ContainsTest, ExplainsMatchResultCorrectly) {
   Matcher<vector<int> > m = Contains(1);
-  EXPECT_EQ("contains 1", Describe(m));
+  EXPECT_EQ("contains at least one element that is equal to 1", Describe(m));
+
+  Matcher<vector<int> > m2 = Not(m);
+  EXPECT_EQ("doesn't contain any element that is equal to 1", Describe(m2));
 }
 
 TEST(ContainsTest, MapMatchesWhenElementIsInContainer) {
@@ -823,7 +910,7 @@ TEST(ContainsTest, MapDoesNotMatchWhenElementIsNotInContainer) {
 
 TEST(ContainsTest, ArrayMatchesWhenElementIsInContainer) {
   const char* string_array[] = { "fee", "fie", "foe", "fum" };
-  EXPECT_THAT(string_array, Contains(string("fum")));
+  EXPECT_THAT(string_array, Contains(Eq(string("fum"))));
 }
 
 TEST(ContainsTest, ArrayDoesNotMatchWhenElementIsNotInContainer) {
@@ -831,4 +918,24 @@ TEST(ContainsTest, ArrayDoesNotMatchWhenElementIsNotInContainer) {
   EXPECT_THAT(int_array, Not(Contains(5)));
 }
 
+TEST(ContainsTest, AcceptsMatcher) {
+  const int a[] = { 1, 2, 3 };
+  EXPECT_THAT(a, Contains(Gt(2)));
+  EXPECT_THAT(a, Not(Contains(Gt(4))));
+}
+
+TEST(ContainsTest, WorksForNativeArrayAsTuple) {
+  const int a[] = { 1, 2 };
+  EXPECT_THAT(make_tuple(a, 2), Contains(1));
+  EXPECT_THAT(make_tuple(a, 2), Not(Contains(Gt(3))));
+}
+
+TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
+  int a[][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
+  EXPECT_THAT(a, Contains(ElementsAre(4, 5, 6)));
+  EXPECT_THAT(a, Contains(Contains(5)));
+  EXPECT_THAT(a, Not(Contains(ElementsAre(3, 4, 5))));
+  EXPECT_THAT(a, Contains(Not(Contains(5))));
+}
+
 }  // namespace
diff --git a/test/gmock-internal-utils_test.cc b/test/gmock-internal-utils_test.cc
index 7886f6d3..73960df5 100644
--- a/test/gmock-internal-utils_test.cc
+++ b/test/gmock-internal-utils_test.cc
@@ -53,6 +53,7 @@ namespace internal {
 
 namespace {
 
+using ::std::tr1::make_tuple;
 using ::std::tr1::tuple;
 
 TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) {
@@ -130,6 +131,8 @@ TEST(RemoveConstTest, DoesNotAffectNonConstType) {
 // Tests that RemoveConst removes const from const types.
 TEST(RemoveConstTest, RemovesConst) {
   CompileAssertTypesEqual<int, RemoveConst<const int>::type>();
+  CompileAssertTypesEqual<char[2], RemoveConst<const char[2]>::type>();
+  CompileAssertTypesEqual<char[2][3], RemoveConst<const char[2][3]>::type>();
 }
 
 // Tests GMOCK_REMOVE_CONST_.
@@ -721,6 +724,234 @@ TEST(OnCallTest, LogsAnythingArgument) {
 
 #endif  // 0
 
+// Tests ArrayEq().
+
+TEST(ArrayEqTest, WorksForDegeneratedArrays) {
+  EXPECT_TRUE(ArrayEq(5, 5L));
+  EXPECT_FALSE(ArrayEq('a', 0));
+}
+
+TEST(ArrayEqTest, WorksForOneDimensionalArrays) {
+  const int a[] = { 0, 1 };
+  long b[] = { 0, 1 };
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  b[0] = 2;
+  EXPECT_FALSE(ArrayEq(a, b));
+  EXPECT_FALSE(ArrayEq(a, 1, b));
+}
+
+TEST(ArrayEqTest, WorksForTwoDimensionalArrays) {
+  const char a[][3] = { "hi", "lo" };
+  const char b[][3] = { "hi", "lo" };
+  const char c[][3] = { "hi", "li" };
+
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  EXPECT_FALSE(ArrayEq(a, c));
+  EXPECT_FALSE(ArrayEq(a, 2, c));
+}
+
+// Tests ArrayAwareFind().
+
+TEST(ArrayAwareFindTest, WorksForOneDimensionalArray) {
+  const char a[] = "hello";
+  EXPECT_EQ(a + 4, ArrayAwareFind(a, a + 5, 'o'));
+  EXPECT_EQ(a + 5, ArrayAwareFind(a, a + 5, 'x'));
+}
+
+TEST(ArrayAwareFindTest, WorksForTwoDimensionalArray) {
+  int a[][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
+  const int b[2] = { 2, 3 };
+  EXPECT_EQ(a + 1, ArrayAwareFind(a, a + 3, b));
+
+  const int c[2] = { 6, 7 };
+  EXPECT_EQ(a + 3, ArrayAwareFind(a, a + 3, c));
+}
+
+// Tests CopyArray().
+
+TEST(CopyArrayTest, WorksForDegeneratedArrays) {
+  int n = 0;
+  CopyArray('a', &n);
+  EXPECT_EQ('a', n);
+}
+
+TEST(CopyArrayTest, WorksForOneDimensionalArrays) {
+  const char a[3] = "hi";
+  int b[3];
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+
+  int c[3];
+  CopyArray(a, 3, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+TEST(CopyArrayTest, WorksForTwoDimensionalArrays) {
+  const int a[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
+  int b[2][3];
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+
+  int c[2][3];
+  CopyArray(a, 2, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+// Tests NativeArray.
+
+TEST(NativeArrayTest, ConstructorFromArrayReferenceWorks) {
+  const int a[3] = { 0, 1, 2 };
+  NativeArray<int> na(a, kReference);
+  EXPECT_EQ(3, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+TEST(NativeArrayTest, ConstructorFromTupleWorks) {
+  int a[3] = { 0, 1, 2 };
+  // Tests with a plain pointer.
+  NativeArray<int> na(make_tuple(a, 3U), kReference);
+  EXPECT_EQ(a, na.begin());
+
+  const linked_ptr<char> b(new char);
+  *b = 'a';
+  // Tests with a smart pointer.
+  NativeArray<char> nb(make_tuple(b, 1), kCopy);
+  EXPECT_NE(b.get(), nb.begin());
+  EXPECT_EQ('a', nb.begin()[0]);
+}
+
+TEST(NativeArrayTest, CreatesAndDeletesCopyOfArrayWhenAskedTo) {
+  typedef int Array[2];
+  Array* a = new Array[1];
+  (*a)[0] = 0;
+  (*a)[1] = 1;
+  NativeArray<int> na(*a, kCopy);
+  EXPECT_NE(*a, na.begin());
+  delete[] a;
+  EXPECT_EQ(0, na.begin()[0]);
+  EXPECT_EQ(1, na.begin()[1]);
+
+  // We rely on the heap checker to verify that na deletes the copy of
+  // array.
+}
+
+TEST(NativeArrayTest, TypeMembersAreCorrect) {
+  StaticAssertTypeEq<char, NativeArray<char>::value_type>();
+  StaticAssertTypeEq<int[2], NativeArray<int[2]>::value_type>();
+
+  StaticAssertTypeEq<const char*, NativeArray<char>::const_iterator>();
+  StaticAssertTypeEq<const bool(*)[2], NativeArray<bool[2]>::const_iterator>();
+}
+
+TEST(NativeArrayTest, MethodsWork) {
+  const int a[] = { 0, 1, 2 };
+  NativeArray<int> na(a, kCopy);
+  ASSERT_EQ(3, na.size());
+  EXPECT_EQ(3, na.end() - na.begin());
+
+  NativeArray<int>::const_iterator it = na.begin();
+  EXPECT_EQ(0, *it);
+  ++it;
+  EXPECT_EQ(1, *it);
+  it++;
+  EXPECT_EQ(2, *it);
+  ++it;
+  EXPECT_EQ(na.end(), it);
+
+  EXPECT_THAT(na, Eq(na));
+
+  NativeArray<int> na2(a, kReference);
+  EXPECT_THAT(na, Eq(na2));
+
+  const int b1[] = { 0, 1, 1 };
+  const int b2[] = { 0, 1, 2, 3 };
+  EXPECT_THAT(na, Not(Eq(NativeArray<int>(b1, kReference))));
+  EXPECT_THAT(na, Not(Eq(NativeArray<int>(b2, kCopy))));
+}
+
+TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
+  const char a[2][3] = { "hi", "lo" };
+  NativeArray<char[3]> na(a, kReference);
+  ASSERT_EQ(2, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+// Tests StlContainerView.
+
+TEST(StlContainerViewTest, WorksForStlContainer) {
+  StaticAssertTypeEq<std::vector<int>,
+      StlContainerView<std::vector<int> >::type>();
+  StaticAssertTypeEq<const std::vector<double>&,
+      StlContainerView<std::vector<double> >::const_reference>();
+
+  typedef std::vector<char> Chars;
+  Chars v1;
+  const Chars& v2(StlContainerView<Chars>::ConstReference(v1));
+  EXPECT_EQ(&v1, &v2);
+
+  v1.push_back('a');
+  Chars v3 = StlContainerView<Chars>::Copy(v1);
+  EXPECT_THAT(v3, Eq(v3));
+}
+
+TEST(StlContainerViewTest, WorksForStaticNativeArray) {
+  StaticAssertTypeEq<NativeArray<int>,
+      StlContainerView<int[3]>::type>();
+  StaticAssertTypeEq<NativeArray<double>,
+      StlContainerView<const double[4]>::type>();
+  StaticAssertTypeEq<NativeArray<char[3]>,
+      StlContainerView<const char[2][3]>::type>();
+
+  StaticAssertTypeEq<const NativeArray<int>,
+      StlContainerView<int[2]>::const_reference>();
+
+  int a1[3] = { 0, 1, 2 };
+  NativeArray<int> a2 = StlContainerView<int[3]>::ConstReference(a1);
+  EXPECT_EQ(3, a2.size());
+  EXPECT_EQ(a1, a2.begin());
+
+  const NativeArray<int> a3 = StlContainerView<int[3]>::Copy(a1);
+  ASSERT_EQ(3, a3.size());
+  EXPECT_EQ(0, a3.begin()[0]);
+  EXPECT_EQ(1, a3.begin()[1]);
+  EXPECT_EQ(2, a3.begin()[2]);
+
+  // Makes sure a1 and a3 aren't aliases.
+  a1[0] = 3;
+  EXPECT_EQ(0, a3.begin()[0]);
+}
+
+TEST(StlContainerViewTest, WorksForDynamicNativeArray) {
+  StaticAssertTypeEq<NativeArray<int>,
+      StlContainerView<tuple<const int*, size_t> >::type>();
+  StaticAssertTypeEq<NativeArray<double>,
+      StlContainerView<tuple<linked_ptr<double>, int> >::type>();
+
+  StaticAssertTypeEq<const NativeArray<int>,
+      StlContainerView<tuple<const int*, int> >::const_reference>();
+
+  int a1[3] = { 0, 1, 2 };
+  NativeArray<int> a2 = StlContainerView<tuple<const int*, int> >::
+      ConstReference(make_tuple(a1, 3));
+  EXPECT_EQ(3, a2.size());
+  EXPECT_EQ(a1, a2.begin());
+
+  const NativeArray<int> a3 = StlContainerView<tuple<int*, size_t> >::
+      Copy(make_tuple(a1, 3));
+  ASSERT_EQ(3, a3.size());
+  EXPECT_EQ(0, a3.begin()[0]);
+  EXPECT_EQ(1, a3.begin()[1]);
+  EXPECT_EQ(2, a3.begin()[2]);
+
+  // Makes sure a1 and a3 aren't aliases.
+  a1[0] = 3;
+  EXPECT_EQ(0, a3.begin()[0]);
+}
+
 }  // namespace
 }  // namespace internal
 }  // namespace testing
diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc
index e7709018..1226a1d1 100644
--- a/test/gmock-matchers_test.cc
+++ b/test/gmock-matchers_test.cc
@@ -60,6 +60,7 @@ bool SkipPrefix(const char* prefix, const char** pstr);
 namespace gmock_matchers_test {
 
 using std::stringstream;
+using std::tr1::make_tuple;
 using testing::A;
 using testing::AllOf;
 using testing::An;
@@ -98,6 +99,7 @@ using testing::StrEq;
 using testing::StrNe;
 using testing::Truly;
 using testing::TypedEq;
+using testing::Value;
 using testing::_;
 using testing::internal::FloatingEqMatcher;
 using testing::internal::FormatMatcherDescriptionSyntaxError;
@@ -1670,6 +1672,25 @@ TEST(MatchesTest, WorksWithMatcherOnNonRefType) {
   EXPECT_FALSE(Matches(eq5)(2));
 }
 
+// Tests Value(value, matcher).  Since Value() is a simple wrapper for
+// Matches(), which has been tested already, we don't spend a lot of
+// effort on testing Value().
+TEST(ValueTest, WorksWithPolymorphicMatcher) {
+  EXPECT_TRUE(Value("hi", StartsWith("h")));
+  EXPECT_FALSE(Value(5, Gt(10)));
+}
+
+TEST(ValueTest, WorksWithMonomorphicMatcher) {
+  const Matcher<int> is_zero = Eq(0);
+  EXPECT_TRUE(Value(0, is_zero));
+  EXPECT_FALSE(Value('a', is_zero));
+
+  int n = 0;
+  const Matcher<const int&> ref_n = Ref(n);
+  EXPECT_TRUE(Value(n, ref_n));
+  EXPECT_FALSE(Value(1, ref_n));
+}
+
 // Tests that ASSERT_THAT() and EXPECT_THAT() work when the value
 // matches the matcher.
 TEST(MatcherAssertionTest, WorksWhenMatcherIsSatisfied) {
@@ -2765,9 +2786,7 @@ TEST(ByRefTest, AllowsNotCopyableValueInMatchers) {
 // different element types.
 
 template <typename T>
-class ContainerEqTest : public testing::Test {
- public:
-};
+class ContainerEqTest : public testing::Test {};
 
 typedef testing::Types<
     std::set<int>,
@@ -2901,6 +2920,59 @@ TEST(ContainerEqExtraTest, WorksForMaps) {
             Explain(m, test_map));
 }
 
+TEST(ContainerEqExtraTest, WorksForNativeArray) {
+  int a1[] = { 1, 2, 3 };
+  int a2[] = { 1, 2, 3 };
+  int b[] = { 1, 2, 4 };
+
+  EXPECT_THAT(a1, ContainerEq(a2));
+  EXPECT_THAT(a1, Not(ContainerEq(b)));
+}
+
+TEST(ContainerEqExtraTest, WorksForTwoDimensionalNativeArray) {
+  const char a1[][3] = { "hi", "lo" };
+  const char a2[][3] = { "hi", "lo" };
+  const char b[][3] = { "lo", "hi" };
+
+  // Tests using ContainerEq() in the first dimension.
+  EXPECT_THAT(a1, ContainerEq(a2));
+  EXPECT_THAT(a1, Not(ContainerEq(b)));
+
+  // Tests using ContainerEq() in the second dimension.
+  EXPECT_THAT(a1, ElementsAre(ContainerEq(a2[0]), ContainerEq(a2[1])));
+  EXPECT_THAT(a1, ElementsAre(Not(ContainerEq(b[0])), ContainerEq(a2[1])));
+}
+
+TEST(ContainerEqExtraTest, WorksForNativeArrayAsTuple) {
+  const int a1[] = { 1, 2, 3 };
+  const int a2[] = { 1, 2, 3 };
+  const int b[] = { 1, 2, 3, 4 };
+
+  EXPECT_THAT(make_tuple(a1, 3), ContainerEq(a2));
+  EXPECT_THAT(make_tuple(a1, 3), Not(ContainerEq(b)));
+
+  const int c[] = { 1, 3, 2 };
+  EXPECT_THAT(make_tuple(a1, 3), Not(ContainerEq(c)));
+}
+
+TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
+  std::string a1[][3] = {
+    { "hi", "hello", "ciao" },
+    { "bye", "see you", "ciao" }
+  };
+
+  std::string a2[][3] = {
+    { "hi", "hello", "ciao" },
+    { "bye", "see you", "ciao" }
+  };
+
+  const Matcher<const std::string(&)[2][3]> m = ContainerEq(a2);
+  EXPECT_THAT(a1, m);
+
+  a2[0][0] = "ha";
+  EXPECT_THAT(a1, m);
+}
+
 // Tests GetParamIndex().
 
 TEST(GetParamIndexTest, WorksForEmptyParamList) {
diff --git a/test/gmock-printers_test.cc b/test/gmock-printers_test.cc
index f03be292..8c03ec46 100644
--- a/test/gmock-printers_test.cc
+++ b/test/gmock-printers_test.cc
@@ -154,10 +154,13 @@ using ::std::tr1::tuple;
 using ::std::vector;
 using ::testing::ElementsAre;
 using ::testing::StartsWith;
+using ::testing::internal::NativeArray;
 using ::testing::internal::Strings;
 using ::testing::internal::UniversalTersePrint;
+using ::testing::internal::UniversalPrint;
 using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
 using ::testing::internal::UniversalPrinter;
+using ::testing::internal::kReference;
 using ::testing::internal::string;
 
 #if GTEST_OS_WINDOWS
@@ -786,6 +789,17 @@ TEST(PrintStlContainerTest, NestedContainer) {
   EXPECT_EQ("{ { 1, 2 }, { 3, 4, 5 } }", Print(v));
 }
 
+TEST(PrintStlContainerTest, OneDimensionalNativeArray) {
+  const int a[] = { 1, 2, 3 };
+  NativeArray<int> b(a, kReference);
+  EXPECT_EQ("{ 1, 2, 3 }", Print(b));
+}
+
+TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
+  const int a[][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
+  NativeArray<int[3]> b(a, kReference);
+  EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
+}
 
 // Tests printing tuples.
 
@@ -1013,6 +1027,37 @@ TEST(UniversalTersePrintTest, WorksForCString) {
   EXPECT_EQ("NULL", ss3.str());
 }
 
+TEST(UniversalPrintTest, WorksForNonReference) {
+  ::std::stringstream ss;
+  UniversalPrint(123, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForReference) {
+  const int& n = 123;
+  ::std::stringstream ss;
+  UniversalPrint(n, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForCString) {
+  const char* s1 = "abc";
+  ::std::stringstream ss1;
+  UniversalPrint(s1, &ss1);
+  EXPECT_EQ(PrintPointer(s1) + " pointing to \"abc\"", string(ss1.str()));
+
+  char* s2 = const_cast<char*>(s1);
+  ::std::stringstream ss2;
+  UniversalPrint(s2, &ss2);
+  EXPECT_EQ(PrintPointer(s2) + " pointing to \"abc\"", string(ss2.str()));
+
+  const char* s3 = NULL;
+  ::std::stringstream ss3;
+  UniversalPrint(s3, &ss3);
+  EXPECT_EQ("NULL", ss3.str());
+}
+
+
 TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsEmptyTuple) {
   EXPECT_THAT(UniversalTersePrintTupleFieldsToStrings(make_tuple()),
               ElementsAre());