Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1194,6 +1194,20 @@ extern const internal::VariadicDynCastAllOfMatcher enumConstantDecl; +/// Matches tag declarations. +/// +/// Example matches X, Z, U, S, E +/// \code +/// class X; +/// template class Z {}; +/// struct S {}; +/// union U {}; +/// enum E { +/// A, B, C +/// }; +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher tagDecl; + /// Matches method declarations. /// /// Example matches y @@ -4845,42 +4859,58 @@ 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 Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -647,6 +647,7 @@ const internal::VariadicDynCastAllOfMatcher enumDecl; const internal::VariadicDynCastAllOfMatcher enumConstantDecl; +const internal::VariadicDynCastAllOfMatcher tagDecl; const internal::VariadicDynCastAllOfMatcher cxxMethodDecl; const internal::VariadicDynCastAllOfMatcher cxxConversionDecl; Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -208,6 +208,8 @@ REGISTER_MATCHER(doStmt); REGISTER_MATCHER(eachOf); REGISTER_MATCHER(elaboratedType); + REGISTER_MATCHER(tagDecl); + REGISTER_MATCHER(tagType); REGISTER_MATCHER(enumConstantDecl); REGISTER_MATCHER(enumDecl); REGISTER_MATCHER(enumType); Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -2504,6 +2504,13 @@ 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()))); Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -184,6 +184,13 @@ 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.