Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -4814,12 +4814,15 @@ 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*. + struct X { + int m; + int f(X x) { x.m; return m; } + }; +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))) + matches "x.m", but not "m" +memberExpr(hasObjectExpression(hasType(pointsTo( + cxxRecordDecl(hasName("X")))))) + matches "m", but not "x.m" @@ -4857,16 +4860,39 @@ Matcher<CXXMemberCallExpr>onImplicitObjectArgumentMatcher<Expr> InnerMatcher -

+
Matches on the implicit object argument of a member call expression. Unlike
+`on`, matches the argument directly without stripping away anything.
+
+Given
+  class Y { public: void m(); };
+  Y g();
+  class X : public Y { void g(); };
+  void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); }
+cxxMemberCallExpr(onImplicitObjectArgument(hasType(
+    cxxRecordDecl(hasName("Y")))))
+  matches `y.m()`, `x.m()` and (g()).m(), but not `x.g()`.
+cxxMemberCallExpr(on(callExpr()))
+  does not match `(g()).m()`, because the parens are not ignored.
+
+FIXME: Overload to allow directly matching types?
+
Matcher<CXXMemberCallExpr>onMatcher<Expr> InnerMatcher -
Matches on the implicit object argument of a member call expression.
+
Matches on the implicit object argument of a member call expression, after
+stripping off any parentheses or implicit casts.
 
-Example matches y.x()
-  (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
-  class Y { public: void x(); };
-  void z() { Y y; y.x(); }
+Given
+  class Y { public: void m(); };
+  Y g();
+  class X : public Y {};
+  void z(Y y, X x) { y.m(); (g()).m(); x.m(); }
+cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))
+  matches `y.m()`, `(g()).m()` and `x.m()`.
+cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))))
+  matches `x.m()`.
+cxxMemberCallExpr(on(callExpr()))
+  matches `(g()).m()`
 
 FIXME: Overload to allow directly matching types?
 
@@ -4878,8 +4904,20 @@ Matcher<CXXMemberCallExpr>thisPointerTypeMatcher<QualType> InnerMatcher -
Matches if the expression's type either matches the specified
-matcher, or is a pointer to a type that matches the InnerMatcher.
+
Matches if the type of the expression's implicit object argument either
+matches the InnerMatcher, or is a pointer to a type that matches the
+InnerMatcher.
+
+Given
+  class Y { public: void m(); };
+  class X : public Y { void g(); };
+  void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
+cxxMemberCallExpr(thisPointerType(hasDeclaration(
+    cxxRecordDecl(hasName("Y")))))
+  matches `y.m()`, `p->m()` and `x.m()`.
+cxxMemberCallExpr(thisPointerType(hasDeclaration(
+    cxxRecordDecl(hasName("X")))))
+  matches `x.g()`.
 
@@ -5988,12 +6026,15 @@ 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*. + struct X { + int m; + int f(X x) { x.m; return m; } + }; +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))) + matches "x.m", but not "m" +memberExpr(hasObjectExpression(hasType(pointsTo( + cxxRecordDecl(hasName("X")))))) + matches "m", but not "x.m"
@@ -6809,12 +6850,15 @@ 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*. + struct X { + int m; + int f(X x) { x.m; return m; } + }; +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))) + matches "x.m", but not "m" +memberExpr(hasObjectExpression(hasType(pointsTo( + cxxRecordDecl(hasName("X")))))) + matches "m", but not "x.m"
Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2887,14 +2887,22 @@ InnerMatcher.matches(*UnderlyingDecl, Finder, Builder); } -/// Matches on the implicit object argument of a member call expression. +/// Matches on the implicit object argument of a member call expression, after +/// stripping off any parentheses or implicit casts. /// -/// Example matches y.x() -/// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))) +/// Given /// \code -/// class Y { public: void x(); }; -/// void z() { Y y; y.x(); } +/// class Y { public: void m(); }; +/// Y g(); +/// class X : public Y {}; +/// void z(Y y, X x) { y.m(); (g()).m(); x.m(); } /// \endcode +/// cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))) +/// matches `y.m()`, `(g()).m()` and `x.m()`. +/// cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X"))))) +/// matches `x.m()`. +/// cxxMemberCallExpr(on(callExpr())) +/// matches `(g()).m()` /// /// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher, @@ -3254,6 +3262,23 @@ .matches(Node, Finder, Builder); } +/// Matches on the implicit object argument of a member call expression. Unlike +/// `on`, matches the argument directly without stripping away anything. +/// +/// Given +/// \code +/// class Y { public: void m(); }; +/// Y g(); +/// class X : public Y { void g(); }; +/// void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); } +/// \endcode +/// cxxMemberCallExpr(onImplicitObjectArgument(hasType( +/// cxxRecordDecl(hasName("Y"))))) +/// matches `y.m()`, `x.m()` and (g()).m(), but not `x.g()`. +/// cxxMemberCallExpr(on(callExpr())) +/// does not match `(g()).m()`, because the parens are not ignored. +/// +/// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, internal::Matcher, InnerMatcher) { const Expr *ExprNode = Node.getImplicitObjectArgument(); @@ -3261,8 +3286,22 @@ InnerMatcher.matches(*ExprNode, Finder, Builder)); } -/// Matches if the expression's type either matches the specified -/// matcher, or is a pointer to a type that matches the InnerMatcher. +/// Matches if the type of the expression's implicit object argument either +/// matches the InnerMatcher, or is a pointer to a type that matches the +/// InnerMatcher. +/// +/// Given +/// \code +/// class Y { public: void m(); }; +/// class X : public Y { void g(); }; +/// void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); } +/// \endcode +/// cxxMemberCallExpr(thisPointerType(hasDeclaration( +/// cxxRecordDecl(hasName("Y"))))) +/// matches `y.m()`, `p->m()` and `x.m()`. +/// cxxMemberCallExpr(thisPointerType(hasDeclaration( +/// cxxRecordDecl(hasName("X"))))) +/// matches `x.g()`. AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, internal::Matcher, InnerMatcher, 0) { return onImplicitObjectArgument( @@ -4969,13 +5008,16 @@ /// /// Given /// \code -/// struct X { int m; }; -/// void f(X x) { x.m; m; } +/// struct X { +/// int m; +/// int f(X x) { x.m; return m; } +/// }; /// \endcode -/// 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*. +/// memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))) +/// matches "x.m", but not "m" +/// memberExpr(hasObjectExpression(hasType(pointsTo( +// cxxRecordDecl(hasName("X")))))) +/// matches "m", but not "x.m" AST_POLYMORPHIC_MATCHER_P( hasObjectExpression, AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr,