]> granicus.if.org Git - clang/commitdiff
Add a polymorphic AST matcher for testing whether a constructor or a conversion decla...
authorAaron Ballman <aaron@aaronballman.com>
Tue, 11 Aug 2015 21:09:52 +0000 (21:09 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Tue, 11 Aug 2015 21:09:52 +0000 (21:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244666 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 799b47af6fd3841962e9270cfa9e8604c6e45402..954304efbccdd943b2a6ff80c349c08f8514a309 100644 (file)
@@ -1483,6 +1483,19 @@ Example matches #1, but not #2 or #3 (matcher = constructorDecl(isDefaultConstru
 </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 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.
+</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('isMoveConstructor1')"><a name="isMoveConstructor1Anchor">isMoveConstructor</a></td><td></td></tr>
 <tr><td colspan="4" class="doc" id="isMoveConstructor1"><pre>Matches constructor declarations that are move constructors.
 
@@ -1495,6 +1508,19 @@ Example matches #3, but not #1 or #2 (matcher = constructorDecl(isMoveConstructo
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConversionDecl.html">CXXConversionDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicit1')"><a name="isExplicit1Anchor">isExplicit</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isExplicit1"><pre>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.
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('isBaseInitializer0')"><a name="isBaseInitializer0Anchor">isBaseInitializer</a></td><td></td></tr>
 <tr><td colspan="4" class="doc" id="isBaseInitializer0"><pre>Matches a constructor initializer if it is initializing a base, as opposed to a member.
 
index 778e1f4dfe7c0d2cc37ce8b54725788dca83a072..4aec6c1f445144512b07a620b2543f2d139cb5b1 100644 (file)
@@ -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.
 ///
index 7e3df2dfd9a34f2d4ae13aba7a8af4af072e3760..be04ed476333e42643fc0e14fe0e91f7e627087f 100644 (file)
@@ -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);
index d51a5e28b5e5bc9886692e3d2f8c8ccf2dcb1454..f0eede8a788fe2d10adec0184731a7aae32bd307 100644 (file)
@@ -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())));