ymandel updated this revision to Diff 183591.
ymandel added a comment.

Contrast to thisPointerType with explicit examples.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56851/new/

https://reviews.llvm.org/D56851

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -470,6 +470,35 @@
 
 }
 
+TEST(MatcherCXXMemberCallExpr, InvokedAtType) {
+  auto M = cxxMemberCallExpr(invokedAtType(cxxRecordDecl(hasName("Y"))));
+  EXPECT_TRUE(matches(
+      R"cc(
+        struct Y {
+          void m();
+        };
+        void z(Y y) { y.m(); }
+      )cc",
+      M));
+  EXPECT_TRUE(matches(
+      R"cc(
+        struct Y {
+          void m();
+        };
+        void z(Y *y) { y->m(); }
+      )cc",
+      M));
+  EXPECT_TRUE(notMatches(
+      R"cc(
+        struct Y {
+          void m();
+        };
+        struct X : public Y {};
+        void z(X x) { x.m(); }
+      )cc",
+      M));
+}
+
 TEST(ForEachArgumentWithParam, ReportsNoFalsePositives) {
   StatementMatcher ArgumentY =
     declRefExpr(to(varDecl(hasName("y")))).bind("arg");
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3278,6 +3278,49 @@
       .matches(Node, Finder, Builder);
 }
 
+/// Matches if the type of the object expression (as written, without any
+/// implicit casts) either matches the InnerMatcher, or is a pointer to a
+/// type that matches the InnerMatcher. Differs from `thisPointerType` in that
+/// it matches against the type of the written object expression, which could be
+/// a subclass of the this-pointer type (like when the invoked member is
+/// inherited).
+///
+/// Given
+/// \code
+///   class Y { public: void m(); };
+///   class X : public Y {};
+///   void z() { Y y; y.m(); X x; x.m(); X *p; p->m(); }
+/// \endcode
+/// cxxMemberCallExpr(onOrPointsToType(hasDeclaration(
+///     cxxRecordDecl(hasName("Y")))))
+///   matches `y.m()`.
+/// cxxMemberCallExpr(thisPointerType(hasDeclaration(
+///     cxxRecordDecl(hasName("Y")))))
+///   matches `y.m()`, `x.m()` and `p->m()`.
+///
+/// cxxMemberCallExpr(onOrPointsToType(hasDeclaration(
+///     cxxRecordDecl(hasName("X")))))
+///   matches `x.m()` and `p->m()`.
+/// cxxMemberCallExpr(thisPointerType(hasDeclaration(
+///     cxxRecordDecl(hasName("X")))))
+///   matches nothing because the `this` type is `Y` in all three calls.
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, onOrPointsToType,
+                       internal::Matcher<QualType>, InnerMatcher, 0) {
+  return on(anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+      .matches(Node, Finder, Builder);
+}
+
+/// Overloaded to match the type's declaration. With this overload, the above
+/// examples could be simplified to:
+///
+/// cxxMemberCallExpr(onOrPointsToType(cxxRecordDecl(hasName("Y"))))
+/// cxxMemberCallExpr(onOrPointsToType(cxxRecordDecl(hasName("X"))))
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, onOrPointsToType, DeclarationMatcher,
+                       InnerMatcher, 1) {
+  return on(anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+      .matches(Node, Finder, Builder);
+}
+
 /// Matches a DeclRefExpr that refers to a declaration that matches the
 /// specified matcher.
 ///
Index: clang/docs/LibASTMatchersReference.html
===================================================================
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -4224,6 +4224,11 @@
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;clang::CXXMemberCallExpr&gt;</td><td class="name" onclick="toggle('invokedAtType1')"><a name="invokedAtType1Anchor">invokedAtType</a></td><td>clang::ast_matchers::DeclarationMatcher InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="invokedAtType1"><pre>Overloaded to match the type's declaration.
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html";>Decl</a>&gt;&gt;</td><td class="name" onclick="toggle('isInstantiated0')"><a name="isInstantiated0Anchor">isInstantiated</a></td><td></td></tr>
 <tr><td colspan="4" class="doc" id="isInstantiated0"><pre>Matches declarations that are template instantiations or are inside
 template instantiations.
@@ -6956,6 +6961,27 @@
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;clang::CXXMemberCallExpr&gt;</td><td class="name" onclick="toggle('invokedAtType0')"><a name="invokedAtType0Anchor">invokedAtType</a></td><td>clang::ast_matchers::Matcher&lt;clang::QualType&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="invokedAtType0"><pre>Matches if the type of the object expression (as written, without any
+implicit casts) either matches the InnerMatcher, or is a pointer to a
+type that matches the InnerMatcher. Differs from `thisPointerType` in that
+it matches against the type of the written object expression, which could be
+a subclass of the thisPointerType (like when the invoked member is
+inherited).
+
+Given
+  class Y { public: void m(); };
+  class X : public Y {};
+  void z() { Y y; y.m(); X x; x.m(); X *p; p-&gt;m(); }
+cxxMemberCallExpr(invokedAtType(hasDeclaration(
+    cxxRecordDecl(hasName("Y")))))
+  matches `y.m()`.
+cxxMemberCallExpr(invokedAtType(hasDeclaration(
+    cxxRecordDecl(hasName("X")))))
+  matches `x.m()` and `p-&gt;m()`.
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;internal::BindableMatcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html";>NestedNameSpecifierLoc</a>&gt;&gt;</td><td class="name" onclick="toggle('loc1')"><a name="loc1Anchor">loc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html";>NestedNameSpecifier</a>&gt; InnerMatcher</td></tr>
 <tr><td colspan="4" class="doc" id="loc1"><pre>Matches NestedNameSpecifierLocs for which the given inner
 NestedNameSpecifier-matcher matches.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to