Index: cfe/trunk/docs/LibASTMatchersReference.html =================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html +++ cfe/trunk/docs/LibASTMatchersReference.html @@ -1799,6 +1799,21 @@ +Matcher<CXXConstructorDecl>isDelegatingConstructor +
Matches constructors that delegate to another constructor.
+
+Given
+  struct S {
+    S(); #1
+    S(int) {} #2
+    S(S &&) : S() {} #3
+  };
+  S::S() : S(0) {} #4
+cxxConstructorDecl(isDelegatingConstructor()) will match #3 and #4, but not
+#1 or #2.
+
+ + Matcher<CXXConstructorDecl>isExplicit
Matches constructor and conversion declarations that are marked with
 the explicit keyword.
@@ -1983,6 +1998,19 @@
 
+Matcher<CXXMethodDecl>isUserProvided +
Matches method declarations that are user-provided.
+
+Given
+  struct S {
+    S(); #1
+    S(const S &) = default; #2
+    S(S &&) = delete; #3
+  };
+cxxConstructorDecl(isUserProvided()) will match #1, but not #2 or #3.
+
+ + Matcher<CXXMethodDecl>isVirtual
Matches if the given method declaration is virtual.
 
@@ -2538,7 +2566,7 @@
 
-Matcher<NamedDecl>hasNamestd::string Name +Matcher<NamedDecl>hasNamestd::string Name
Matches NamedDecl nodes that have the specified name.
 
 Supports specifying enclosing namespaces or classes by prefixing the name
@@ -2731,13 +2759,20 @@
 
 
 Matcher<QualType>isAnyPointer
-
Matches QualType nodes that are of any pointer type.
+
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".
 
@@ -3228,16 +3263,6 @@
-Matcher<internal::Matcher<NamedDecl>>hasAnyNameStringRef, ..., StringRef -
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))
-
- - Matcher<internal::Matcher<Stmt>>isInTemplateInstantiation
Matches statements inside of a template instantiation.
 
Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
@@ -3803,6 +3803,21 @@
   return Node.size_overridden_methods() > 0 || Node.hasAttr();
 }
 
+/// \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 @@
   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: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -2327,6 +2327,32 @@
                       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")))));