diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 69c58e90b3df..2a8d864c3c5c 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -5421,6 +5421,20 @@ sizeof. +
Matches template type parameter substitutions that have a replacement +type that matches the provided matcher. + +Given + template <typename T> + double F(T t); + int i; + double j = F(i); + +substTemplateTypeParmType(hasReplacementType(type())) matches int +
Matches each case or default statement belonging to the given switch statement. This matcher may produce multiple matches. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 409786e8e9cd..ce01f45333b8 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -5019,6 +5019,22 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher, /// \c substTemplateTypeParmType() matches the type of 't' but not '1' AST_TYPE_MATCHER(SubstTemplateTypeParmType, substTemplateTypeParmType); +/// \brief Matches template type parameter substitutions that have a replacement +/// type that matches the provided matcher. +/// +/// Given +/// \code +/// template +/// double F(T t); +/// int i; +/// double j = F(i); +/// \endcode +/// +/// \c substTemplateTypeParmType(hasReplacementType(type())) matches int +AST_TYPE_TRAVERSE_MATCHER( + hasReplacementType, getReplacementType, + AST_POLYMORPHIC_SUPPORTED_TYPES(SubstTemplateTypeParmType)); + /// \brief Matches template type parameter types. /// /// Example matches T, but not int. diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index eca8a1a9d134..b1309bcafe3a 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -252,6 +252,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasQualifier); REGISTER_MATCHER(hasRangeInit); REGISTER_MATCHER(hasReceiverType); + REGISTER_MATCHER(hasReplacementType); REGISTER_MATCHER(hasReturnValue); REGISTER_MATCHER(hasRHS); REGISTER_MATCHER(hasSelector); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 27f0669ca70d..789982972e01 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -2204,5 +2204,22 @@ TEST(Matcher, HasAnyDeclaration) { functionDecl(hasName("bar")))))); } +TEST(SubstTemplateTypeParmType, HasReplacementType) +{ + std::string Fragment = "template " + "double F(T t);" + "int i;" + "double j = F(i);"; + EXPECT_TRUE(matches(Fragment, substTemplateTypeParmType(hasReplacementType( + qualType(asString("int")))))); + EXPECT_TRUE(notMatches(Fragment, substTemplateTypeParmType(hasReplacementType( + qualType(asString("double")))))); + EXPECT_TRUE( + notMatches("template " + "double F();" + "double j = F<5>();", + substTemplateTypeParmType(hasReplacementType(qualType())))); +} + } // namespace ast_matchers } // namespace clang