Author: Karasev Nikita Date: 2020-01-29T07:58:31-05:00 New Revision: d5dfd1350efb80f9674db322999dd883fb36a6ad
URL: https://github.com/llvm/llvm-project/commit/d5dfd1350efb80f9674db322999dd883fb36a6ad DIFF: https://github.com/llvm/llvm-project/commit/d5dfd1350efb80f9674db322999dd883fb36a6ad.diff LOG: Add TagDecl AST matcher Added: Modified: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp Removed: ################################################################################ diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 837f74ea0d41..907353d1d9bb 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -502,6 +502,20 @@ <h2 id="decl-matchers">Node Matchers</h2> </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('tagDecl0')"><a name="tagDecl0Anchor">tagDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="tagDecl0"><pre>Matches tag declarations. + +Example matches X, Z, U, S, E + class X; + template<class T> class Z {}; + struct S {}; + union U {}; + enum E { + A, B, C + }; +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('templateTypeParmDecl0')"><a name="templateTypeParmDecl0Anchor">templateTypeParmDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmDecl.html">TemplateTypeParmDecl</a>>...</td></tr> <tr><td colspan="4" class="doc" id="templateTypeParmDecl0"><pre>Matches template type parameter declarations. @@ -3957,36 +3971,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>></td><td class="name" onclick="toggle('isClass0')"><a name="isClass0Anchor">isClass</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isClass0"><pre>Matches RecordDecl object that are spelled with "class." - -Example matches C, but not S or U. - struct S {}; - class C {}; - union U {}; -</pre></td></tr> - - -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>></td><td class="name" onclick="toggle('isStruct0')"><a name="isStruct0Anchor">isStruct</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isStruct0"><pre>Matches RecordDecl object that are spelled with "struct." - -Example matches S, but not C or U. - struct S {}; - class C {}; - union U {}; -</pre></td></tr> - - -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>></td><td class="name" onclick="toggle('isUnion0')"><a name="isUnion0Anchor">isUnion</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isUnion0"><pre>Matches RecordDecl object that are spelled with "union." - -Example matches U, but not C or S. - struct S {}; - class C {}; - union U {}; -</pre></td></tr> - - <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('equalsBoundNode0')"><a name="equalsBoundNode0Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr> <tr><td colspan="4" class="doc" id="equalsBoundNode0"><pre>Matches if a node equals a previously bound node. @@ -4090,6 +4074,17 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isClass0')"><a name="isClass0Anchor">isClass</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isClass0"><pre>Matches TagDecl object that are spelled with "class." + +Example matches C, but not S, U or E. + struct S {}; + class C {}; + union U {}; + enum E {}; +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isDefinition0')"><a name="isDefinition0Anchor">isDefinition</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isDefinition0"><pre>Matches if a declaration has a body attached. @@ -4112,6 +4107,39 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isEnum0')"><a name="isEnum0Anchor">isEnum</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isEnum0"><pre>Matches TagDecl object that are spelled with "enum." + +Example matches E, but not C, S or U. + struct S {}; + class C {}; + union U {}; + enum E {}; +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isStruct0')"><a name="isStruct0Anchor">isStruct</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isStruct0"><pre>Matches TagDecl object that are spelled with "struct." + +Example matches S, but not C, U or E. + struct S {}; + class C {}; + union U {}; + enum E {}; +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isUnion0')"><a name="isUnion0Anchor">isUnion</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isUnion0"><pre>Matches TagDecl object that are spelled with "union." + +Example matches U, but not C, S or E. + struct S {}; + class C {}; + union U {}; + enum E {}; +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>></td><td class="name" onclick="toggle('equalsIntegralValue0')"><a name="equalsIntegralValue0Anchor">equalsIntegralValue</a></td><td>std::string Value</td></tr> <tr><td colspan="4" class="doc" id="equalsIntegralValue0"><pre>Matches a TemplateArgument of integral type with a given value. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index ac6ce076d60d..f105586a4d62 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1195,6 +1195,20 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> enumConstantDecl; +/// Matches tag declarations. +/// +/// Example matches X, Z, U, S, E +/// \code +/// class X; +/// template<class T> class Z {}; +/// struct S {}; +/// union U {}; +/// enum E { +/// A, B, C +/// }; +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Decl, TagDecl> tagDecl; + /// Matches method declarations. /// /// Example matches y @@ -4863,42 +4877,58 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, return InnerMatcher.matches(Node.getType(), Finder, Builder); } -/// Matches RecordDecl object that are spelled with "struct." +/// Matches TagDecl object that are spelled with "struct." /// -/// Example matches S, but not C or U. +/// Example matches S, but not C, U or E. /// \code /// struct S {}; /// class C {}; /// union U {}; +/// enum E {}; /// \endcode -AST_MATCHER(RecordDecl, isStruct) { +AST_MATCHER(TagDecl, isStruct) { return Node.isStruct(); } -/// Matches RecordDecl object that are spelled with "union." +/// Matches TagDecl object that are spelled with "union." /// -/// Example matches U, but not C or S. +/// Example matches U, but not C, S or E. /// \code /// struct S {}; /// class C {}; /// union U {}; +/// enum E {}; /// \endcode -AST_MATCHER(RecordDecl, isUnion) { +AST_MATCHER(TagDecl, isUnion) { return Node.isUnion(); } -/// Matches RecordDecl object that are spelled with "class." +/// Matches TagDecl object that are spelled with "class." /// -/// Example matches C, but not S or U. +/// Example matches C, but not S, U or E. /// \code /// struct S {}; /// class C {}; /// union U {}; +/// enum E {}; /// \endcode -AST_MATCHER(RecordDecl, isClass) { +AST_MATCHER(TagDecl, isClass) { return Node.isClass(); } +/// Matches TagDecl object that are spelled with "enum." +/// +/// Example matches E, but not C, S or U. +/// \code +/// struct S {}; +/// class C {}; +/// union U {}; +/// enum E {}; +/// \endcode +AST_MATCHER(TagDecl, isEnum) { + return Node.isEnum(); +} + /// Matches the true branch expression of a conditional operator. /// /// Example 1 (conditional ternary operator): matches a diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 3631922a5abf..b09ab752719b 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -650,6 +650,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> enumConstantDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, TagDecl> tagDecl; const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> cxxConversionDecl; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index cd3f34630f8d..4fd5abffc791 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -493,6 +493,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(substTemplateTypeParmType); REGISTER_MATCHER(switchCase); REGISTER_MATCHER(switchStmt); + REGISTER_MATCHER(tagDecl); REGISTER_MATCHER(tagType); REGISTER_MATCHER(templateArgument); REGISTER_MATCHER(templateArgumentCountIs); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 92678a309196..479680987fd0 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -2504,6 +2504,13 @@ TEST(IsScopedEnum, MatchesScopedEnum) { EXPECT_TRUE(notMatches("enum X {};", enumDecl(isScoped()))); } +TEST(TagDeclKind, MatchesTagDeclKind) { + EXPECT_TRUE(matches("struct X {};", tagDecl(isStruct()))); + EXPECT_TRUE(matches("class C {};", tagDecl(isClass()))); + EXPECT_TRUE(matches("union U {};", tagDecl(isUnion()))); + EXPECT_TRUE(matches("enum E {};", tagDecl(isEnum()))); +} + TEST(HasTrailingReturn, MatchesTrailingReturn) { EXPECT_TRUE(matches("auto Y() -> int { return 0; }", functionDecl(hasTrailingReturn()))); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index b37ec2705406..1fdaf66f285c 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -184,6 +184,13 @@ TEST(EnumConstant, Matches) { EXPECT_TRUE(notMatches("enum X {};", Matcher)); } +TEST(TagDecl, MatchesTagDecls) { + EXPECT_TRUE(matches("struct X {};", tagDecl(hasName("X")))); + EXPECT_TRUE(matches("class C {};", tagDecl(hasName("C")))); + EXPECT_TRUE(matches("union U {};", tagDecl(hasName("U")))); + EXPECT_TRUE(matches("enum E {};", tagDecl(hasName("E")))); +} + TEST(Matcher, UnresolvedLookupExpr) { // FIXME: The test is known to be broken on Windows with delayed template // parsing. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits