]> granicus.if.org Git - clang/commitdiff
Add AST Matchers for CXXConstructorDecl::isDelegatingConstructor and CXXMethodDecl...
authorAlexander Kornienko <alexfh@google.com>
Wed, 13 Apr 2016 11:13:08 +0000 (11:13 +0000)
committerAlexander Kornienko <alexfh@google.com>
Wed, 13 Apr 2016 11:13:08 +0000 (11:13 +0000)
Summary: Added two AST matchers: isDelegatingConstructor for CXXConstructorDecl::IsDelegatingConstructor; and isUserProvided corresponding to CXXMethodDecl::isUserProvided.

Reviewers: aaron.ballman, alexfh

Subscribers: klimek, cfe-commits

Patch by Michael Miller!

Differential Revision: http://reviews.llvm.org/D19038

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@266189 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LibASTMatchersReference.html
include/clang/ASTMatchers/ASTMatchers.h
unittests/ASTMatchers/ASTMatchersTest.cpp

index aaddb5b840bdd0806e3a6b80453a3e9029d85a3e..f31d9490cc511c41697fc268f3562e2c824fd156 100644 (file)
@@ -1799,6 +1799,21 @@ cxxConstructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isDelegatingConstructor0')"><a name="isDelegatingConstructor0Anchor">isDelegatingConstructor</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isDelegatingConstructor0"><pre>Matches constructors that delegate to another constructor.
+
+Given
+  struct S {
+    S(); #1
+    S(int) {} #2
+    S(S &amp;&amp;) : S() {} #3
+  };
+  S::S() : S(0) {} #4
+cxxConstructorDecl(isDelegatingConstructor()) will match #3 and #4, but not
+#1 or #2.
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicit0')"><a name="isExplicit0Anchor">isExplicit</a></td><td></td></tr>
 <tr><td colspan="4" class="doc" id="isExplicit0"><pre>Matches constructor and conversion declarations that are marked with
 the explicit keyword.
@@ -1983,6 +1998,19 @@ Given
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isUserProvided0')"><a name="isUserProvided0Anchor">isUserProvided</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isUserProvided0"><pre>Matches method declarations that are user-provided.
+
+Given
+  struct S {
+    S(); #1
+    S(const S &amp;) = default; #2
+    S(S &amp;&amp;) = delete; #3
+  };
+cxxConstructorDecl(isUserProvided()) will match #1, but not #2 or #3.
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isVirtual0')"><a name="isVirtual0Anchor">isVirtual</a></td><td></td></tr>
 <tr><td colspan="4" class="doc" id="isVirtual0"><pre>Matches if the given method declaration is virtual.
 
@@ -2538,7 +2566,7 @@ memberExpr(isArrow())
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>std::string Name</td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>std::string  Name</td></tr>
 <tr><td colspan="4" class="doc" id="hasName0"><pre>Matches NamedDecl nodes that have the specified name.
 
 Supports specifying enclosing namespaces or classes by prefixing the name
@@ -2731,13 +2759,20 @@ matches "a(char)", "b(wchar_t)", but not "c(double)".
 
 
 <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isAnyPointer0')"><a name="isAnyPointer0Anchor">isAnyPointer</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isAnyPointer0"><pre>Matches QualType nodes that are of any pointer type.
+<tr><td colspan="4" class="doc" id="isAnyPointer0"><pre>Matches QualType nodes that are of any pointer type; this includes
+the Objective-C object pointer type, which is different despite being
+syntactically similar.
 
 Given
   int *i = nullptr;
+
+  @interface Foo
+  @end
+  Foo *f;
+
   int j;
 varDecl(hasType(isAnyPointer()))
-  matches "int *i", but not "int j".
+  matches "int *i" and "Foo *f", but not "int j".
 </pre></td></tr>
 
 
@@ -3228,16 +3263,6 @@ expr(nullPointerConstant())
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;&gt;</td><td class="name" onclick="toggle('hasAnyName0')"><a name="hasAnyName0Anchor">hasAnyName</a></td><td>StringRef, ..., StringRef</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyName0"><pre>Matches NamedDecl nodes that have any of the specified names.
-
-This matcher is only provided as a performance optimization of hasName.
-    hasAnyName(a, b, c)
- is equivalent but faster than
-    anyOf(hasName(a), hasName(b), hasName(c))
-</pre></td></tr>
-
-
 <tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;&gt;</td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
 <tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation.
 
index 9a89cd1e38189f4e7c1a1753d5efcf669a789d70..2a734f14fb172f60df7bb5e3881666ee999b4bac 100644 (file)
@@ -3803,6 +3803,21 @@ AST_MATCHER(CXXMethodDecl, isOverride) {
   return Node.size_overridden_methods() > 0 || Node.hasAttr<OverrideAttr>();
 }
 
+/// \brief Matches method declarations that are user-provided.
+///
+/// Given
+/// \code
+///   struct S {
+///     S(); // #1
+///     S(const S &) = default; // #2
+///     S(S &&) = delete; // #3
+///   };
+/// \endcode
+/// cxxConstructorDecl(isUserProvided()) will match #1, but not #2 or #3.
+AST_MATCHER(CXXMethodDecl, isUserProvided) {
+  return Node.isUserProvided();
+}
+
 /// \brief Matches member expressions that are called with '->' as opposed
 /// to '.'.
 ///
@@ -4911,6 +4926,23 @@ AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
   return Node.isDefaultConstructor();
 }
 
+/// \brief Matches constructors that delegate to another constructor.
+///
+/// Given
+/// \code
+///   struct S {
+///     S(); // #1
+///     S(int) {} // #2
+///     S(S &&) : S() {} // #3
+///   };
+///   S::S() : S(0) {} // #4
+/// \endcode
+/// cxxConstructorDecl(isDelegatingConstructor()) will match #3 and #4, but not
+/// #1 or #2.
+AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) {
+  return Node.isDelegatingConstructor();
+}
+
 /// \brief Matches constructor and conversion declarations that are marked with
 /// the explicit keyword.
 ///
index e4b6bb170331fa2d83a7ecefe9c7cdd281568351..df818ba9422de00480a628b986289d785d096229 100644 (file)
@@ -2327,6 +2327,32 @@ TEST(ConstructorDeclaration, Kinds) {
                       cxxConstructorDecl(isMoveConstructor())));
 }
 
+TEST(ConstructorDeclaration, IsUserProvided) {
+  EXPECT_TRUE(notMatches("struct S { int X = 0; };",
+                         cxxConstructorDecl(isUserProvided())));
+  EXPECT_TRUE(notMatches("struct S { S() = default; };",
+                         cxxConstructorDecl(isUserProvided())));
+  EXPECT_TRUE(notMatches("struct S { S() = delete; };",
+                         cxxConstructorDecl(isUserProvided())));
+  EXPECT_TRUE(
+      matches("struct S { S(); };", cxxConstructorDecl(isUserProvided())));
+  EXPECT_TRUE(matches("struct S { S(); }; S::S(){}",
+                      cxxConstructorDecl(isUserProvided())));
+}
+
+TEST(ConstructorDeclaration, IsDelegatingConstructor) {
+  EXPECT_TRUE(notMatches("struct S { S(); S(int); int X; };",
+                         cxxConstructorDecl(isDelegatingConstructor())));
+  EXPECT_TRUE(notMatches("struct S { S(){} S(int X) : X(X) {} int X; };",
+                         cxxConstructorDecl(isDelegatingConstructor())));
+  EXPECT_TRUE(matches(
+      "struct S { S() : S(0) {} S(int X) : X(X) {} int X; };",
+      cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(0))));
+  EXPECT_TRUE(matches(
+      "struct S { S(); S(int X); int X; }; S::S(int X) : S() {}",
+      cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(1))));
+}
+
 TEST(DestructorDeclaration, MatchesVirtualDestructor) {
   EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
                       cxxDestructorDecl(ofClass(hasName("Foo")))));