Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -4668,6 +4668,20 @@ +Matcher<CXXDependentScopeMemberExpr>hasObjectExpressionMatcher<Expr> InnerMatcher +
Matches a member expression where the object expression is
+matched by a given matcher.
+
+Given
+  struct X { int m; };
+  void f(X x) { x.m; m; }
+memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
+  matches "x.m" and "m"
+with hasObjectExpression(...)
+  matching "x" and the implicit object expression of "m" which has type X*.
+
+ + Matcher<CXXForRangeStmt>hasBodyMatcher<Stmt> InnerMatcher
Matches a 'for', 'while', 'do while' statement or a function
 definition that has a given body.
@@ -6692,6 +6706,20 @@
 
+Matcher<UnresolvedMemberExpr>hasObjectExpressionMatcher<Expr> InnerMatcher +
Matches a member expression where the object expression is
+matched by a given matcher.
+
+Given
+  struct X { int m; };
+  void f(X x) { x.m; m; }
+memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
+  matches "x.m" and "m"
+with hasObjectExpression(...)
+  matching "x" and the implicit object expression of "m" which has type X*.
+
+ + Matcher<UnresolvedUsingType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -4825,8 +4825,17 @@
 ///   matches "x.m" and "m"
 /// with hasObjectExpression(...)
 ///   matching "x" and the implicit object expression of "m" which has type X*.
-AST_MATCHER_P(MemberExpr, hasObjectExpression,
-              internal::Matcher, InnerMatcher) {
+AST_POLYMORPHIC_MATCHER_P(
+    hasObjectExpression,
+    AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr,
+                                    CXXDependentScopeMemberExpr),
+    internal::Matcher, InnerMatcher) {
+  if (const auto *E = dyn_cast(&Node))
+    if (E->isImplicitAccess())
+      return false;
+  if (const auto *E = dyn_cast(&Node))
+    if (E->isImplicitAccess())
+      return false;
   return InnerMatcher.matches(*Node.getBase(), Finder, Builder);
 }
 
Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1517,6 +1517,26 @@
     "struct X { int m; }; void f(X* x) { x->m; }",
     memberExpr(hasObjectExpression(
       hasType(pointsTo(recordDecl(hasName("X"))))))));
+  EXPECT_TRUE(matches("template  struct X { void f() { T t; t.m; } };",
+                      cxxDependentScopeMemberExpr(hasObjectExpression(
+                          declRefExpr(to(namedDecl(hasName("t"))))))));
+  EXPECT_TRUE(
+      matches("template  struct X { void f() { T t; t->m; } };",
+              cxxDependentScopeMemberExpr(hasObjectExpression(
+                  declRefExpr(to(namedDecl(hasName("t"))))))));
+}
+
+TEST(HasObjectExpression, MatchesBaseOfMemberFunc) {
+  EXPECT_TRUE(matches(
+      "struct X { void f(); }; void g(X x) { x.f(); }",
+      memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
+  EXPECT_TRUE(matches("struct X { template  void f(); };"
+                      "template  void g(X x) { x.f(); }",
+                      unresolvedMemberExpr(hasObjectExpression(
+                          hasType(recordDecl(hasName("X")))))));
+  EXPECT_TRUE(matches("template  void f(T t) { t.g(); }",
+                      cxxDependentScopeMemberExpr(hasObjectExpression(
+                          declRefExpr(to(namedDecl(hasName("t"))))))));
 }
 
 TEST(HasObjectExpression,