From: Aaron Ballman Date: Tue, 11 Aug 2015 21:09:52 +0000 (+0000) Subject: Add a polymorphic AST matcher for testing whether a constructor or a conversion decla... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea8e04cc0df27076268292a256333b9f80812804;p=clang Add a polymorphic AST matcher for testing whether a constructor or a conversion declaration is marked as explicit or not. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244666 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 799b47af6f..954304efbc 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1483,6 +1483,19 @@ Example matches #1, but not #2 or #3 (matcher = constructorDecl(isDefaultConstru +Matcher<CXXConstructorDecl>isExplicit +
Matches a constructor declaration if it is marked explicit.
+
+Given
+  struct S {
+    S(int); // #1
+    explicit S(double); // #2
+  };
+constructorDecl(isExplicit())
+  will match #2, but not #1.
+
+ + Matcher<CXXConstructorDecl>isMoveConstructor
Matches constructor declarations that are move constructors.
 
@@ -1495,6 +1508,19 @@ Example matches #3, but not #1 or #2 (matcher = constructorDecl(isMoveConstructo
 
+Matcher<CXXConversionDecl>isExplicit +
Matches a conversion declaration if it is marked explicit.
+
+Given
+  struct S {
+    operator int(); // #1
+    explicit operator bool(); // #2
+  };
+conversionDecl(isExplicit())
+  will match #2, but not #1.
+
+ + Matcher<CXXCtorInitializer>isBaseInitializer
Matches a constructor initializer if it is initializing a base, as opposed to a member.
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 778e1f4dfe..4aec6c1f44 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -4189,6 +4189,27 @@ AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
   return Node.isDefaultConstructor();
 }
 
+/// \brief Matches constructor and conversion declarations that are marked with
+/// the explicit keyword.
+///
+/// Given
+/// \code
+///   struct S {
+///     S(int); // #1
+///     explicit S(double); // #2
+///     operator int(); // #3
+///     explicit operator bool(); // #4
+///   };
+/// \endcode
+/// constructorDecl(isExplicit()) will match #2, but not #1.
+/// conversionDecl(isExplicit()) will match #4, but not #3.
+AST_POLYMORPHIC_MATCHER(isExplicit,
+                        AST_POLYMORPHIC_SUPPORTED_TYPES(CXXConstructorDecl,
+                                                        CXXConversionDecl)) {
+  return Node.isExplicit();
+
+}
+
 /// \brief If the given case statement does not use the GNU case range
 /// extension, matches the constant given in the statement.
 ///
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 7e3df2dfd9..be04ed4763 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -249,6 +249,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isDefinition);
   REGISTER_MATCHER(isDeleted);
   REGISTER_MATCHER(isExceptionVariable);
+  REGISTER_MATCHER(isExplicit);
   REGISTER_MATCHER(isExplicitTemplateSpecialization);
   REGISTER_MATCHER(isExpr);
   REGISTER_MATCHER(isExternC);
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index d51a5e28b5..f0eede8a78 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -1420,6 +1420,13 @@ TEST(Callee, MatchesDeclarations) {
                          CallMethodX));
 }
 
+TEST(ConversionDeclaration, IsExplicit) {
+  EXPECT_TRUE(matches("struct S { explicit operator int(); };",
+                      conversionDecl(isExplicit())));
+  EXPECT_TRUE(notMatches("struct S { operator int(); };",
+                         conversionDecl(isExplicit())));
+}
+
 TEST(Callee, MatchesMemberExpressions) {
   EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
               callExpr(callee(memberExpr()))));
@@ -1992,6 +1999,13 @@ TEST(ConstructorDeclaration, IsImplicit) {
                       methodDecl(isImplicit(), hasName("operator="))));
 }
 
+TEST(ConstructorDeclaration, IsExplicit) {
+  EXPECT_TRUE(matches("struct S { explicit S(int); };",
+                      constructorDecl(isExplicit())));
+  EXPECT_TRUE(notMatches("struct S { S(int); };",
+                         constructorDecl(isExplicit())));
+}
+
 TEST(ConstructorDeclaration, Kinds) {
   EXPECT_TRUE(matches("struct S { S(); };",
                       constructorDecl(isDefaultConstructor())));