Skip to content

Commit 8a43680

Browse files
committed
[ASTMatchers][NFC] Update comments on assorted CXXMemberCallExpr matchers.
Specifically: * fixes the comments on `hasObjectExpression`, * clarifies comments on `thisPointerType` and `on`, * adds comments to `onImplicitObjectArgument`. It also updates associated reference docs (using the doc tool). Reviewers: alexfh, steveire, aaron.ballman Differential Revision: https://reviews.llvm.org/D56849 llvm-svn: 353532
1 parent 30b7d09 commit 8a43680

File tree

2 files changed

+137
-47
lines changed

2 files changed

+137
-47
lines changed

clang/docs/LibASTMatchersReference.html

+79-32
Original file line numberDiff line numberDiff line change
@@ -4810,16 +4810,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
48104810

48114811

48124812
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasObjectExpression2')"><a name="hasObjectExpression2Anchor">hasObjectExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; 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`.
48154816

48164817
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-&gt;m`), but not `x.m`.
48234827
</pre></td></tr>
48244828

48254829

@@ -4857,16 +4861,39 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
48574861

48584862

48594863
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('onImplicitObjectArgument0')"><a name="onImplicitObjectArgument0Anchor">onImplicitObjectArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; 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>
48614880

48624881

48634882
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('on0')"><a name="on0Anchor">on</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; 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.
48654885

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()`.
48704897

48714898
FIXME: Overload to allow directly matching types?
48724899
</pre></td></tr>
@@ -4878,8 +4905,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
48784905

48794906

48804907
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('thisPointerType0')"><a name="thisPointerType0Anchor">thisPointerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; 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-&gt;m(); X x; x.m(); x.g(); }
4916+
cxxMemberCallExpr(thisPointerType(hasDeclaration(
4917+
cxxRecordDecl(hasName("Y")))))
4918+
matches `y.m()`, `p-&gt;m()` and `x.m()`.
4919+
cxxMemberCallExpr(thisPointerType(hasDeclaration(
4920+
cxxRecordDecl(hasName("X")))))
4921+
matches `x.g()`.
48834922
</pre></td></tr>
48844923

48854924

@@ -5984,16 +6023,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
59846023

59856024

59866025
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasObjectExpression0')"><a name="hasObjectExpression0Anchor">hasObjectExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; 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`.
59896029

59906030
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-&gt;m`), but not `x.m`.
59976040
</pre></td></tr>
59986041

59996042

@@ -6805,16 +6848,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
68056848

68066849

68076850
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html">UnresolvedMemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasObjectExpression1')"><a name="hasObjectExpression1Anchor">hasObjectExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; 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`.
68106854

68116855
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-&gt;m`), but not `x.m`.
68186865
</pre></td></tr>
68196866

68206867

clang/include/clang/ASTMatchers/ASTMatchers.h

+58-15
Original file line numberDiff line numberDiff line change
@@ -2886,14 +2886,22 @@ AST_MATCHER_P(NamedDecl, hasUnderlyingDecl, internal::Matcher<NamedDecl>,
28862886
InnerMatcher.matches(*UnderlyingDecl, Finder, Builder);
28872887
}
28882888

2889-
/// Matches on the implicit object argument of a member call expression.
2889+
/// Matches on the implicit object argument of a member call expression, after
2890+
/// stripping off any parentheses or implicit casts.
28902891
///
2891-
/// Example matches y.x()
2892-
/// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
2892+
/// Given
28932893
/// \code
2894-
/// class Y { public: void x(); };
2895-
/// void z() { Y y; y.x(); }
2894+
/// class Y { public: void m(); };
2895+
/// Y g();
2896+
/// class X : public Y {};
2897+
/// void z(Y y, X x) { y.m(); (g()).m(); x.m(); }
28962898
/// \endcode
2899+
/// cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))
2900+
/// matches `y.m()` and `(g()).m()`.
2901+
/// cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))))
2902+
/// matches `x.m()`.
2903+
/// cxxMemberCallExpr(on(callExpr()))
2904+
/// matches `(g()).m()`.
28972905
///
28982906
/// FIXME: Overload to allow directly matching types?
28992907
AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
@@ -3253,15 +3261,46 @@ AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
32533261
.matches(Node, Finder, Builder);
32543262
}
32553263

3264+
/// Matches on the implicit object argument of a member call expression. Unlike
3265+
/// `on`, matches the argument directly without stripping away anything.
3266+
///
3267+
/// Given
3268+
/// \code
3269+
/// class Y { public: void m(); };
3270+
/// Y g();
3271+
/// class X : public Y { void g(); };
3272+
/// void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); }
3273+
/// \endcode
3274+
/// cxxMemberCallExpr(onImplicitObjectArgument(hasType(
3275+
/// cxxRecordDecl(hasName("Y")))))
3276+
/// matches `y.m()`, `x.m()` and (g()).m(), but not `x.g()`.
3277+
/// cxxMemberCallExpr(on(callExpr()))
3278+
/// does not match `(g()).m()`, because the parens are not ignored.
3279+
///
3280+
/// FIXME: Overload to allow directly matching types?
32563281
AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
32573282
internal::Matcher<Expr>, InnerMatcher) {
32583283
const Expr *ExprNode = Node.getImplicitObjectArgument();
32593284
return (ExprNode != nullptr &&
32603285
InnerMatcher.matches(*ExprNode, Finder, Builder));
32613286
}
32623287

3263-
/// Matches if the expression's type either matches the specified
3264-
/// matcher, or is a pointer to a type that matches the InnerMatcher.
3288+
/// Matches if the type of the expression's implicit object argument either
3289+
/// matches the InnerMatcher, or is a pointer to a type that matches the
3290+
/// InnerMatcher.
3291+
///
3292+
/// Given
3293+
/// \code
3294+
/// class Y { public: void m(); };
3295+
/// class X : public Y { void g(); };
3296+
/// void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
3297+
/// \endcode
3298+
/// cxxMemberCallExpr(thisPointerType(hasDeclaration(
3299+
/// cxxRecordDecl(hasName("Y")))))
3300+
/// matches `y.m()`, `p->m()` and `x.m()`.
3301+
/// cxxMemberCallExpr(thisPointerType(hasDeclaration(
3302+
/// cxxRecordDecl(hasName("X")))))
3303+
/// matches `x.g()`.
32653304
AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
32663305
internal::Matcher<QualType>, InnerMatcher, 0) {
32673306
return onImplicitObjectArgument(
@@ -4963,18 +5002,22 @@ AST_MATCHER_P(MemberExpr, member,
49635002
return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
49645003
}
49655004

4966-
/// Matches a member expression where the object expression is
4967-
/// matched by a given matcher.
5005+
/// Matches a member expression where the object expression is matched by a
5006+
/// given matcher. Implicit object expressions are included; that is, it matches
5007+
/// use of implicit `this`.
49685008
///
49695009
/// Given
49705010
/// \code
4971-
/// struct X { int m; };
4972-
/// void f(X x) { x.m; m; }
5011+
/// struct X {
5012+
/// int m;
5013+
/// int f(X x) { x.m; return m; }
5014+
/// };
49735015
/// \endcode
4974-
/// memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
4975-
/// matches "x.m" and "m"
4976-
/// with hasObjectExpression(...)
4977-
/// matching "x" and the implicit object expression of "m" which has type X*.
5016+
/// memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
5017+
/// matches `x.m`, but not `m`; however,
5018+
/// memberExpr(hasObjectExpression(hasType(pointsTo(
5019+
// cxxRecordDecl(hasName("X"))))))
5020+
/// matches `m` (aka. `this->m`), but not `x.m`.
49785021
AST_POLYMORPHIC_MATCHER_P(
49795022
hasObjectExpression,
49805023
AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr,

0 commit comments

Comments
 (0)