From: Eric Liu Date: Wed, 21 Feb 2018 13:51:27 +0000 (+0000) Subject: [ASTMatchers] isTemplateInstantiation: also match explicit instantiation declaration. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bdb4755681125844874494802f912ddbd9c956cc;p=clang [ASTMatchers] isTemplateInstantiation: also match explicit instantiation declaration. Summary: Example: template class X {}; class A {}; // Explicit instantiation declaration. extern template class X; Reviewers: bkramer Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D43567 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325678 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index e51ce4175e..b9ce286294 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -4649,6 +4649,10 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, /// \code /// template class X {}; class A {}; template class X; /// \endcode +/// or +/// \code +/// template class X {}; class A {}; extern template class X; +/// \endcode /// cxxRecordDecl(hasName("::X"), isTemplateInstantiation()) /// matches the template instantiation of X. /// @@ -4666,7 +4670,9 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation, CXXRecordDecl)) { return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation || Node.getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition); + TSK_ExplicitInstantiationDefinition || + Node.getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration); } /// \brief Matches declarations that are template instantiations or are inside diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 55c53e66ec..3e27948db7 100644 --- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1623,6 +1623,14 @@ TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) { "template class X;", cxxRecordDecl(isTemplateInstantiation(), hasDescendant( fieldDecl(hasType(recordDecl(hasName("A")))))))); + + // Make sure that we match the instantiation instead of the template + // definition by checking whether the member function is present. + EXPECT_TRUE( + matches("template class X { void f() { T t; } };" + "extern template class X;", + cxxRecordDecl(isTemplateInstantiation(), + unless(hasDescendant(varDecl(hasName("t"))))))); } TEST(IsTemplateInstantiation,