Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -2967,6 +2967,27 @@ TSK_ExplicitInstantiationDefinition); } +/// \brief Matches declarations or statements that are contained in a function +/// or class template instantiation. +/// +/// Given +/// \code +/// template void A(T t) { T i; } +/// A(0); +/// A(0U); +/// \endcode +/// stmt(isInTemplateInstantiation()) +/// matches 'int i;' and 'unsigned i;'. +/// +/// Usable as: Matcher, Matcher +AST_POLYMORPHIC_MATCHER(isInTemplateInstantiation, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(Decl, Stmt)) { + Matcher InnerMatcher = + hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()), + functionDecl(isTemplateInstantiation())))); + return InnerMatcher.matches(Node, Finder, Builder); +} + /// \brief Matches explicit template specializations of function, class, or /// static member variable template instantiations. /// Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -242,6 +242,7 @@ REGISTER_MATCHER(isExternC); REGISTER_MATCHER(isImplicit); REGISTER_MATCHER(isInteger); + REGISTER_MATCHER(isInTemplateInstantiation); REGISTER_MATCHER(isListInitialization); REGISTER_MATCHER(isOverride); REGISTER_MATCHER(isPrivate); Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -3504,6 +3504,50 @@ recordDecl(isTemplateInstantiation()))); } +TEST(IsInTemplateInstantiation, MatchesInstantiation) { + EXPECT_TRUE( + matches("template class A { T i; }; class Y { A a; };", + recordDecl(isInTemplateInstantiation()))); +} + +TEST(IsInTemplateInstantiation, NotMatchesDefinition) { + EXPECT_TRUE(notMatches("template class A { T i; };", + recordDecl(isInTemplateInstantiation()))); +} + +TEST(IsInTemplateInstantiation, MatchesInstantiationStmt) { + EXPECT_TRUE(matches("template struct A { A() { T i; } };" + "class Y { A a; }; Y y;", + declStmt(isInTemplateInstantiation()))); +} + +TEST(IsInTemplateInstantiation, NotMatchesDefinitionStmt) { + EXPECT_TRUE(notMatches("template struct A { void x() { T i; } };", + declStmt(isInTemplateInstantiation()))); +} + +TEST(IsInTemplateInstantiation, MatchesFunctionInstantiation) { + EXPECT_TRUE( + matches("template void A(T t) { T i; } void x() { A(0); }", + varDecl(isInTemplateInstantiation()))); +} + +TEST(IsInTemplateInstantiation, NotMatchesFunctionDefinition) { + EXPECT_TRUE(notMatches("template void A(T t) { T i; }", + varDecl(isInTemplateInstantiation()))); +} + +TEST(IsInTemplateInstantiation, MatchesFunctionInstantiationStmt) { + EXPECT_TRUE( + matches("template void A(T t) { T i; } void x() { A(0); }", + declStmt(isInTemplateInstantiation()))); +} + +TEST(IsInTemplateInstantiation, NotMatchesFunctionDefinitionStmt) { + EXPECT_TRUE(notMatches("template void A(T t) { T i; }", + declStmt(isInTemplateInstantiation()))); +} + TEST(IsExplicitTemplateSpecialization, DoesNotMatchPrimaryTemplate) { EXPECT_TRUE(notMatches(