Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -163,11 +163,35 @@ /// Given /// \code /// typedef int X; +// using Y = int; /// \endcode /// typedefDecl() -/// matches "typedef int X" +/// matches "typedef int X", but not "using Y = int" const internal::VariadicDynCastAllOfMatcher typedefDecl; +/// \brief Matches typedef name declarations. +/// +/// Given +/// \code +/// typedef int X; +// using Y = int; +/// \endcode +/// typedefNameDecl() +/// matches "typedef int X" and "using Y = int" +const internal::VariadicDynCastAllOfMatcher + typedefNameDecl; + +/// \brief Matches type alias declarations. +/// +/// Given +/// \code +/// typedef int X; +// using Y = int; +/// \endcode +/// typeAliasDecl() +/// matches "using Y = int", but not "typedef int X" +const internal::VariadicDynCastAllOfMatcher typeAliasDecl; + /// \brief Matches AST nodes that were expanded within the main-file. /// /// Example matches X but not Y @@ -2451,9 +2475,9 @@ /// typedef int U; /// \endcode AST_POLYMORPHIC_MATCHER_P_OVERLOAD( - hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefDecl, ValueDecl), + hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefNameDecl, ValueDecl), internal::Matcher, InnerMatcher, 0) { - return InnerMatcher.matches(internal::getUnderlyingType(Node), + return InnerMatcher.matches(internal::getUnderlyingType(Node), Finder, Builder); } Index: include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- include/clang/ASTMatchers/ASTMatchersInternal.h +++ include/clang/ASTMatchers/ASTMatchersInternal.h @@ -96,12 +96,13 @@ /// \brief Unifies obtaining the underlying type of a regular node through /// `getType` and a TypedefNameDecl node through `getUnderlyingType`. -template -inline QualType getUnderlyingType(const NodeType &Node) { +inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); } + +inline QualType getUnderlyingType(const ValueDecl &Node) { return Node.getType(); } -template <> inline QualType getUnderlyingType(const TypedefDecl &Node) { +inline QualType getUnderlyingType(const TypedefNameDecl &Node) { return Node.getUnderlyingType(); } Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -388,7 +388,9 @@ REGISTER_MATCHER(translationUnitDecl); REGISTER_MATCHER(type); REGISTER_MATCHER(typedefDecl); + REGISTER_MATCHER(typedefNameDecl); REGISTER_MATCHER(typedefType); + REGISTER_MATCHER(typeAliasDecl); REGISTER_MATCHER(typeLoc); REGISTER_MATCHER(unaryExprOrTypeTraitExpr); REGISTER_MATCHER(unaryOperator); Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1101,6 +1101,16 @@ typedefDecl(hasType(asString("foo")), hasName("bar")))); } +TEST(HasType, MatchesTypedefNameDecl) { + EXPECT_TRUE(matches("using X = int;", typedefNameDecl(hasType(asString("int"))))); + EXPECT_TRUE(matches("using T = const int;", + typedefNameDecl(hasType(asString("const int"))))); + EXPECT_TRUE(notMatches("using T = const int;", + typedefNameDecl(hasType(asString("int"))))); + EXPECT_TRUE(matches("using foo = int; using bar = foo;", + typedefNameDecl(hasType(asString("foo")), hasName("bar")))); +} + TEST(HasTypeLoc, MatchesDeclaratorDecls) { EXPECT_TRUE(matches("int x;", varDecl(hasName("x"), hasTypeLoc(loc(asString("int")))))); @@ -5404,9 +5414,25 @@ .bind("data"))); } -TEST(TypeDefDeclMatcher, Match) { +TEST(TypedefDeclMatcher, Match) { EXPECT_TRUE(matches("typedef int typedefDeclTest;", typedefDecl(hasName("typedefDeclTest")))); + EXPECT_FALSE(matches("using typedefDeclTest2 = int;", + typedefDecl(hasName("typedefDeclTest2")))); +} + +TEST(TypeAliasDeclMatcher, Match) { + EXPECT_TRUE(matches("using typeAliasTest2 = int;", + typeAliasDecl(hasName("typeAliasTest2")))); + EXPECT_FALSE(matches("typedef int typeAliasTest;", + typeAliasDecl(hasName("typeAliasTest")))); +} + +TEST(TypedefNameDeclMatcher, Match) { + EXPECT_TRUE(matches("typedef int typedefNameDeclTest1;", + typedefNameDecl(hasName("typedefNameDeclTest1")))); + EXPECT_TRUE(matches("using typedefNameDeclTest2 = int;", + typedefNameDecl(hasName("typedefNameDeclTest2")))); } TEST(IsInlineMatcher, IsInline) {