diff options
author | Adrian Prantl <aprantl@apple.com> | 2024-05-07 13:02:17 -0700 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2024-05-07 13:03:14 -0700 |
commit | c6855ab24e63feb432aac4f86eb70ac16d76c921 (patch) | |
tree | d9c3f525aac1bb609dffce6f664b3a56ae9822fa | |
parent | 2e4abfae57f81e2bb23fc654d6edbaeae51ae10a (diff) | |
download | llvm-c6855ab24e63feb432aac4f86eb70ac16d76c921.zip llvm-c6855ab24e63feb432aac4f86eb70ac16d76c921.tar.gz llvm-c6855ab24e63feb432aac4f86eb70ac16d76c921.tar.bz2 |
Revert "[Clang] Unify interface for accessing template arguments as written for class/variable template specializations (#81642)"
This reverts commit 7115ed0fff027b65fa76fdfae215ed1382ed1473.
This commit broke several LLDB tests.
https://green.lab.llvm.org/job/llvm.org/view/LLDB/job/as-lldb-cmake/3480/
26 files changed, 729 insertions, 846 deletions
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index fda1e5fd..1b86ea1 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -50,12 +50,17 @@ getTemplateSpecializationArgLocs(const NamedDecl &ND) { if (const ASTTemplateArgumentListInfo *Args = Func->getTemplateSpecializationArgsAsWritten()) return Args->arguments(); - } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) { + } else if (auto *Cls = + llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) { if (auto *Args = Cls->getTemplateArgsAsWritten()) return Args->arguments(); - } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) { + } else if (auto *Var = + llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) { if (auto *Args = Var->getTemplateArgsAsWritten()) return Args->arguments(); + } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) { + if (auto *Args = Var->getTemplateArgsInfo()) + return Args->arguments(); } // We return std::nullopt for ClassTemplateSpecializationDecls because it does // not contain TemplateArgumentLoc information. @@ -265,10 +270,22 @@ std::string printTemplateSpecializationArgs(const NamedDecl &ND) { getTemplateSpecializationArgLocs(ND)) { printTemplateArgumentList(OS, *Args, Policy); } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) { - // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST, - // e.g. friend decls. Currently we fallback to Template Arguments without - // location information. - printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); + if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) { + // ClassTemplateSpecializationDecls do not contain + // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we + // create a new argument location list from TypeSourceInfo. + auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>(); + llvm::SmallVector<TemplateArgumentLoc> ArgLocs; + ArgLocs.reserve(STL.getNumArgs()); + for (unsigned I = 0; I < STL.getNumArgs(); ++I) + ArgLocs.push_back(STL.getArgLoc(I)); + printTemplateArgumentList(OS, ArgLocs, Policy); + } else { + // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST, + // e.g. friend decls. Currently we fallback to Template Arguments without + // location information. + printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); + } } OS.flush(); return TemplateArgs; @@ -436,12 +453,10 @@ bool hasReservedScope(const DeclContext &DC) { } QualType declaredType(const TypeDecl *D) { - ASTContext &Context = D->getASTContext(); if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) - if (const auto *Args = CTSD->getTemplateArgsAsWritten()) - return Context.getTemplateSpecializationType( - TemplateName(CTSD->getSpecializedTemplate()), Args->arguments()); - return Context.getTypeDeclType(D); + if (const auto *TSI = CTSD->getTypeAsWritten()) + return TSI->getType(); + return D->getASTContext().getTypeDeclType(D); } namespace { diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index eb025f2..08f99e1 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -693,22 +693,17 @@ public: return true; } - bool - VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) { - if (auto *Args = D->getTemplateArgsAsWritten()) - H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); - return true; - } - bool VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { if (auto *TPL = D->getTemplateParameters()) H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc()); + if (auto *Args = D->getTemplateArgsAsWritten()) + H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); return true; } bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) { - if (auto *Args = D->getTemplateArgsAsWritten()) + if (auto *Args = D->getTemplateArgsInfo()) H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); return true; } @@ -717,6 +712,8 @@ public: VarTemplatePartialSpecializationDecl *D) { if (auto *TPL = D->getTemplateParameters()) H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc()); + if (auto *Args = D->getTemplateArgsAsWritten()) + H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); return true; } diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index f7cc9d1..878067a 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -267,21 +267,18 @@ public: return true; } - // Report a reference from explicit specializations/instantiations to the - // specialized template. Implicit ones are filtered out by RAV. + // Report a reference from explicit specializations to the specialized + // template. Implicit ones are filtered out by RAV and explicit instantiations + // are already traversed through typelocs. bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) { - // if (CTSD->isExplicitSpecialization()) - if (clang::isTemplateExplicitInstantiationOrSpecialization( - CTSD->getTemplateSpecializationKind())) + if (CTSD->isExplicitSpecialization()) report(CTSD->getLocation(), CTSD->getSpecializedTemplate()->getTemplatedDecl()); return true; } bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) { - // if (VTSD->isExplicitSpecialization()) - if (clang::isTemplateExplicitInstantiationOrSpecialization( - VTSD->getTemplateSpecializationKind())) + if (VTSD->isExplicitSpecialization()) report(VTSD->getLocation(), VTSD->getSpecializedTemplate()->getTemplatedDecl()); return true; diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index a16b9c4..bb1b68f 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3546,35 +3546,33 @@ cxxMethodDecl(isConst()) matches A::foo() but not A::bar() </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isCopyAssignmentOperator0')"><a name="isCopyAssignmentOperator0Anchor">isCopyAssignmentOperator</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isCopyAssignmentOperator0"><pre>Matches if the given method declaration declares a copy assignment -operator. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isExplicitObjectMemberFunction0')"><a name="isExplicitObjectMemberFunction0Anchor">isExplicitObjectMemberFunction</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isExplicitObjectMemberFunction0"><pre>Matches if the given method declaration declares a member function with an explicit object parameter. Given struct A { - A &operator=(const A &); - A &operator=(A &&); + int operator-(this A, int); + void fun(this A &&self); + static int operator()(int); + int operator+(int); }; -cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not -the second one. +cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two methods but not the last two. </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isExplicitObjectMemberFunction0')"><a name="isExplicitObjectMemberFunction0Anchor">isExplicitObjectMemberFunction</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isExplicitObjectMemberFunction0"><pre>Matches if the given method declaration declares a member function with an -explicit object parameter. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isCopyAssignmentOperator0')"><a name="isCopyAssignmentOperator0Anchor">isCopyAssignmentOperator</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isCopyAssignmentOperator0"><pre>Matches if the given method declaration declares a copy assignment +operator. Given struct A { - int operator-(this A, int); - void fun(this A &&self); - static int operator()(int); - int operator+(int); + A &operator=(const A &); + A &operator=(A &&); }; -cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two -methods but not the last two. +cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not +the second one. </pre></td></tr> @@ -6715,7 +6713,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -6759,7 +6757,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -6987,7 +6985,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -7221,7 +7219,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -7418,7 +7416,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -7622,7 +7620,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -7679,7 +7677,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -7877,10 +7875,9 @@ int a = b ?: 1; <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('forEachTemplateArgument0')"><a name="forEachTemplateArgument0Anchor">forEachTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="forEachTemplateArgument0"><pre>Matches templateSpecializationType, class template specialization, -variable template specialization, and function template specialization -nodes where the template argument matches the inner matcher. This matcher -may produce multiple matches. +<tr><td colspan="4" class="doc" id="forEachTemplateArgument0"><pre>Matches classTemplateSpecialization, templateSpecializationType and +functionDecl nodes where the template argument matches the inner matcher. +This matcher may produce multiple matches. Given template <typename T, unsigned N, unsigned M> @@ -7902,25 +7899,10 @@ functionDecl(forEachTemplateArgument(refersToType(builtinType()))) </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgumentLoc0')"><a name="hasAnyTemplateArgumentLoc0Anchor">hasAnyTemplateArgumentLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgumentLoc0"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -that have at least one `TemplateArgumentLoc` matching the given -`InnerMatcher`. - -Given - template<typename T> class A {}; - A<int> a; -varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( - hasTypeLoc(loc(asString("int"))))))) - matches `A<int> a`. -</pre></td></tr> - - <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgument0')"><a name="hasAnyTemplateArgument0Anchor">hasAnyTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument0"><pre>Matches templateSpecializationTypes, class template specializations, -variable template specializations, and function template specializations -that have at least one TemplateArgument matching the given InnerMatcher. +<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and +functionDecl that have at least one TemplateArgument matching the given +InnerMatcher. Given template<typename T> class A {}; @@ -7951,25 +7933,9 @@ classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl())) </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc0')"><a name="hasTemplateArgumentLoc0Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgumentLoc0"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`. - -Given - template<typename T, typename U> class A {}; - A<double, int> b; - A<int, double> c; -varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0, - hasTypeLoc(loc(asString("double"))))))) - matches `A<double, int> b`, but not `A<int, double> c`. -</pre></td></tr> - - <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasTemplateArgument0')"><a name="hasTemplateArgument0Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgument0"><pre>Matches templateSpecializationType, class template specializations, -variable template specializations, and function template specializations -where the n'th TemplateArgument matches the given InnerMatcher. +<tr><td colspan="4" class="doc" id="hasTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and +functionDecl where the n'th TemplateArgument matches the given InnerMatcher. Given template<typename T, typename U> class A {}; @@ -7987,6 +7953,34 @@ functionDecl(hasTemplateArgument(0, refersToType(asString("int")))) </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc7')"><a name="hasTypeLoc7Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc7"><pre>Matches if the type location of a node matches the inner matcher. + +Examples: + int x; +declaratorDecl(hasTypeLoc(loc(asString("int")))) + matches int x + +auto x = int(3); +cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int")))) + matches int(3) + +struct Foo { Foo(int, int); }; +auto x = Foo(1, 2); +cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) + matches Foo(1, 2) + +Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>></td><td class="name" onclick="toggle('hasElementType1')"><a name="hasElementType1Anchor">hasElementType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr> <tr><td colspan="4" class="doc" id="hasElementType1"><pre>Matches arrays and C99 complex types that have a specific element type. @@ -8002,8 +7996,8 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Arra </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc7')"><a name="hasTypeLoc7Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> -<tr><td colspan="4" class="doc" id="hasTypeLoc7"><pre>Matches if the type location of a node matches the inner matcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc8')"><a name="hasTypeLoc8Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc8"><pre>Matches if the type location of a node matches the inner matcher. Examples: int x; @@ -8023,7 +8017,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -8072,21 +8066,6 @@ with compoundStmt() </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgumentLoc3')"><a name="hasAnyTemplateArgumentLoc3Anchor">hasAnyTemplateArgumentLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgumentLoc3"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -that have at least one `TemplateArgumentLoc` matching the given -`InnerMatcher`. - -Given - template<typename T> class A {}; - A<int> a; -varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( - hasTypeLoc(loc(asString("int"))))))) - matches `A<int> a`. -</pre></td></tr> - - <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>></td><td class="name" onclick="toggle('hasDeclaration11')"><a name="hasDeclaration11Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasDeclaration11"><pre>Matches a node if the declaration associated with that node matches the given matcher. @@ -8121,10 +8100,9 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Addr </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc3')"><a name="hasTemplateArgumentLoc3Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgumentLoc3"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc0')"><a name="hasTemplateArgumentLoc0Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasTemplateArgumentLoc0"><pre>Matches template specialization `TypeLoc`s where the n'th +`TemplateArgumentLoc` matches the given `InnerMatcher`. Given template<typename T, typename U> class A {}; @@ -8198,8 +8176,8 @@ declStmt(hasSingleDecl(anything())) </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc8')"><a name="hasTypeLoc8Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> -<tr><td colspan="4" class="doc" id="hasTypeLoc8"><pre>Matches if the type location of a node matches the inner matcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc9')"><a name="hasTypeLoc9Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc9"><pre>Matches if the type location of a node matches the inner matcher. Examples: int x; @@ -8219,7 +8197,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -8415,8 +8393,8 @@ actual casts "explicit" casts.) </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc9')"><a name="hasTypeLoc9Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> -<tr><td colspan="4" class="doc" id="hasTypeLoc9"><pre>Matches if the type location of a node matches the inner matcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc10')"><a name="hasTypeLoc10Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc10"><pre>Matches if the type location of a node matches the inner matcher. Examples: int x; @@ -8436,7 +8414,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -8729,10 +8707,9 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X"))))) <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('forEachTemplateArgument2')"><a name="forEachTemplateArgument2Anchor">forEachTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="forEachTemplateArgument2"><pre>Matches templateSpecializationType, class template specialization, -variable template specialization, and function template specialization -nodes where the template argument matches the inner matcher. This matcher -may produce multiple matches. +<tr><td colspan="4" class="doc" id="forEachTemplateArgument2"><pre>Matches classTemplateSpecialization, templateSpecializationType and +functionDecl nodes where the template argument matches the inner matcher. +This matcher may produce multiple matches. Given template <typename T, unsigned N, unsigned M> @@ -8801,25 +8778,10 @@ matching y. </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgumentLoc2')"><a name="hasAnyTemplateArgumentLoc2Anchor">hasAnyTemplateArgumentLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgumentLoc2"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -that have at least one `TemplateArgumentLoc` matching the given -`InnerMatcher`. - -Given - template<typename T> class A {}; - A<int> a; -varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( - hasTypeLoc(loc(asString("int"))))))) - matches `A<int> a`. -</pre></td></tr> - - <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgument2')"><a name="hasAnyTemplateArgument2Anchor">hasAnyTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument2"><pre>Matches templateSpecializationTypes, class template specializations, -variable template specializations, and function template specializations -that have at least one TemplateArgument matching the given InnerMatcher. +<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and +functionDecl that have at least one TemplateArgument matching the given +InnerMatcher. Given template<typename T> class A {}; @@ -8916,25 +8878,9 @@ functionDecl(hasReturnTypeLoc(loc(asString("int")))) </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc2')"><a name="hasTemplateArgumentLoc2Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgumentLoc2"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`. - -Given - template<typename T, typename U> class A {}; - A<double, int> b; - A<int, double> c; -varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0, - hasTypeLoc(loc(asString("double"))))))) - matches `A<double, int> b`, but not `A<int, double> c`. -</pre></td></tr> - - <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasTemplateArgument2')"><a name="hasTemplateArgument2Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgument2"><pre>Matches templateSpecializationType, class template specializations, -variable template specializations, and function template specializations -where the n'th TemplateArgument matches the given InnerMatcher. +<tr><td colspan="4" class="doc" id="hasTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and +functionDecl where the n'th TemplateArgument matches the given InnerMatcher. Given template<typename T, typename U> class A {}; @@ -9527,8 +9473,8 @@ matching y. </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc10')"><a name="hasTypeLoc10Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> -<tr><td colspan="4" class="doc" id="hasTypeLoc10"><pre>Matches if the type location of a node matches the inner matcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc11')"><a name="hasTypeLoc11Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc11"><pre>Matches if the type location of a node matches the inner matcher. Examples: int x; @@ -9548,7 +9494,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -9973,8 +9919,8 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Addr </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>></td><td class="name" onclick="toggle('hasTypeLoc11')"><a name="hasTypeLoc11Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> -<tr><td colspan="4" class="doc" id="hasTypeLoc11"><pre>Matches if the type location of a node matches the inner matcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>></td><td class="name" onclick="toggle('hasTypeLoc12')"><a name="hasTypeLoc12Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc12"><pre>Matches if the type location of a node matches the inner matcher. Examples: int x; @@ -9994,7 +9940,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -10068,11 +10014,9 @@ matches the specialization of struct A generated by A<X>. </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationTypeLoc.html">TemplateSpecializationTypeLoc</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgumentLoc4')"><a name="hasAnyTemplateArgumentLoc4Anchor">hasAnyTemplateArgumentLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgumentLoc4"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -that have at least one `TemplateArgumentLoc` matching the given -`InnerMatcher`. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationTypeLoc.html">TemplateSpecializationTypeLoc</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgumentLoc0')"><a name="hasAnyTemplateArgumentLoc0Anchor">hasAnyTemplateArgumentLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyTemplateArgumentLoc0"><pre>Matches template specialization `TypeLoc`s that have at least one +`TemplateArgumentLoc` matching the given `InnerMatcher`. Given template<typename T> class A {}; @@ -10083,10 +10027,9 @@ varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationTypeLoc.html">TemplateSpecializationTypeLoc</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc4')"><a name="hasTemplateArgumentLoc4Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgumentLoc4"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationTypeLoc.html">TemplateSpecializationTypeLoc</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc1')"><a name="hasTemplateArgumentLoc1Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasTemplateArgumentLoc1"><pre>Matches template specialization `TypeLoc`s where the n'th +`TemplateArgumentLoc` matches the given `InnerMatcher`. Given template<typename T, typename U> class A {}; @@ -10098,11 +10041,10 @@ varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0, </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>></td><td class="name" onclick="toggle('forEachTemplateArgument3')"><a name="forEachTemplateArgument3Anchor">forEachTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="forEachTemplateArgument3"><pre>Matches templateSpecializationType, class template specialization, -variable template specialization, and function template specialization -nodes where the template argument matches the inner matcher. This matcher -may produce multiple matches. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>></td><td class="name" onclick="toggle('forEachTemplateArgument1')"><a name="forEachTemplateArgument1Anchor">forEachTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="forEachTemplateArgument1"><pre>Matches classTemplateSpecialization, templateSpecializationType and +functionDecl nodes where the template argument matches the inner matcher. +This matcher may produce multiple matches. Given template <typename T, unsigned N, unsigned M> @@ -10124,10 +10066,10 @@ functionDecl(forEachTemplateArgument(refersToType(builtinType()))) </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgument3')"><a name="hasAnyTemplateArgument3Anchor">hasAnyTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument3"><pre>Matches templateSpecializationTypes, class template specializations, -variable template specializations, and function template specializations -that have at least one TemplateArgument matching the given InnerMatcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgument1')"><a name="hasAnyTemplateArgument1Anchor">hasAnyTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and +functionDecl that have at least one TemplateArgument matching the given +InnerMatcher. Given template<typename T> class A {}; @@ -10180,10 +10122,9 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Addr </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>></td><td class="name" onclick="toggle('hasTemplateArgument3')"><a name="hasTemplateArgument3Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgument3"><pre>Matches templateSpecializationType, class template specializations, -variable template specializations, and function template specializations -where the n'th TemplateArgument matches the given InnerMatcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>></td><td class="name" onclick="toggle('hasTemplateArgument1')"><a name="hasTemplateArgument1Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and +functionDecl where the n'th TemplateArgument matches the given InnerMatcher. Given template<typename T, typename U> class A {}; @@ -10241,8 +10182,8 @@ QualType-matcher matches. </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc12')"><a name="hasTypeLoc12Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> -<tr><td colspan="4" class="doc" id="hasTypeLoc12"><pre>Matches if the type location of a node matches the inner matcher. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc13')"><a name="hasTypeLoc13Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc13"><pre>Matches if the type location of a node matches the inner matcher. Examples: int x; @@ -10262,7 +10203,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>, - Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, + Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>> @@ -10508,105 +10449,6 @@ Example matches x (matcher = varDecl(hasInitializer(callExpr()))) </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarTemplateSpecializationDecl.html">VarTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('forEachTemplateArgument1')"><a name="forEachTemplateArgument1Anchor">forEachTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="forEachTemplateArgument1"><pre>Matches templateSpecializationType, class template specialization, -variable template specialization, and function template specialization -nodes where the template argument matches the inner matcher. This matcher -may produce multiple matches. - -Given - template <typename T, unsigned N, unsigned M> - struct Matrix {}; - - constexpr unsigned R = 2; - Matrix<int, R * 2, R * 4> M; - - template <typename T, typename U> - void f(T&& t, U&& u) {} - - bool B = false; - f(R, B); -templateSpecializationType(forEachTemplateArgument(isExpr(expr()))) - matches twice, with expr() matching 'R * 2' and 'R * 4' -functionDecl(forEachTemplateArgument(refersToType(builtinType()))) - matches the specialization f<unsigned, bool> twice, for 'unsigned' - and 'bool' -</pre></td></tr> - - -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarTemplateSpecializationDecl.html">VarTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgumentLoc1')"><a name="hasAnyTemplateArgumentLoc1Anchor">hasAnyTemplateArgumentLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgumentLoc1"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -that have at least one `TemplateArgumentLoc` matching the given -`InnerMatcher`. - -Given - template<typename T> class A {}; - A<int> a; -varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( - hasTypeLoc(loc(asString("int"))))))) - matches `A<int> a`. -</pre></td></tr> - - -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarTemplateSpecializationDecl.html">VarTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasAnyTemplateArgument1')"><a name="hasAnyTemplateArgument1Anchor">hasAnyTemplateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument1"><pre>Matches templateSpecializationTypes, class template specializations, -variable template specializations, and function template specializations -that have at least one TemplateArgument matching the given InnerMatcher. - -Given - template<typename T> class A {}; - template<> class A<double> {}; - A<int> a; - - template<typename T> f() {}; - void func() { f<int>(); }; - -classTemplateSpecializationDecl(hasAnyTemplateArgument( - refersToType(asString("int")))) - matches the specialization A<int> - -functionDecl(hasAnyTemplateArgument(refersToType(asString("int")))) - matches the specialization f<int> -</pre></td></tr> - - -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarTemplateSpecializationDecl.html">VarTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc1')"><a name="hasTemplateArgumentLoc1Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgumentLoc1"><pre>Matches template specialization `TypeLoc`s, class template specializations, -variable template specializations, and function template specializations -where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`. - -Given - template<typename T, typename U> class A {}; - A<double, int> b; - A<int, double> c; -varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0, - hasTypeLoc(loc(asString("double"))))))) - matches `A<double, int> b`, but not `A<int, double> c`. -</pre></td></tr> - - -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarTemplateSpecializationDecl.html">VarTemplateSpecializationDecl</a>></td><td class="name" onclick="toggle('hasTemplateArgument1')"><a name="hasTemplateArgument1Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasTemplateArgument1"><pre>Matches templateSpecializationType, class template specializations, -variable template specializations, and function template specializations -where the n'th TemplateArgument matches the given InnerMatcher. - -Given - template<typename T, typename U> class A {}; - A<bool, int> b; - A<int, bool> c; - - template<typename T> void f() {} - void func() { f<int>(); }; -classTemplateSpecializationDecl(hasTemplateArgument( - 1, refersToType(asString("int")))) - matches the specialization A<bool, int> - -functionDecl(hasTemplateArgument(0, refersToType(asString("int")))) - matches the specialization f<int> -</pre></td></tr> - - <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VariableArrayType.html">VariableArrayType</a>></td><td class="name" onclick="toggle('hasSizeExpr0')"><a name="hasSizeExpr0Anchor">hasSizeExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasSizeExpr0"><pre>Matches VariableArrayType nodes that have a specific size expression. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2fae573..cc3108b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -111,9 +111,6 @@ Clang Frontend Potentially Breaking Changes $ clang --target=<your target triple> -print-target-triple <the normalized target triple> -- The ``hasTypeLoc`` AST matcher will no longer match a ``classTemplateSpecializationDecl``; - existing uses should switch to ``templateArgumentLoc`` or ``hasAnyTemplateArgumentLoc`` instead. - What's New in Clang |release|? ============================== Some of the major new features and improvements to Clang are listed diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 36fb7ec..3ee03ee 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1776,25 +1776,6 @@ public: BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; } }; -/// Provides information about an explicit instantiation of a variable or class -/// template. -struct ExplicitInstantiationInfo { - /// The template arguments as written.. - const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr; - - /// The location of the extern keyword. - SourceLocation ExternKeywordLoc; - - /// The location of the template keyword. - SourceLocation TemplateKeywordLoc; - - ExplicitInstantiationInfo() = default; -}; - -using SpecializationOrInstantiationInfo = - llvm::PointerUnion<const ASTTemplateArgumentListInfo *, - ExplicitInstantiationInfo *>; - /// Represents a class template specialization, which refers to /// a class template with a given set of template arguments. /// @@ -1808,8 +1789,8 @@ using SpecializationOrInstantiationInfo = /// template<> /// class array<bool> { }; // class template specialization array<bool> /// \endcode -class ClassTemplateSpecializationDecl : public CXXRecordDecl, - public llvm::FoldingSetNode { +class ClassTemplateSpecializationDecl + : public CXXRecordDecl, public llvm::FoldingSetNode { /// Structure that stores information about a class template /// specialization that was instantiated from a class template partial /// specialization. @@ -1828,8 +1809,22 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl, SpecializedTemplate; /// Further info for explicit template specialization/instantiation. + struct ExplicitSpecializationInfo { + /// The type-as-written. + TypeSourceInfo *TypeAsWritten = nullptr; + + /// The location of the extern keyword. + SourceLocation ExternLoc; + + /// The location of the template keyword. + SourceLocation TemplateKeywordLoc; + + ExplicitSpecializationInfo() = default; + }; + + /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - SpecializationOrInstantiationInfo ExplicitInfo = nullptr; + ExplicitSpecializationInfo *ExplicitInfo = nullptr; /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; @@ -2006,49 +2001,44 @@ public: SpecializedTemplate = TemplDecl; } - /// Retrieve the template argument list as written in the sources, - /// if any. - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->TemplateArgsAsWritten; - return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); + /// Sets the type of this specialization as it was written by + /// the user. This will be a class template specialization type. + void setTypeAsWritten(TypeSourceInfo *T) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = T; } - /// Set the template argument list as written in the sources. - void - setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - Info->TemplateArgsAsWritten = ArgsWritten; - else - ExplicitInfo = ArgsWritten; - } - - /// Set the template argument list as written in the sources. - void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { - setTemplateArgsAsWritten( - ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); + /// Gets the type of this specialization as it was written by + /// the user, if it was so written. + TypeSourceInfo *getTypeAsWritten() const { + return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; } /// Gets the location of the extern keyword, if present. - SourceLocation getExternKeywordLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->ExternKeywordLoc; - return SourceLocation(); + SourceLocation getExternLoc() const { + return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); } /// Sets the location of the extern keyword. - void setExternKeywordLoc(SourceLocation Loc); + void setExternLoc(SourceLocation Loc) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->ExternLoc = Loc; + } + + /// Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->TemplateKeywordLoc = Loc; + } /// Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->TemplateKeywordLoc; - return SourceLocation(); + return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - /// Sets the location of the template keyword. - void setTemplateKeywordLoc(SourceLocation Loc); - SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { @@ -2076,6 +2066,10 @@ class ClassTemplatePartialSpecializationDecl /// The list of template parameters TemplateParameterList* TemplateParams = nullptr; + /// The source info for the template arguments as written. + /// FIXME: redundant with TypeAsWritten? + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; + /// The class template partial specialization from which this /// class template partial specialization was instantiated. /// @@ -2084,11 +2078,15 @@ class ClassTemplatePartialSpecializationDecl llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool> InstantiatedFromMember; - ClassTemplatePartialSpecializationDecl( - ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, - ClassTemplatePartialSpecializationDecl *PrevDecl); + ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ClassTemplatePartialSpecializationDecl *PrevDecl); ClassTemplatePartialSpecializationDecl(ASTContext &C) : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization), @@ -2103,8 +2101,11 @@ public: static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - ArrayRef<TemplateArgument> Args, QualType CanonInjectedType, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + const TemplateArgumentListInfo &ArgInfos, + QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl); static ClassTemplatePartialSpecializationDecl * @@ -2135,6 +2136,11 @@ public: return TemplateParams->hasAssociatedConstraints(); } + /// Get the template arguments as written. + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ArgsAsWritten; + } + /// Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. @@ -2608,11 +2614,26 @@ class VarTemplateSpecializationDecl : public VarDecl, SpecializedTemplate; /// Further info for explicit template specialization/instantiation. + struct ExplicitSpecializationInfo { + /// The type-as-written. + TypeSourceInfo *TypeAsWritten = nullptr; + + /// The location of the extern keyword. + SourceLocation ExternLoc; + + /// The location of the template keyword. + SourceLocation TemplateKeywordLoc; + + ExplicitSpecializationInfo() = default; + }; + + /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - SpecializationOrInstantiationInfo ExplicitInfo = nullptr; + ExplicitSpecializationInfo *ExplicitInfo = nullptr; /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; + const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr; /// The point where this template was instantiated (if any). SourceLocation PointOfInstantiation; @@ -2666,6 +2687,14 @@ public: /// specialization. const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; } + // TODO: Always set this when creating the new specialization? + void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo); + void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo); + + const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const { + return TemplateArgsInfo; + } + /// Determine the kind of specialization that this /// declaration represents. TemplateSpecializationKind getSpecializationKind() const { @@ -2769,49 +2798,44 @@ public: SpecializedTemplate = TemplDecl; } - /// Retrieve the template argument list as written in the sources, - /// if any. - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->TemplateArgsAsWritten; - return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); - } - - /// Set the template argument list as written in the sources. - void - setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - Info->TemplateArgsAsWritten = ArgsWritten; - else - ExplicitInfo = ArgsWritten; + /// Sets the type of this specialization as it was written by + /// the user. + void setTypeAsWritten(TypeSourceInfo *T) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = T; } - /// Set the template argument list as written in the sources. - void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { - setTemplateArgsAsWritten( - ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); + /// Gets the type of this specialization as it was written by + /// the user, if it was so written. + TypeSourceInfo *getTypeAsWritten() const { + return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; } /// Gets the location of the extern keyword, if present. - SourceLocation getExternKeywordLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->ExternKeywordLoc; - return SourceLocation(); + SourceLocation getExternLoc() const { + return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); } /// Sets the location of the extern keyword. - void setExternKeywordLoc(SourceLocation Loc); + void setExternLoc(SourceLocation Loc) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->ExternLoc = Loc; + } + + /// Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->TemplateKeywordLoc = Loc; + } /// Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->TemplateKeywordLoc; - return SourceLocation(); + return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - /// Sets the location of the template keyword. - void setTemplateKeywordLoc(SourceLocation Loc); - SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { @@ -2839,6 +2863,10 @@ class VarTemplatePartialSpecializationDecl /// The list of template parameters TemplateParameterList *TemplateParams = nullptr; + /// The source info for the template arguments as written. + /// FIXME: redundant with TypeAsWritten? + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; + /// The variable template partial specialization from which this /// variable template partial specialization was instantiated. /// @@ -2851,7 +2879,8 @@ class VarTemplatePartialSpecializationDecl ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args); + StorageClass S, ArrayRef<TemplateArgument> Args, + const ASTTemplateArgumentListInfo *ArgInfos); VarTemplatePartialSpecializationDecl(ASTContext &Context) : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, @@ -2868,8 +2897,8 @@ public: Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, - TypeSourceInfo *TInfo, StorageClass S, - ArrayRef<TemplateArgument> Args); + TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args, + const TemplateArgumentListInfo &ArgInfos); static VarTemplatePartialSpecializationDecl * CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -2885,6 +2914,11 @@ public: return TemplateParams; } + /// Get the template arguments as written. + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ArgsAsWritten; + } + /// \brief All associated constraints of this partial specialization, /// including the requires clause and any constraints derived from /// constrained-parameters. diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 782f608..f9b145b 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2030,15 +2030,6 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( - const TemplateArgumentLoc *TAL, unsigned Count) { - for (unsigned I = 0; I < Count; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); - } - return true; -} - #define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ /* For implicit instantiations ("set<int> x;"), we don't want to \ @@ -2048,12 +2039,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( TemplateSpecializationType). For explicit instantiations \ ("template set<int>;"), we do need a callback, since this \ is the only callback that's made for this instantiation. \ - We use getTemplateArgsAsWritten() to distinguish. */ \ - if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \ - /* The args that remains unspecialized. */ \ - TRY_TO(TraverseTemplateArgumentLocsHelper( \ - ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \ - } \ + We use getTypeAsWritten() to distinguish. */ \ + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ \ if (getDerived().shouldVisitTemplateInstantiations() || \ D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ @@ -2073,6 +2061,15 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord) DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var) +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( + const TemplateArgumentLoc *TAL, unsigned Count) { + for (unsigned I = 0; I < Count; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); + } + return true; +} + #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ /* The partial specialization. */ \ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 0f3257d..8a2bbff 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -764,9 +764,9 @@ AST_POLYMORPHIC_MATCHER(isImplicit, return Node.isImplicit(); } -/// Matches templateSpecializationTypes, class template specializations, -/// variable template specializations, and function template specializations -/// that have at least one TemplateArgument matching the given InnerMatcher. +/// Matches classTemplateSpecializations, templateSpecializationType and +/// functionDecl that have at least one TemplateArgument matching the given +/// InnerMatcher. /// /// Given /// \code @@ -788,8 +788,8 @@ AST_POLYMORPHIC_MATCHER(isImplicit, AST_POLYMORPHIC_MATCHER_P( hasAnyTemplateArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - VarTemplateSpecializationDecl, FunctionDecl, - TemplateSpecializationType), + TemplateSpecializationType, + FunctionDecl), internal::Matcher<TemplateArgument>, InnerMatcher) { ArrayRef<TemplateArgument> List = internal::getTemplateSpecializationArgs(Node); @@ -1047,9 +1047,8 @@ AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); } /// expr(isValueDependent()) matches return Size AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); } -/// Matches templateSpecializationType, class template specializations, -/// variable template specializations, and function template specializations -/// where the n'th TemplateArgument matches the given InnerMatcher. +/// Matches classTemplateSpecializations, templateSpecializationType and +/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher. /// /// Given /// \code @@ -1069,8 +1068,8 @@ AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); } AST_POLYMORPHIC_MATCHER_P2( hasTemplateArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - VarTemplateSpecializationDecl, FunctionDecl, - TemplateSpecializationType), + TemplateSpecializationType, + FunctionDecl), unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) { ArrayRef<TemplateArgument> List = internal::getTemplateSpecializationArgs(Node); @@ -4067,7 +4066,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD( /// Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, /// Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, /// Matcher<CXXUnresolvedConstructExpr>, -/// Matcher<CompoundLiteralExpr>, +/// Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, /// Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, /// Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, /// Matcher<TypedefNameDecl> @@ -4076,8 +4075,9 @@ AST_POLYMORPHIC_MATCHER_P( AST_POLYMORPHIC_SUPPORTED_TYPES( BlockDecl, CXXBaseSpecifier, CXXCtorInitializer, CXXFunctionalCastExpr, CXXNewExpr, CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr, - CompoundLiteralExpr, DeclaratorDecl, ExplicitCastExpr, ObjCPropertyDecl, - TemplateArgumentLoc, TypedefNameDecl), + ClassTemplateSpecializationDecl, CompoundLiteralExpr, DeclaratorDecl, + ExplicitCastExpr, ObjCPropertyDecl, TemplateArgumentLoc, + TypedefNameDecl), internal::Matcher<TypeLoc>, Inner) { TypeSourceInfo *source = internal::GetTypeSourceInfo(Node); if (source == nullptr) { @@ -5304,10 +5304,9 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs, return Node.getNumParams() == N; } -/// Matches templateSpecializationType, class template specialization, -/// variable template specialization, and function template specialization -/// nodes where the template argument matches the inner matcher. This matcher -/// may produce multiple matches. +/// Matches classTemplateSpecialization, templateSpecializationType and +/// functionDecl nodes where the template argument matches the inner matcher. +/// This matcher may produce multiple matches. /// /// Given /// \code @@ -5331,8 +5330,7 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs, AST_POLYMORPHIC_MATCHER_P( forEachTemplateArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - VarTemplateSpecializationDecl, FunctionDecl, - TemplateSpecializationType), + TemplateSpecializationType, FunctionDecl), internal::Matcher<TemplateArgument>, InnerMatcher) { ArrayRef<TemplateArgument> TemplateArgs = clang::ast_matchers::internal::getTemplateSpecializationArgs(Node); @@ -6907,10 +6905,8 @@ extern const internal::VariadicDynCastAllOfMatcher< TypeLoc, TemplateSpecializationTypeLoc> templateSpecializationTypeLoc; -/// Matches template specialization `TypeLoc`s, class template specializations, -/// variable template specializations, and function template specializations -/// that have at least one `TemplateArgumentLoc` matching the given -/// `InnerMatcher`. +/// Matches template specialization `TypeLoc`s that have at least one +/// `TemplateArgumentLoc` matching the given `InnerMatcher`. /// /// Given /// \code @@ -6920,21 +6916,20 @@ extern const internal::VariadicDynCastAllOfMatcher< /// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( /// hasTypeLoc(loc(asString("int"))))))) /// matches `A<int> a`. -AST_POLYMORPHIC_MATCHER_P( - hasAnyTemplateArgumentLoc, - AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - VarTemplateSpecializationDecl, FunctionDecl, - DeclRefExpr, TemplateSpecializationTypeLoc), - internal::Matcher<TemplateArgumentLoc>, InnerMatcher) { - auto Args = internal::getTemplateArgsWritten(Node); - return matchesFirstInRange(InnerMatcher, Args.begin(), Args.end(), Finder, - Builder) != Args.end(); +AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc, + internal::Matcher<TemplateArgumentLoc>, InnerMatcher) { + for (unsigned Index = 0, N = Node.getNumArgs(); Index < N; ++Index) { + clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder); + if (InnerMatcher.matches(Node.getArgLoc(Index), Finder, &Result)) { + *Builder = std::move(Result); + return true; + } + } return false; } -/// Matches template specialization `TypeLoc`s, class template specializations, -/// variable template specializations, and function template specializations -/// where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`. +/// Matches template specialization `TypeLoc`s where the n'th +/// `TemplateArgumentLoc` matches the given `InnerMatcher`. /// /// Given /// \code @@ -6947,13 +6942,10 @@ AST_POLYMORPHIC_MATCHER_P( /// matches `A<double, int> b`, but not `A<int, double> c`. AST_POLYMORPHIC_MATCHER_P2( hasTemplateArgumentLoc, - AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - VarTemplateSpecializationDecl, FunctionDecl, - DeclRefExpr, TemplateSpecializationTypeLoc), + AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, TemplateSpecializationTypeLoc), unsigned, Index, internal::Matcher<TemplateArgumentLoc>, InnerMatcher) { - auto Args = internal::getTemplateArgsWritten(Node); - return Index < Args.size() && - InnerMatcher.matches(Args[Index], Finder, Builder); + return internal::MatchTemplateArgLocAt(Node, Index, InnerMatcher, Finder, + Builder); } /// Matches C or C++ elaborated `TypeLoc`s. diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index c1cc63f..47d912c 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -186,6 +186,10 @@ inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) { inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) { return Node.getAllocatedTypeSourceInfo(); } +inline TypeSourceInfo * +GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) { + return Node.getTypeAsWritten(); +} /// Unifies obtaining the FunctionProtoType pointer from both /// FunctionProtoType and FunctionDecl nodes.. @@ -1936,11 +1940,6 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) { } inline ArrayRef<TemplateArgument> -getTemplateSpecializationArgs(const VarTemplateSpecializationDecl &D) { - return D.getTemplateArgs().asArray(); -} - -inline ArrayRef<TemplateArgument> getTemplateSpecializationArgs(const TemplateSpecializationType &T) { return T.template_arguments(); } @@ -1949,46 +1948,7 @@ inline ArrayRef<TemplateArgument> getTemplateSpecializationArgs(const FunctionDecl &FD) { if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs()) return TemplateArgs->asArray(); - return std::nullopt; -} - -inline ArrayRef<TemplateArgumentLoc> -getTemplateArgsWritten(const ClassTemplateSpecializationDecl &D) { - if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten()) - return Args->arguments(); - return std::nullopt; -} - -inline ArrayRef<TemplateArgumentLoc> -getTemplateArgsWritten(const VarTemplateSpecializationDecl &D) { - if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten()) - return Args->arguments(); - return std::nullopt; -} - -inline ArrayRef<TemplateArgumentLoc> -getTemplateArgsWritten(const FunctionDecl &FD) { - if (const auto *Args = FD.getTemplateSpecializationArgsAsWritten()) - return Args->arguments(); - return std::nullopt; -} - -inline ArrayRef<TemplateArgumentLoc> -getTemplateArgsWritten(const DeclRefExpr &DRE) { - if (const auto *Args = DRE.getTemplateArgs()) - return {Args, DRE.getNumTemplateArgs()}; - return std::nullopt; -} - -inline SmallVector<TemplateArgumentLoc> -getTemplateArgsWritten(const TemplateSpecializationTypeLoc &T) { - SmallVector<TemplateArgumentLoc> Args; - if (!T.isNull()) { - Args.reserve(T.getNumArgs()); - for (unsigned I = 0; I < T.getNumArgs(); ++I) - Args.emplace_back(T.getArgLoc(I)); - } - return Args; + return ArrayRef<TemplateArgument>(); } struct NotEqualsBoundNodePredicate { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 9ff8e1e..60f21332 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -443,9 +443,8 @@ namespace clang { Expected<FunctionTemplateAndArgsTy> ImportFunctionTemplateWithTemplateArgsFromSpecialization( FunctionDecl *FromFD); - - template <typename DeclTy> - Error ImportTemplateParameterLists(const DeclTy *FromD, DeclTy *ToD); + Error ImportTemplateParameterLists(const DeclaratorDecl *FromD, + DeclaratorDecl *ToD); Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); @@ -3323,9 +3322,8 @@ ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { return ToEnumerator; } -template <typename DeclTy> -Error ASTNodeImporter::ImportTemplateParameterLists(const DeclTy *FromD, - DeclTy *ToD) { +Error ASTNodeImporter::ImportTemplateParameterLists(const DeclaratorDecl *FromD, + DeclaratorDecl *ToD) { unsigned int Num = FromD->getNumTemplateParameterLists(); if (Num == 0) return Error::success(); @@ -6212,16 +6210,15 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (!IdLocOrErr) return IdLocOrErr.takeError(); - // Import TemplateArgumentListInfo. - TemplateArgumentListInfo ToTAInfo; - if (const auto *ASTTemplateArgs = D->getTemplateArgsAsWritten()) { - if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo)) - return std::move(Err); - } - // Create the specialization. ClassTemplateSpecializationDecl *D2 = nullptr; if (PartialSpec) { + // Import TemplateArgumentListInfo. + TemplateArgumentListInfo ToTAInfo; + const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); + if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) + return std::move(Err); + QualType CanonInjType; if (Error Err = importInto( CanonInjType, PartialSpec->getInjectedSpecializationType())) @@ -6231,7 +6228,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, *IdLocOrErr, ToTPList, ClassTemplate, - llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), + llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo, CanonInjType, cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) return D2; @@ -6279,27 +6276,28 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( else return BraceRangeOrErr.takeError(); - if (Error Err = ImportTemplateParameterLists(D, D2)) - return std::move(Err); - // Import the qualifier, if any. if (auto LocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*LocOrErr); else return LocOrErr.takeError(); - if (D->getTemplateArgsAsWritten()) - D2->setTemplateArgsAsWritten(ToTAInfo); + if (auto *TSI = D->getTypeAsWritten()) { + if (auto TInfoOrErr = import(TSI)) + D2->setTypeAsWritten(*TInfoOrErr); + else + return TInfoOrErr.takeError(); - if (auto LocOrErr = import(D->getTemplateKeywordLoc())) - D2->setTemplateKeywordLoc(*LocOrErr); - else - return LocOrErr.takeError(); + if (auto LocOrErr = import(D->getTemplateKeywordLoc())) + D2->setTemplateKeywordLoc(*LocOrErr); + else + return LocOrErr.takeError(); - if (auto LocOrErr = import(D->getExternKeywordLoc())) - D2->setExternKeywordLoc(*LocOrErr); - else - return LocOrErr.takeError(); + if (auto LocOrErr = import(D->getExternLoc())) + D2->setExternLoc(*LocOrErr); + else + return LocOrErr.takeError(); + } if (D->getPointOfInstantiation().isValid()) { if (auto POIOrErr = import(D->getPointOfInstantiation())) @@ -6519,7 +6517,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *D2 = nullptr; TemplateArgumentListInfo ToTAInfo; - if (const auto *Args = D->getTemplateArgsAsWritten()) { + if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) return std::move(Err); } @@ -6527,6 +6525,14 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) { + // Import TemplateArgumentListInfo + TemplateArgumentListInfo ArgInfos; + const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten(); + // NOTE: FromTAArgsAsWritten and template parameter list are non-null. + if (Error Err = + ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos)) + return std::move(Err); + auto ToTPListOrErr = import(FromPartial->getTemplateParameters()); if (!ToTPListOrErr) return ToTPListOrErr.takeError(); @@ -6535,7 +6541,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, VarTemplate, QualType(), nullptr, - D->getStorageClass(), TemplateArgs)) + D->getStorageClass(), TemplateArgs, ArgInfos)) return ToPartial; if (Expected<PartVarSpecDecl *> ToInstOrErr = @@ -6578,9 +6584,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( } D2->setSpecializationKind(D->getSpecializationKind()); - - if (D->getTemplateArgsAsWritten()) - D2->setTemplateArgsAsWritten(ToTAInfo); + D2->setTemplateArgsInfo(ToTAInfo); if (auto LocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*LocOrErr); diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index c586825..599d379 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1083,15 +1083,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { NNS->print(Out, Policy); Out << *D; - if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - const TemplateParameterList *TParams = - S->getSpecializedTemplate()->getTemplateParameters(); - const ASTTemplateArgumentListInfo *TArgAsWritten = - S->getTemplateArgsAsWritten(); - if (TArgAsWritten && !Policy.PrintCanonicalTypes) - printTemplateArguments(TArgAsWritten->arguments(), TParams); - else - printTemplateArguments(S->getTemplateArgs().asArray(), TParams); + if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + ArrayRef<TemplateArgument> Args = S->getTemplateArgs().asArray(); + if (!Policy.PrintCanonicalTypes) + if (const auto* TSI = S->getTypeAsWritten()) + if (const auto *TST = + dyn_cast<TemplateSpecializationType>(TSI->getType())) + Args = TST->template_arguments(); + printTemplateArguments( + Args, S->getSpecializedTemplate()->getTemplateParameters()); } } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index af2d8d72..d27a30e 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -985,63 +985,41 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { SourceRange ClassTemplateSpecializationDecl::getSourceRange() const { - if (getSpecializationKind() == TSK_ExplicitInstantiationDeclaration) { - return SourceRange(getExternKeywordLoc(), - getTemplateArgsAsWritten()->getRAngleLoc()); - } else if (getSpecializationKind() == TSK_ExplicitInstantiationDefinition) { - return SourceRange(getTemplateKeywordLoc(), - getTemplateArgsAsWritten()->getRAngleLoc()); - } else if (!isExplicitSpecialization()) { + if (ExplicitInfo) { + SourceLocation Begin = getTemplateKeywordLoc(); + if (Begin.isValid()) { + // Here we have an explicit (partial) specialization or instantiation. + assert(getSpecializationKind() == TSK_ExplicitSpecialization || + getSpecializationKind() == TSK_ExplicitInstantiationDeclaration || + getSpecializationKind() == TSK_ExplicitInstantiationDefinition); + if (getExternLoc().isValid()) + Begin = getExternLoc(); + SourceLocation End = getBraceRange().getEnd(); + if (End.isInvalid()) + End = getTypeAsWritten()->getTypeLoc().getEndLoc(); + return SourceRange(Begin, End); + } + // An implicit instantiation of a class template partial specialization + // uses ExplicitInfo to record the TypeAsWritten, but the source + // locations should be retrieved from the instantiation pattern. + using CTPSDecl = ClassTemplatePartialSpecializationDecl; + auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this)); + CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember(); + assert(inst_from != nullptr); + return inst_from->getSourceRange(); + } + else { // No explicit info available. llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> - InstFrom = getInstantiatedFrom(); - if (InstFrom.isNull()) + inst_from = getInstantiatedFrom(); + if (inst_from.isNull()) return getSpecializedTemplate()->getSourceRange(); - if (const auto *CTD = InstFrom.dyn_cast<ClassTemplateDecl *>()) - return CTD->getSourceRange(); - return InstFrom.get<ClassTemplatePartialSpecializationDecl *>() - ->getSourceRange(); - } - SourceLocation Begin = TagDecl::getOuterLocStart(); - if (const auto *CTPSD = - dyn_cast<ClassTemplatePartialSpecializationDecl>(this)) { - if (const auto *InstFrom = CTPSD->getInstantiatedFromMember()) - return InstFrom->getSourceRange(); - else if (!getNumTemplateParameterLists()) - Begin = CTPSD->getTemplateParameters()->getTemplateLoc(); - } - SourceLocation End = getBraceRange().getEnd(); - if (End.isInvalid()) - End = getTemplateArgsAsWritten()->getRAngleLoc(); - return SourceRange(Begin, End); -} - -void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) { - auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); - if (!Info) { - // Don't allocate if the location is invalid. - if (Loc.isInvalid()) - return; - Info = new (getASTContext()) ExplicitInstantiationInfo; - Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); - ExplicitInfo = Info; + if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>()) + return ctd->getSourceRange(); + return inst_from.get<ClassTemplatePartialSpecializationDecl *>() + ->getSourceRange(); } - Info->ExternKeywordLoc = Loc; -} - -void ClassTemplateSpecializationDecl::setTemplateKeywordLoc( - SourceLocation Loc) { - auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); - if (!Info) { - // Don't allocate if the location is invalid. - if (Loc.isInvalid()) - return; - Info = new (getASTContext()) ExplicitInstantiationInfo; - Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); - ExplicitInfo = Info; - } - Info->TemplateKeywordLoc = Loc; } //===----------------------------------------------------------------------===// @@ -1109,29 +1087,43 @@ void ImplicitConceptSpecializationDecl::setTemplateArguments( //===----------------------------------------------------------------------===// void ClassTemplatePartialSpecializationDecl::anchor() {} -ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl( - ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, - ClassTemplatePartialSpecializationDecl *PrevDecl) - : ClassTemplateSpecializationDecl( - Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc, - SpecializedTemplate, Args, PrevDecl), - TemplateParams(Params), InstantiatedFromMember(nullptr, false) { +ClassTemplatePartialSpecializationDecl:: +ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + const ASTTemplateArgumentListInfo *ArgInfos, + ClassTemplatePartialSpecializationDecl *PrevDecl) + : ClassTemplateSpecializationDecl(Context, + ClassTemplatePartialSpecialization, + TK, DC, StartLoc, IdLoc, + SpecializedTemplate, Args, PrevDecl), + TemplateParams(Params), ArgsAsWritten(ArgInfos), + InstantiatedFromMember(nullptr, false) { if (AdoptTemplateParameterList(Params, this)) setInvalidDecl(); } ClassTemplatePartialSpecializationDecl * -ClassTemplatePartialSpecializationDecl::Create( - ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, - QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl) { - auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl( - Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args, - PrevDecl); +ClassTemplatePartialSpecializationDecl:: +Create(ASTContext &Context, TagKind TK,DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + const TemplateArgumentListInfo &ArgInfos, + QualType CanonInjectedType, + ClassTemplatePartialSpecializationDecl *PrevDecl) { + const ASTTemplateArgumentListInfo *ASTArgInfos = + ASTTemplateArgumentListInfo::Create(Context, ArgInfos); + + auto *Result = new (Context, DC) + ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc, + Params, SpecializedTemplate, Args, + ASTArgInfos, PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); Result->setMayHaveOutOfDateDef(false); @@ -1379,47 +1371,26 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { return SpecializedTemplate.get<VarTemplateDecl *>(); } +void VarTemplateSpecializationDecl::setTemplateArgsInfo( + const TemplateArgumentListInfo &ArgsInfo) { + TemplateArgsInfo = + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); +} + +void VarTemplateSpecializationDecl::setTemplateArgsInfo( + const ASTTemplateArgumentListInfo *ArgsInfo) { + TemplateArgsInfo = + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); +} + SourceRange VarTemplateSpecializationDecl::getSourceRange() const { if (isExplicitSpecialization() && !hasInit()) { - if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) + if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo()) return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); - } else if (getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDeclaration) { - if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) - return SourceRange(getExternKeywordLoc(), Info->getRAngleLoc()); - } else if (getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition) { - if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) - return SourceRange(getTemplateKeywordLoc(), Info->getRAngleLoc()); } return VarDecl::getSourceRange(); } -void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) { - auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); - if (!Info) { - // Don't allocate if the location is invalid. - if (Loc.isInvalid()) - return; - Info = new (getASTContext()) ExplicitInstantiationInfo; - Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); - ExplicitInfo = Info; - } - Info->ExternKeywordLoc = Loc; -} - -void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) { - auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); - if (!Info) { - // Don't allocate if the location is invalid. - if (Loc.isInvalid()) - return; - Info = new (getASTContext()) ExplicitInstantiationInfo; - Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); - ExplicitInfo = Info; - } - Info->TemplateKeywordLoc = Loc; -} //===----------------------------------------------------------------------===// // VarTemplatePartialSpecializationDecl Implementation @@ -1431,11 +1402,13 @@ VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args) + StorageClass S, ArrayRef<TemplateArgument> Args, + const ASTTemplateArgumentListInfo *ArgInfos) : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context, DC, StartLoc, IdLoc, SpecializedTemplate, T, TInfo, S, Args), - TemplateParams(Params), InstantiatedFromMember(nullptr, false) { + TemplateParams(Params), ArgsAsWritten(ArgInfos), + InstantiatedFromMember(nullptr, false) { if (AdoptTemplateParameterList(Params, DC)) setInvalidDecl(); } @@ -1445,10 +1418,15 @@ VarTemplatePartialSpecializationDecl::Create( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args) { - auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl( - Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S, - Args); + StorageClass S, ArrayRef<TemplateArgument> Args, + const TemplateArgumentListInfo &ArgInfos) { + const ASTTemplateArgumentListInfo *ASTArgInfos + = ASTTemplateArgumentListInfo::Create(Context, ArgInfos); + + auto *Result = + new (Context, DC) VarTemplatePartialSpecializationDecl( + Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, + S, Args, ASTArgInfos); Result->setSpecializationKind(TSK_ExplicitSpecialization); return Result; } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 87f0a87..9602f44 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1472,18 +1472,21 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { // If this is a class template specialization, print the template // arguments. - if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - const TemplateParameterList *TParams = - S->getSpecializedTemplate()->getTemplateParameters(); - const ASTTemplateArgumentListInfo *TArgAsWritten = - S->getTemplateArgsAsWritten(); + if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + ArrayRef<TemplateArgument> Args; + TypeSourceInfo *TAW = Spec->getTypeAsWritten(); + if (!Policy.PrintCanonicalTypes && TAW) { + const TemplateSpecializationType *TST = + cast<TemplateSpecializationType>(TAW->getType()); + Args = TST->template_arguments(); + } else { + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + Args = TemplateArgs.asArray(); + } IncludeStrongLifetimeRAII Strong(Policy); - if (TArgAsWritten && !Policy.PrintCanonicalTypes) - printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy, - TParams); - else - printTemplateArgumentList(OS, S->getTemplateArgs().asArray(), Policy, - TParams); + printTemplateArgumentList( + OS, Args, Policy, + Spec->getSpecializedTemplate()->getTemplateParameters()); } spaceBeforePlaceHolder(OS); diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 8eb88f5..1c04aa1 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -673,12 +673,9 @@ public: IndexCtx.indexTagDecl( D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), SpecializationOf)); - // Template specialization arguments. - if (const ASTTemplateArgumentListInfo *TemplateArgInfo = - D->getTemplateArgsAsWritten()) { - for (const auto &Arg : TemplateArgInfo->arguments()) - handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); - } + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) + IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, + D->getLexicalDeclContext()); return true; } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 0febf4e..a1e32d3 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1408,7 +1408,7 @@ void Sema::ActOnEndOfTranslationUnit() { SourceRange DiagRange = DiagD->getLocation(); if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(DiagD)) { if (const ASTTemplateArgumentListInfo *ASTTAL = - VTSD->getTemplateArgsAsWritten()) + VTSD->getTemplateArgsInfo()) DiagRange.setEnd(ASTTAL->RAngleLoc); } if (DiagD->isReferenced()) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b268d7c..5c72270 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5166,8 +5166,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( VarTemplatePartialSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, - CanonicalConverted); - Partial->setTemplateArgsAsWritten(TemplateArgs); + CanonicalConverted, TemplateArgs); if (!PrevPartial) VarTemplate->AddPartialSpecialization(Partial, InsertPos); @@ -5185,7 +5184,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( Specialization = VarTemplateSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, VarTemplate, DI->getType(), DI, SC, CanonicalConverted); - Specialization->setTemplateArgsAsWritten(TemplateArgs); + Specialization->setTemplateArgsInfo(TemplateArgs); if (!PrevDecl) VarTemplate->AddSpecialization(Specialization, InsertPos); @@ -5220,6 +5219,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( } } + Specialization->setTemplateKeywordLoc(TemplateKWLoc); Specialization->setLexicalDeclContext(CurContext); // Add the specialization into its lexical context, so that it can @@ -9489,8 +9489,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( ClassTemplatePartialSpecializationDecl::Create( Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted, - CanonType, PrevPartial); - Partial->setTemplateArgsAsWritten(TemplateArgs); + TemplateArgs, CanonType, PrevPartial); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo( @@ -9513,7 +9512,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization = ClassTemplateSpecializationDecl::Create( Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, ClassTemplate, CanonicalConverted, PrevDecl); - Specialization->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Specialization, SS); if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, @@ -9597,6 +9595,21 @@ DeclResult Sema::ActOnClassTemplateSpecialization( << (isPartialSpecialization? 1 : 0) << FixItHint::CreateRemoval(ModulePrivateLoc); + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy + = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, + TemplateArgs, CanonType); + if (TUK != TUK_Friend) { + Specialization->setTypeAsWritten(WrittenTy); + Specialization->setTemplateKeywordLoc(TemplateKWLoc); + } + // C++ [temp.expl.spec]p9: // A template explicit specialization is in the scope of the // namespace in which the template was defined. @@ -9612,15 +9625,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization->startDefinition(); if (TUK == TUK_Friend) { - // Build the fully-sugared type for this class template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo( - Name, TemplateNameLoc, TemplateArgs, CanonType); FriendDecl *Friend = FriendDecl::Create(Context, CurContext, TemplateNameLoc, WrittenTy, @@ -10826,10 +10830,21 @@ DeclResult Sema::ActOnExplicitInstantiation( } } - Specialization->setTemplateArgsAsWritten(TemplateArgs); + // Build the fully-sugared type for this explicit instantiation as + // the user wrote in the explicit instantiation itself. This means + // that we'll pretty-print the type retrieved from the + // specialization's declaration the way that the user actually wrote + // the explicit instantiation, rather than formatting the name based + // on the "canonical" representation used to store the template + // arguments in the specialization. + TypeSourceInfo *WrittenTy + = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, + TemplateArgs, + Context.getTypeDeclType(Specialization)); + Specialization->setTypeAsWritten(WrittenTy); // Set source locations for keywords. - Specialization->setExternKeywordLoc(ExternLoc); + Specialization->setExternLoc(ExternLoc); Specialization->setTemplateKeywordLoc(TemplateLoc); Specialization->setBraceRange(SourceRange()); @@ -11242,11 +11257,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!HasNoEffect) { // Instantiate static data member or variable template. Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); - if (auto *VTSD = dyn_cast<VarTemplatePartialSpecializationDecl>(Prev)) { - VTSD->setExternKeywordLoc(ExternLoc); - VTSD->setTemplateKeywordLoc(TemplateLoc); - } - // Merge attributes. ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); if (PrevTemplate) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5315b14..d544cfa 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3858,16 +3858,15 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( // Substitute into the template arguments of the class template explicit // specialization. - TemplateArgumentListInfo InstTemplateArgs; - if (const ASTTemplateArgumentListInfo *TemplateArgsInfo = - D->getTemplateArgsAsWritten()) { - InstTemplateArgs.setLAngleLoc(TemplateArgsInfo->getLAngleLoc()); - InstTemplateArgs.setRAngleLoc(TemplateArgsInfo->getRAngleLoc()); - - if (SemaRef.SubstTemplateArguments(TemplateArgsInfo->arguments(), - TemplateArgs, InstTemplateArgs)) - return nullptr; - } + TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc(). + castAs<TemplateSpecializationTypeLoc>(); + TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(), + Loc.getRAngleLoc()); + SmallVector<TemplateArgumentLoc, 4> ArgLocs; + for (unsigned I = 0; I != Loc.getNumArgs(); ++I) + ArgLocs.push_back(Loc.getArgLoc(I)); + if (SemaRef.SubstTemplateArguments(ArgLocs, TemplateArgs, InstTemplateArgs)) + return nullptr; // Check that the template argument list is well-formed for this // class template. @@ -3921,7 +3920,6 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl::Create( SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), D->getLocation(), InstClassTemplate, CanonicalConverted, PrevDecl); - InstD->setTemplateArgsAsWritten(InstTemplateArgs); // Add this partial specialization to the set of class template partial // specializations. @@ -3938,10 +3936,22 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( TemplateName(InstClassTemplate), CanonicalConverted, SemaRef.Context.getRecordType(InstD)); + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( + TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs, + CanonType); + InstD->setAccess(D->getAccess()); InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); InstD->setSpecializationKind(D->getSpecializationKind()); - InstD->setExternKeywordLoc(D->getExternKeywordLoc()); + InstD->setTypeAsWritten(WrittenTy); + InstD->setExternLoc(D->getExternLoc()); InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc()); Owner->addDecl(InstD); @@ -3975,7 +3985,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( // Substitute the current template arguments. if (const ASTTemplateArgumentListInfo *TemplateArgsInfo = - D->getTemplateArgsAsWritten()) { + D->getTemplateArgsInfo()) { VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc()); VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc()); @@ -4033,7 +4043,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); - Var->setTemplateArgsAsWritten(TemplateArgsInfo); + Var->setTemplateArgsInfo(TemplateArgsInfo); if (!PrevDecl) { void *InsertPos = nullptr; VarTemplate->findSpecialization(Converted, InsertPos); @@ -4275,21 +4285,19 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( QualType CanonType = SemaRef.Context.getTemplateSpecializationType( TemplateName(ClassTemplate), CanonicalConverted); - // Create the class template partial specialization declaration. - ClassTemplatePartialSpecializationDecl *InstPartialSpec = - ClassTemplatePartialSpecializationDecl::Create( - SemaRef.Context, PartialSpec->getTagKind(), Owner, - PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, - ClassTemplate, CanonicalConverted, CanonType, - /*PrevDecl=*/nullptr); - - InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs); - - // Substitute the nested name specifier, if any. - if (SubstQualifier(PartialSpec, InstPartialSpec)) - return nullptr; - - InstPartialSpec->setInstantiatedFromMember(PartialSpec); + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy + = SemaRef.Context.getTemplateSpecializationTypeInfo( + TemplateName(ClassTemplate), + PartialSpec->getLocation(), + InstTemplateArgs, + CanonType); if (PrevDecl) { // We've already seen a partial specialization with the same template @@ -4307,14 +4315,28 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // // Outer<int, int> outer; // error: the partial specializations of Inner // // have the same signature. - SemaRef.Diag(InstPartialSpec->getLocation(), - diag::err_partial_spec_redeclared) - << InstPartialSpec; + SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) + << WrittenTy->getType(); SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) << SemaRef.Context.getTypeDeclType(PrevDecl); return nullptr; } + + // Create the class template partial specialization declaration. + ClassTemplatePartialSpecializationDecl *InstPartialSpec = + ClassTemplatePartialSpecializationDecl::Create( + SemaRef.Context, PartialSpec->getTagKind(), Owner, + PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, + ClassTemplate, CanonicalConverted, InstTemplateArgs, CanonType, + nullptr); + // Substitute the nested name specifier, if any. + if (SubstQualifier(PartialSpec, InstPartialSpec)) + return nullptr; + + InstPartialSpec->setInstantiatedFromMember(PartialSpec); + InstPartialSpec->setTypeAsWritten(WrittenTy); + // Check the completed partial specialization. SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); @@ -4383,6 +4405,46 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams, InsertPos); + // Build the canonical type that describes the converted template + // arguments of the variable template partial specialization. + QualType CanonType = SemaRef.Context.getTemplateSpecializationType( + TemplateName(VarTemplate), CanonicalConverted); + + // Build the fully-sugared type for this variable template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( + TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs, + CanonType); + + if (PrevDecl) { + // We've already seen a partial specialization with the same template + // parameters and template arguments. This can happen, for example, when + // substituting the outer template arguments ends up causing two + // variable template partial specializations of a member variable template + // to have identical forms, e.g., + // + // template<typename T, typename U> + // struct Outer { + // template<typename X, typename Y> pair<X,Y> p; + // template<typename Y> pair<T, Y> p; + // template<typename Y> pair<U, Y> p; + // }; + // + // Outer<int, int> outer; // error: the partial specializations of Inner + // // have the same signature. + SemaRef.Diag(PartialSpec->getLocation(), + diag::err_var_partial_spec_redeclared) + << WrittenTy->getType(); + SemaRef.Diag(PrevDecl->getLocation(), + diag::note_var_prev_partial_spec_here); + return nullptr; + } + // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType( PartialSpec->getTypeSourceInfo(), TemplateArgs, @@ -4402,39 +4464,16 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplatePartialSpecializationDecl::Create( SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), - DI, PartialSpec->getStorageClass(), CanonicalConverted); - - InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs); + DI, PartialSpec->getStorageClass(), CanonicalConverted, + InstTemplateArgs); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return nullptr; InstPartialSpec->setInstantiatedFromMember(PartialSpec); + InstPartialSpec->setTypeAsWritten(WrittenTy); - if (PrevDecl) { - // We've already seen a partial specialization with the same template - // parameters and template arguments. This can happen, for example, when - // substituting the outer template arguments ends up causing two - // variable template partial specializations of a member variable template - // to have identical forms, e.g., - // - // template<typename T, typename U> - // struct Outer { - // template<typename X, typename Y> pair<X,Y> p; - // template<typename Y> pair<T, Y> p; - // template<typename Y> pair<U, Y> p; - // }; - // - // Outer<int, int> outer; // error: the partial specializations of Inner - // // have the same signature. - SemaRef.Diag(PartialSpec->getLocation(), - diag::err_var_partial_spec_redeclared) - << InstPartialSpec; - SemaRef.Diag(PrevDecl->getLocation(), - diag::note_var_prev_partial_spec_here); - return nullptr; - } // Check the completed partial specialization. SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); @@ -5696,7 +5735,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, TemplateArgumentListInfo TemplateArgInfo; if (const ASTTemplateArgumentListInfo *ArgInfo = - VarSpec->getTemplateArgsAsWritten()) { + VarSpec->getTemplateArgsInfo()) { TemplateArgInfo.setLAngleLoc(ArgInfo->getLAngleLoc()); TemplateArgInfo.setRAngleLoc(ArgInfo->getRAngleLoc()); for (const TemplateArgumentLoc &Arg : ArgInfo->arguments()) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0c647086..089ede4 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2548,17 +2548,16 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( } } - // extern/template keyword locations for explicit instantiations - if (Record.readBool()) { - auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; - ExplicitInfo->ExternKeywordLoc = readSourceLocation(); + // Explicit info. + if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { + auto *ExplicitInfo = + new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = TyInfo; + ExplicitInfo->ExternLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; } - if (Record.readBool()) - D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo()); - return Redecl; } @@ -2568,6 +2567,7 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( // need them for profiling TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; + D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); @@ -2617,17 +2617,16 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( } } - // extern/template keyword locations for explicit instantiations - if (Record.readBool()) { - auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; - ExplicitInfo->ExternKeywordLoc = readSourceLocation(); + // Explicit info. + if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { + auto *ExplicitInfo = + new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = TyInfo; + ExplicitInfo->ExternLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; } - if (Record.readBool()) - D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo()); - SmallVector<TemplateArgument, 8> TemplArgs; Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true); D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs); @@ -2667,6 +2666,7 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; + D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index c2f1d1b..6201d28 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1765,28 +1765,20 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl()); } - bool ExplicitInstantiation = - D->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDeclaration || - D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; - Record.push_back(ExplicitInstantiation); - if (ExplicitInstantiation) { - Record.AddSourceLocation(D->getExternKeywordLoc()); + // Explicit info. + Record.AddTypeSourceInfo(D->getTypeAsWritten()); + if (D->getTypeAsWritten()) { + Record.AddSourceLocation(D->getExternLoc()); Record.AddSourceLocation(D->getTemplateKeywordLoc()); } - const ASTTemplateArgumentListInfo *ArgsWritten = - D->getTemplateArgsAsWritten(); - Record.push_back(!!ArgsWritten); - if (ArgsWritten) - Record.AddASTTemplateArgumentListInfo(ArgsWritten); - Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; } void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { Record.AddTemplateParameterList(D->getTemplateParameters()); + Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); VisitClassTemplateSpecializationDecl(D); @@ -1820,22 +1812,13 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); } - bool ExplicitInstantiation = - D->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDeclaration || - D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; - Record.push_back(ExplicitInstantiation); - if (ExplicitInstantiation) { - Record.AddSourceLocation(D->getExternKeywordLoc()); + // Explicit info. + Record.AddTypeSourceInfo(D->getTypeAsWritten()); + if (D->getTypeAsWritten()) { + Record.AddSourceLocation(D->getExternLoc()); Record.AddSourceLocation(D->getTemplateKeywordLoc()); } - const ASTTemplateArgumentListInfo *ArgsWritten = - D->getTemplateArgsAsWritten(); - Record.push_back(!!ArgsWritten); - if (ArgsWritten) - Record.AddASTTemplateArgumentListInfo(ArgsWritten); - Record.AddTemplateArgumentList(&D->getTemplateArgs()); Record.AddSourceLocation(D->getPointOfInstantiation()); Record.push_back(D->getSpecializationKind()); @@ -1856,6 +1839,7 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { Record.AddTemplateParameterList(D->getTemplateParameters()); + Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); VisitVarTemplateSpecializationDecl(D); diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 3e50d67f..cd02619 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -735,8 +735,7 @@ public: auto *Declaration = cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C)); foldExplicitTemplateInstantiation( - Builder.getTemplateRange(C), - Builder.findToken(C->getExternKeywordLoc()), + Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()), Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C); return true; } diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index 37f6d8a..142bc9e 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -1,12 +1,12 @@ // Test without serialization: // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -ast-dump %s \ -// RUN: | FileCheck -strict-whitespace %s +// RUN: | FileCheck -strict-whitespace %s --check-prefix=DIRECT // // Test with serialization: // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -include-pch %t -ast-dump-all /dev/null \ // RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \ -// RUN: | FileCheck --strict-whitespace %s +// RUN: | FileCheck --strict-whitespace %s --check-prefix=SERIALIZED template <typename Ty> // CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <{{.*}}:1, line:[[@LINE+2]]:10> col:6 a @@ -189,13 +189,15 @@ T unTempl = 1; template<> int unTempl<int>; -// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:16> col:5 unTempl 'int' +// FIXME (#61680) - serializing and loading AST should not affect reported source range +// DIRECT: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:16> col:5 unTempl 'int' +// SERIALIZED: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:5> col:5 unTempl 'int' // CHECK-NEXT: `-TemplateArgument type 'int' // CHECK-NEXT: `-BuiltinType 0x{{[^ ]*}} 'int' template<> float unTempl<float> = 1; -// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 unTempl 'float' +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 unTempl 'float' cinit // CHECK-NEXT: |-TemplateArgument type 'float' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float' // CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}} <col:24> 'float' <IntegralToFloating> @@ -220,7 +222,7 @@ int binTempl<int, U>; template<class U> float binTempl<float, U> = 1; -// CHECK: VarTemplatePartialSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:28> col:7 binTempl 'float' +// CHECK: VarTemplatePartialSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 binTempl 'float' cinit // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:10, col:16> col:16 referenced class depth 0 index 0 U // CHECK-NEXT: |-TemplateArgument type 'float' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float' @@ -231,7 +233,9 @@ float binTempl<float, U> = 1; template<> int binTempl<int, int>; -// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:22> col:5 binTempl 'int' +// FIXME (#61680) - serializing and loading AST should not affect reported source range +// DIRECT: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:22> col:5 binTempl 'int' +// SERIALIZED: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:5> col:5 binTempl 'int' // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int' // CHECK-NEXT: `-TemplateArgument type 'int' @@ -239,7 +243,7 @@ int binTempl<int, int>; template<> float binTempl<float, float> = 1; -// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:32> col:7 binTempl 'float' +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:32> col:7 binTempl 'float' cinit // CHECK-NEXT: |-TemplateArgument type 'float' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float' // CHECK-NEXT: |-TemplateArgument type 'float' diff --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp index 043e616..8f9fbc4 100644 --- a/clang/test/Index/Core/index-source.cpp +++ b/clang/test/Index/Core/index-source.cpp @@ -285,17 +285,20 @@ template<> class SpecializationDecl<int>; // CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Decl,RelSpecialization | rel: 1 // CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T@SpecializationDecl +// CHECK: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Ref | rel: 0 template<> class SpecializationDecl<int> { }; // CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Def,RelSpecialization | rel: 1 // CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T@SpecializationDecl +// CHECK-NEXT: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Ref | rel: 0 template<typename T> class PartialSpecilizationClass<Cls, T>; // CHECK: [[@LINE-1]]:7 | class(Gen,TPS)/C++ | PartialSpecilizationClass | c:@SP>1#T@PartialSpecilizationClass>#$@S@Cls#t0.0 | <no-cgname> | Decl,RelSpecialization | rel: 1 // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass -// CHECK-NEXT: [[@LINE-3]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-3]]:7 | class(Gen)/C++ | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass | <no-cgname> | Ref | rel: 0 +// CHECK-NEXT: [[@LINE-4]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 template<> class PartialSpecilizationClass<Cls, Cls> : Cls { }; @@ -303,10 +306,9 @@ class PartialSpecilizationClass<Cls, Cls> : Cls { }; // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass // CHECK-NEXT: [[@LINE-3]]:45 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelBase,RelCont | rel: 1 // CHECK-NEXT: RelBase,RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ -// CHECK-NEXT: [[@LINE-5]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 -// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ -// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 -// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ +// CHECK-NEXT: [[@LINE-5]]:7 | class(Gen,TS)/C++ | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ | <no-cgname> | Ref | rel: 0 +// CHECK-NEXT: [[@LINE-6]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 +// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 template<typename T, int x> void functionSp() { } @@ -330,14 +332,10 @@ class ClassWithCorrectSpecialization { }; template<> class ClassWithCorrectSpecialization<SpecializationDecl<Cls>, Record::C> { }; -// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | <no-cgname> | Ref,RelCont | rel: 1 -// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 -// CHECK-NEXT: [[@LINE-3]]:57 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 -// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 -// CHECK-NEXT: [[@LINE-5]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read,RelCont | rel: 1 -// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 -// CHECK-NEXT: [[@LINE-7]]:63 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref,RelCont | rel: 1 -// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 +// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | <no-cgname> | Ref | rel: 0 +// CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 +// CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read | rel: 0 +// CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref | rel: 0 namespace ns { // CHECK: [[@LINE-1]]:11 | namespace/C++ | ns | c:@N@ns | <no-cgname> | Decl | rel: 0 diff --git a/clang/test/Index/index-refs.cpp b/clang/test/Index/index-refs.cpp index 1494684..0e613e4 100644 --- a/clang/test/Index/index-refs.cpp +++ b/clang/test/Index/index-refs.cpp @@ -108,6 +108,7 @@ int ginitlist[] = {EnumVal}; // CHECK: [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 47:8 // CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 50:8 // CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] +// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | <parent>:: <<NULL>> | container: [TU] | refkind: direct | role: ref /* when indexing implicit instantiations [indexDeclaration]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 50:8 [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@593@S@TS>#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 60241af..b845a38 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -743,10 +743,14 @@ bool CursorVisitor::VisitClassTemplateSpecializationDecl( } // Visit the template arguments used in the specialization. - if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { - for (const TemplateArgumentLoc &Arg : ArgsWritten->arguments()) - if (VisitTemplateArgumentLoc(Arg)) - return true; + if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) { + TypeLoc TL = SpecType->getTypeLoc(); + if (TemplateSpecializationTypeLoc TSTLoc = + TL.getAs<TemplateSpecializationTypeLoc>()) { + for (unsigned I = 0, N = TSTLoc.getNumArgs(); I != N; ++I) + if (VisitTemplateArgumentLoc(TSTLoc.getArgLoc(I))) + return true; + } } return ShouldVisitBody && VisitCXXRecordDecl(D); @@ -5655,19 +5659,16 @@ CXString clang_getCursorDisplayName(CXCursor C) { if (const ClassTemplateSpecializationDecl *ClassSpec = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + // If the type was explicitly written, use that. + if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten()) + return cxstring::createDup(TSInfo->getType().getAsString(Policy)); + SmallString<128> Str; llvm::raw_svector_ostream OS(Str); OS << *ClassSpec; - // If the template arguments were written explicitly, use them.. - if (const auto *ArgsWritten = ClassSpec->getTemplateArgsAsWritten()) { - printTemplateArgumentList( - OS, ArgsWritten->arguments(), Policy, - ClassSpec->getSpecializedTemplate()->getTemplateParameters()); - } else { - printTemplateArgumentList( - OS, ClassSpec->getTemplateArgs().asArray(), Policy, - ClassSpec->getSpecializedTemplate()->getTemplateParameters()); - } + printTemplateArgumentList( + OS, ClassSpec->getTemplateArgs().asArray(), Policy, + ClassSpec->getSpecializedTemplate()->getTemplateParameters()); return cxstring::createDup(OS.str()); } diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 65df513..b76627c 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2213,6 +2213,18 @@ TEST_P(ASTMatchersTest, ReferenceTypeLocTest_BindsToAnyRvalueReferenceTypeLoc) { EXPECT_TRUE(matches("float&& r = 3.0;", matcher)); } +TEST_P( + ASTMatchersTest, + TemplateSpecializationTypeLocTest_BindsToTemplateSpecializationExplicitInstantiation) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE( + matches("template <typename T> class C {}; template class C<int>;", + classTemplateSpecializationDecl( + hasName("C"), hasTypeLoc(templateSpecializationTypeLoc())))); +} + TEST_P(ASTMatchersTest, TemplateSpecializationTypeLocTest_BindsToVarDeclTemplateSpecialization) { if (!GetParam().isCXX()) { diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index af99c73..f198dc7 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -430,6 +430,12 @@ TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) { cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T")))))); } +TEST(HasTypeLoc, MatchesClassTemplateSpecializationDecl) { + EXPECT_TRUE(matches( + "template <typename T> class Foo; template <> class Foo<int> {};", + classTemplateSpecializationDecl(hasTypeLoc(loc(asString("Foo<int>")))))); +} + TEST(HasTypeLoc, MatchesCompoundLiteralExpr) { EXPECT_TRUE( matches("int* x = (int[2]) { 0, 1 };", @@ -6378,7 +6384,8 @@ TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) { "template<typename T> class A {}; template<> class A<int> {};", classTemplateSpecializationDecl( hasName("A"), - hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))); + hasTypeLoc(templateSpecializationTypeLoc( + hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))))); } TEST(HasAnyTemplateArgumentLoc, @@ -6387,7 +6394,8 @@ TEST(HasAnyTemplateArgumentLoc, "template<typename T> class A {}; template<> class A<double> {};", classTemplateSpecializationDecl( hasName("A"), - hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double"))))))); + hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( + hasTypeLoc(loc(asString("double"))))))))); } TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { @@ -6397,20 +6405,24 @@ TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { )"; EXPECT_TRUE( matches(code, classTemplateSpecializationDecl( - hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc( - loc(asString("double"))))))); - + hasName("A"), hasTypeLoc(templateSpecializationTypeLoc( + hasAnyTemplateArgumentLoc(hasTypeLoc( + loc(asString("double"))))))))); EXPECT_TRUE(matches( - code, classTemplateSpecializationDecl( - hasName("A"), - hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))); + code, + classTemplateSpecializationDecl( + hasName("A"), + hasTypeLoc(templateSpecializationTypeLoc( + hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))))); } TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) { - EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;", - classTemplateSpecializationDecl( - hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc( - loc(asString("double"))))))); + EXPECT_TRUE(notMatches( + "template<typename T> class A {}; A<int> a;", + classTemplateSpecializationDecl( + hasName("A"), + hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( + hasTypeLoc(loc(asString("double"))))))))); } TEST(HasAnyTemplateArgumentLoc, @@ -6419,7 +6431,8 @@ TEST(HasAnyTemplateArgumentLoc, "template<typename T> class A {}; template<> class A<int> {};", classTemplateSpecializationDecl( hasName("A"), - hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double"))))))); + hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( + hasTypeLoc(loc(asString("double"))))))))); } TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) { @@ -6440,21 +6453,13 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) { 0, hasTypeLoc(loc(asString("double"))))))))))); } -TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) { - EXPECT_TRUE(notMatches( - "template<typename T> class A {}; A<int> a;", - varDecl(hasName("a"), - hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc( - templateSpecializationTypeLoc(hasTemplateArgumentLoc( - 0, hasTypeLoc(loc(asString("double"))))))))))); -} - TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) { EXPECT_TRUE(matches( "template<typename T> class A {}; template<> class A<int> {};", classTemplateSpecializationDecl( hasName("A"), - hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int"))))))); + hasTypeLoc(templateSpecializationTypeLoc( + hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int"))))))))); } TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) { @@ -6462,7 +6467,8 @@ TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) { "template<typename T> class A {}; template<> class A<double> {};", classTemplateSpecializationDecl( hasName("A"), - hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double"))))))); + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 0, hasTypeLoc(loc(asString("double"))))))))); } TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { @@ -6472,12 +6478,23 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { )"; EXPECT_TRUE(matches( code, classTemplateSpecializationDecl( - hasName("A"), hasTemplateArgumentLoc( - 0, hasTypeLoc(loc(asString("double"))))))); + hasName("A"), + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 0, hasTypeLoc(loc(asString("double"))))))))); EXPECT_TRUE(matches( code, classTemplateSpecializationDecl( hasName("A"), - hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int"))))))); + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 1, hasTypeLoc(loc(asString("int"))))))))); +} + +TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) { + EXPECT_TRUE(notMatches( + "template<typename T> class A {}; A<int> a;", + classTemplateSpecializationDecl( + hasName("A"), + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 0, hasTypeLoc(loc(asString("double"))))))))); } TEST(HasTemplateArgumentLoc, @@ -6486,7 +6503,8 @@ TEST(HasTemplateArgumentLoc, "template<typename T> class A {}; template<> class A<int> {};", classTemplateSpecializationDecl( hasName("A"), - hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double"))))))); + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 0, hasTypeLoc(loc(asString("double"))))))))); } TEST(HasTemplateArgumentLoc, @@ -6497,12 +6515,14 @@ TEST(HasTemplateArgumentLoc, )"; EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( - hasName("A"), hasTemplateArgumentLoc( - 1, hasTypeLoc(loc(asString("double"))))))); + hasName("A"), + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 1, hasTypeLoc(loc(asString("double"))))))))); EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( hasName("A"), - hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int"))))))); + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 0, hasTypeLoc(loc(asString("int"))))))))); } TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) { @@ -6512,12 +6532,14 @@ TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) { )"; EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( - hasName("A"), hasTemplateArgumentLoc( - -1, hasTypeLoc(loc(asString("double"))))))); + hasName("A"), + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + -1, hasTypeLoc(loc(asString("double"))))))))); EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( - hasName("A"), hasTemplateArgumentLoc( - 100, hasTypeLoc(loc(asString("int"))))))); + hasName("A"), + hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( + 100, hasTypeLoc(loc(asString("int"))))))))); } TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) { |