@@ -4810,16 +4810,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
4810
4810
4811
4811
4812
4812
< tr > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html "> CXXDependentScopeMemberExpr</ a > ></ td > < td class ="name " onclick ="toggle('hasObjectExpression2') "> < a name ="hasObjectExpression2Anchor "> hasObjectExpression</ a > </ td > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1Expr.html "> Expr</ a > > InnerMatcher</ td > </ tr >
4813
- < tr > < td colspan ="4 " class ="doc " id ="hasObjectExpression2 "> < pre > Matches a member expression where the object expression is
4814
- matched by a given matcher.
4813
+ < tr > < td colspan ="4 " class ="doc " id ="hasObjectExpression2 "> < pre > Matches a member expression where the object expression is matched by a
4814
+ given matcher. Implicit object expressions are included; that is, it matches
4815
+ use of implicit `this`.
4815
4816
4816
4817
Given
4817
- struct X { int m; };
4818
- void f(X x) { x.m; m; }
4819
- memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
4820
- matches "x.m" and "m"
4821
- with hasObjectExpression(...)
4822
- matching "x" and the implicit object expression of "m" which has type X*.
4818
+ struct X {
4819
+ int m;
4820
+ int f(X x) { x.m; return m; }
4821
+ };
4822
+ memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
4823
+ matches `x.m`, but not `m`; however,
4824
+ memberExpr(hasObjectExpression(hasType(pointsTo(
4825
+ cxxRecordDecl(hasName("X"))))))
4826
+ matches `m` (aka. `this->m`), but not `x.m`.
4823
4827
</ pre > </ td > </ tr >
4824
4828
4825
4829
@@ -4857,16 +4861,39 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
4857
4861
4858
4862
4859
4863
< tr > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html "> CXXMemberCallExpr</ a > ></ td > < td class ="name " onclick ="toggle('onImplicitObjectArgument0') "> < a name ="onImplicitObjectArgument0Anchor "> onImplicitObjectArgument</ a > </ td > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1Expr.html "> Expr</ a > > InnerMatcher</ td > </ tr >
4860
- < tr > < td colspan ="4 " class ="doc " id ="onImplicitObjectArgument0 "> < pre > </ pre > </ td > </ tr >
4864
+ < tr > < td colspan ="4 " class ="doc " id ="onImplicitObjectArgument0 "> < pre > Matches on the implicit object argument of a member call expression. Unlike
4865
+ `on`, matches the argument directly without stripping away anything.
4866
+
4867
+ Given
4868
+ class Y { public: void m(); };
4869
+ Y g();
4870
+ class X : public Y { void g(); };
4871
+ void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); }
4872
+ cxxMemberCallExpr(onImplicitObjectArgument(hasType(
4873
+ cxxRecordDecl(hasName("Y")))))
4874
+ matches `y.m()`, `x.m()` and (g()).m(), but not `x.g()`.
4875
+ cxxMemberCallExpr(on(callExpr()))
4876
+ does not match `(g()).m()`, because the parens are not ignored.
4877
+
4878
+ FIXME: Overload to allow directly matching types?
4879
+ </ pre > </ td > </ tr >
4861
4880
4862
4881
4863
4882
< tr > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html "> CXXMemberCallExpr</ a > ></ td > < td class ="name " onclick ="toggle('on0') "> < a name ="on0Anchor "> on</ a > </ td > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1Expr.html "> Expr</ a > > InnerMatcher</ td > </ tr >
4864
- < tr > < td colspan ="4 " class ="doc " id ="on0 "> < pre > Matches on the implicit object argument of a member call expression.
4883
+ < tr > < td colspan ="4 " class ="doc " id ="on0 "> < pre > Matches on the implicit object argument of a member call expression, after
4884
+ stripping off any parentheses or implicit casts.
4865
4885
4866
- Example matches y.x()
4867
- (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
4868
- class Y { public: void x(); };
4869
- void z() { Y y; y.x(); }
4886
+ Given
4887
+ class Y { public: void m(); };
4888
+ Y g();
4889
+ class X : public Y {};
4890
+ void z(Y y, X x) { y.m(); (g()).m(); x.m(); }
4891
+ cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))
4892
+ matches `y.m()` and `(g()).m()`.
4893
+ cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))))
4894
+ matches `x.m()`.
4895
+ cxxMemberCallExpr(on(callExpr()))
4896
+ matches `(g()).m()`.
4870
4897
4871
4898
FIXME: Overload to allow directly matching types?
4872
4899
</ pre > </ td > </ tr >
@@ -4878,8 +4905,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
4878
4905
4879
4906
4880
4907
< tr > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html "> CXXMemberCallExpr</ a > ></ td > < td class ="name " onclick ="toggle('thisPointerType0') "> < a name ="thisPointerType0Anchor "> thisPointerType</ a > </ td > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1QualType.html "> QualType</ a > > InnerMatcher</ td > </ tr >
4881
- < tr > < td colspan ="4 " class ="doc " id ="thisPointerType0 "> < pre > Matches if the expression's type either matches the specified
4882
- matcher, or is a pointer to a type that matches the InnerMatcher.
4908
+ < tr > < td colspan ="4 " class ="doc " id ="thisPointerType0 "> < pre > Matches if the type of the expression's implicit object argument either
4909
+ matches the InnerMatcher, or is a pointer to a type that matches the
4910
+ InnerMatcher.
4911
+
4912
+ Given
4913
+ class Y { public: void m(); };
4914
+ class X : public Y { void g(); };
4915
+ void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
4916
+ cxxMemberCallExpr(thisPointerType(hasDeclaration(
4917
+ cxxRecordDecl(hasName("Y")))))
4918
+ matches `y.m()`, `p->m()` and `x.m()`.
4919
+ cxxMemberCallExpr(thisPointerType(hasDeclaration(
4920
+ cxxRecordDecl(hasName("X")))))
4921
+ matches `x.g()`.
4883
4922
</ pre > </ td > </ tr >
4884
4923
4885
4924
@@ -5984,16 +6023,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
5984
6023
5985
6024
5986
6025
< tr > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html "> MemberExpr</ a > ></ td > < td class ="name " onclick ="toggle('hasObjectExpression0') "> < a name ="hasObjectExpression0Anchor "> hasObjectExpression</ a > </ td > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1Expr.html "> Expr</ a > > InnerMatcher</ td > </ tr >
5987
- < tr > < td colspan ="4 " class ="doc " id ="hasObjectExpression0 "> < pre > Matches a member expression where the object expression is
5988
- matched by a given matcher.
6026
+ < tr > < td colspan ="4 " class ="doc " id ="hasObjectExpression0 "> < pre > Matches a member expression where the object expression is matched by a
6027
+ given matcher. Implicit object expressions are included; that is, it matches
6028
+ use of implicit `this`.
5989
6029
5990
6030
Given
5991
- struct X { int m; };
5992
- void f(X x) { x.m; m; }
5993
- memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
5994
- matches "x.m" and "m"
5995
- with hasObjectExpression(...)
5996
- matching "x" and the implicit object expression of "m" which has type X*.
6031
+ struct X {
6032
+ int m;
6033
+ int f(X x) { x.m; return m; }
6034
+ };
6035
+ memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
6036
+ matches `x.m`, but not `m`; however,
6037
+ memberExpr(hasObjectExpression(hasType(pointsTo(
6038
+ cxxRecordDecl(hasName("X"))))))
6039
+ matches `m` (aka. `this->m`), but not `x.m`.
5997
6040
</ pre > </ td > </ tr >
5998
6041
5999
6042
@@ -6805,16 +6848,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
6805
6848
6806
6849
6807
6850
< tr > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html "> UnresolvedMemberExpr</ a > ></ td > < td class ="name " onclick ="toggle('hasObjectExpression1') "> < a name ="hasObjectExpression1Anchor "> hasObjectExpression</ a > </ td > < td > Matcher<< a href ="https://clang.llvm.org/doxygen/classclang_1_1Expr.html "> Expr</ a > > InnerMatcher</ td > </ tr >
6808
- < tr > < td colspan ="4 " class ="doc " id ="hasObjectExpression1 "> < pre > Matches a member expression where the object expression is
6809
- matched by a given matcher.
6851
+ < tr > < td colspan ="4 " class ="doc " id ="hasObjectExpression1 "> < pre > Matches a member expression where the object expression is matched by a
6852
+ given matcher. Implicit object expressions are included; that is, it matches
6853
+ use of implicit `this`.
6810
6854
6811
6855
Given
6812
- struct X { int m; };
6813
- void f(X x) { x.m; m; }
6814
- memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
6815
- matches "x.m" and "m"
6816
- with hasObjectExpression(...)
6817
- matching "x" and the implicit object expression of "m" which has type X*.
6856
+ struct X {
6857
+ int m;
6858
+ int f(X x) { x.m; return m; }
6859
+ };
6860
+ memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
6861
+ matches `x.m`, but not `m`; however,
6862
+ memberExpr(hasObjectExpression(hasType(pointsTo(
6863
+ cxxRecordDecl(hasName("X"))))))
6864
+ matches `m` (aka. `this->m`), but not `x.m`.
6818
6865
</ pre > </ td > </ tr >
6819
6866
6820
6867
0 commit comments