diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 8564f2650d20..fc5578880132 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -2546,6 +2546,17 @@ Example matches T::type }; +
Matches a dependent template specialization type. + +Example matches A::template B + + template struct A; + template struct declToImport { + typename A ::template B a; + }; +
Matches C++17 deduced template specialization types, e.g. deduced class template types. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 61d6aa2216cd..5e75fc447636 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1114,6 +1114,8 @@ AST Matchers - Add ``dependentNameType`` matcher to match a dependent name type. +- Add ``dependentTemplateSpecializationType`` matcher to match a dependent template specialization type. + clang-format ------------ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 9a046714068a..dd0fedb2cda2 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -7721,6 +7721,18 @@ AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher, /// \endcode extern const AstTypeMatcher dependentNameType; +/// Matches a dependent template specialization type +/// +/// Example matches A ::template B +/// \code +/// template struct A; +/// template struct declToImport { +/// typename A ::template B a; +/// }; +/// \endcode +extern const AstTypeMatcher + dependentTemplateSpecializationType; + /// Matches declarations whose declaration context, interpreted as a /// Decl, matches \c InnerMatcher. /// diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index a47633bf4bae..9c7943a98d65 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -1109,6 +1109,8 @@ const AstTypeMatcher templateTypeParmType; const AstTypeMatcher injectedClassNameType; const AstTypeMatcher decayedType; const AstTypeMatcher dependentNameType; +const AstTypeMatcher + dependentTemplateSpecializationType; AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasElementType, AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType, ComplexType)); diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index bfdee412c532..97e6bbc093fe 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -224,6 +224,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(declRefExpr); REGISTER_MATCHER(dependentNameType); REGISTER_MATCHER(dependentScopeDeclRefExpr); + REGISTER_MATCHER(dependentTemplateSpecializationType); REGISTER_MATCHER(declStmt); REGISTER_MATCHER(declaratorDecl); REGISTER_MATCHER(decltypeType); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index ee1d896f1ca6..d197d30df3ad 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -763,10 +763,6 @@ TEST_P(ImportType, ImportPackExpansion) { implicitCastExpr(has(declRefExpr())))))))); } -const internal::VariadicDynCastAllOfMatcher - dependentTemplateSpecializationType; - TEST_P(ImportType, ImportDependentTemplateSpecialization) { MatchVerifier Verifier; testImport("template " diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index b8521e2f9576..680e21840b7d 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1926,6 +1926,21 @@ TEST_P(ASTMatchersTest, DependentNameType) { dependentNameType())); } +TEST_P(ASTMatchersTest, DependentTemplateSpecializationType) { + if (!GetParam().isCXX()) { + return; + } + + EXPECT_TRUE(matches( + R"( + template struct A; + template struct declToImport { + typename A ::template B a; + }; + )", + dependentTemplateSpecializationType())); +} + TEST_P(ASTMatchersTest, RecordType) { EXPECT_TRUE(matches("struct S {}; struct S s;", recordType(hasDeclaration(recordDecl(hasName("S"))))));