Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h @@ -2967,6 +2967,46 @@ TSK_ExplicitInstantiationDefinition); } +/// \brief Matches declarations that are template instantiations or are inside +/// template instantiations. +/// +/// Given +/// \code +/// template void A(T t) { T i; } +/// A(0); +/// A(0U); +/// \endcode +/// functionDecl(isInstantiated()) +/// matches 'A(int) {...};' and 'A(unsigned) {...}'. +AST_MATCHER(Decl, isInstantiated) { + auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()), + functionDecl(isTemplateInstantiation()))); + auto InnerMatcher = + decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation))); + return InnerMatcher.matches(Node, Finder, Builder); +} + +/// \brief Matches statements inside of a template instantiation. +/// +/// Given +/// \code +/// int j; +/// template void A(T t) { T i; j += 42;} +/// A(0); +/// A(0U); +/// \endcode +/// declStmt(isInTemplateInstantiation()) +/// matches 'int i;' and 'unsigned i'. +/// unless(stmt(isInTemplateInstantiation())) +/// will NOT match j += 42; as it's shared between the template definition and +/// instantiation. +AST_MATCHER(Stmt, isInTemplateInstantiation) { + auto InnerMatcher = + stmt(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: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp @@ -241,7 +241,9 @@ REGISTER_MATCHER(isExpr); REGISTER_MATCHER(isExternC); REGISTER_MATCHER(isImplicit); + REGISTER_MATCHER(isInstantiated); REGISTER_MATCHER(isInteger); + REGISTER_MATCHER(isInTemplateInstantiation); REGISTER_MATCHER(isListInitialization); REGISTER_MATCHER(isOverride); REGISTER_MATCHER(isPrivate); Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -3504,6 +3504,62 @@ recordDecl(isTemplateInstantiation()))); } +TEST(IsInstantiated, MatchesInstantiation) { + EXPECT_TRUE( + matches("template class A { T i; }; class Y { A a; };", + recordDecl(isInstantiated()))); +} + +TEST(IsInstantiated, NotMatchesDefinition) { + EXPECT_TRUE(notMatches("template class A { T i; };", + recordDecl(isInstantiated()))); +} + +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(IsInstantiated, MatchesFunctionInstantiation) { + EXPECT_TRUE( + matches("template void A(T t) { T i; } void x() { A(0); }", + functionDecl(isInstantiated()))); +} + +TEST(IsInstantiated, NotMatchesFunctionDefinition) { + EXPECT_TRUE(notMatches("template void A(T t) { T i; }", + varDecl(isInstantiated()))); +} + +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(IsInTemplateInstantiation, Sharing) { + auto Matcher = binaryOperator(unless(isInTemplateInstantiation())); + // FIXME: Node sharing is an implementation detail, exposing it is ugly + // and makes the matcher behave in non-obvious ways. + EXPECT_TRUE(notMatches( + "int j; template void A(T t) { j += 42; } void x() { A(0); }", + Matcher)); + EXPECT_TRUE(matches( + "int j; template void A(T t) { j += t; } void x() { A(0); }", + Matcher)); +} + TEST(IsExplicitTemplateSpecialization, DoesNotMatchPrimaryTemplate) { EXPECT_TRUE(notMatches(