[clang] d5dfd13 - Add TagDecl AST matcher
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 29 04:58:42 PST 2020
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.
More information about the cfe-commits
mailing list