diff options
Diffstat (limited to 'clang')
23 files changed, 819 insertions, 693 deletions
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index bb1b68f..a16b9c4 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3546,33 +3546,35 @@ 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('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> -<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> @@ -6713,7 +6715,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_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_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>> @@ -6757,7 +6759,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_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_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>> @@ -6985,7 +6987,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_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_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>> @@ -7219,7 +7221,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_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_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>> @@ -7416,7 +7418,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_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_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>> @@ -7620,7 +7622,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_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_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>> @@ -7677,7 +7679,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_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_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>> @@ -7875,9 +7877,10 @@ 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 classTemplateSpecialization, templateSpecializationType and -functionDecl 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 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> @@ -7899,10 +7902,25 @@ 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 classTemplateSpecializations, templateSpecializationType and -functionDecl that have at least one TemplateArgument matching the given -InnerMatcher. +<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. Given template<typename T> class A {}; @@ -7933,9 +7951,25 @@ 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 classTemplateSpecializations, templateSpecializationType and -functionDecl where the n'th TemplateArgument matches the given InnerMatcher. +<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. Given template<typename T, typename U> class A {}; @@ -7953,34 +7987,6 @@ 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. @@ -7996,8 +8002,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('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_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. Examples: int x; @@ -8017,7 +8023,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_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_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>> @@ -8066,6 +8072,21 @@ 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. @@ -8100,9 +8121,10 @@ 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('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`. +<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`. Given template<typename T, typename U> class A {}; @@ -8176,8 +8198,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('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_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. Examples: int x; @@ -8197,7 +8219,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_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_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>> @@ -8393,8 +8415,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('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_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. Examples: int x; @@ -8414,7 +8436,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_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_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>> @@ -8707,9 +8729,10 @@ 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 classTemplateSpecialization, templateSpecializationType and -functionDecl 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 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> @@ -8778,10 +8801,25 @@ 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 classTemplateSpecializations, templateSpecializationType and -functionDecl that have at least one TemplateArgument matching the given -InnerMatcher. +<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. Given template<typename T> class A {}; @@ -8878,9 +8916,25 @@ 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 classTemplateSpecializations, templateSpecializationType and -functionDecl where the n'th TemplateArgument matches the given InnerMatcher. +<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. Given template<typename T, typename U> class A {}; @@ -9473,8 +9527,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('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_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. Examples: int x; @@ -9494,7 +9548,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_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_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>> @@ -9919,8 +9973,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('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_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. Examples: int x; @@ -9940,7 +9994,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_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_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>> @@ -10014,9 +10068,11 @@ 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('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`. +<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`. Given template<typename T> class A {}; @@ -10027,9 +10083,10 @@ 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('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`. +<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`. Given template<typename T, typename U> class A {}; @@ -10041,10 +10098,11 @@ 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('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. +<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. Given template <typename T, unsigned N, unsigned M> @@ -10066,10 +10124,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('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. +<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. Given template<typename T> class A {}; @@ -10122,9 +10180,10 @@ 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('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. +<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. Given template<typename T, typename U> class A {}; @@ -10182,8 +10241,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('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. +<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. Examples: int x; @@ -10203,7 +10262,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_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_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>> @@ -10449,6 +10508,105 @@ 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 cc3108b..2fae573 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -111,6 +111,9 @@ 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 3ee03ee..36fb7ec 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1776,6 +1776,25 @@ 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. /// @@ -1789,8 +1808,8 @@ public: /// 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. @@ -1809,22 +1828,8 @@ class ClassTemplateSpecializationDecl 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. - ExplicitSpecializationInfo *ExplicitInfo = nullptr; + SpecializationOrInstantiationInfo ExplicitInfo = nullptr; /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; @@ -2001,44 +2006,49 @@ public: SpecializedTemplate = TemplDecl; } - /// 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; + /// 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 *>(); } - /// 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; + /// 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; } - /// Gets the location of the extern keyword, if present. - SourceLocation getExternLoc() const { - return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); + /// Set the template argument list as written in the sources. + void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { + setTemplateArgsAsWritten( + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); } - /// Sets the location of the extern keyword. - void setExternLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->ExternLoc = Loc; + /// Gets the location of the extern keyword, if present. + SourceLocation getExternKeywordLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->ExternKeywordLoc; + return SourceLocation(); } - /// Sets the location of the template keyword. - void setTemplateKeywordLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TemplateKeywordLoc = Loc; - } + /// Sets the location of the extern keyword. + void setExternKeywordLoc(SourceLocation Loc); /// Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { - return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateKeywordLoc; + return SourceLocation(); } + /// Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc); + SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { @@ -2066,10 +2076,6 @@ 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. /// @@ -2078,15 +2084,11 @@ 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, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ClassTemplatePartialSpecializationDecl *PrevDecl); + ClassTemplatePartialSpecializationDecl( + ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, + ClassTemplatePartialSpecializationDecl *PrevDecl); ClassTemplatePartialSpecializationDecl(ASTContext &C) : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization), @@ -2101,11 +2103,8 @@ public: static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, - ArrayRef<TemplateArgument> Args, - const TemplateArgumentListInfo &ArgInfos, - QualType CanonInjectedType, + TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl); static ClassTemplatePartialSpecializationDecl * @@ -2136,11 +2135,6 @@ 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. @@ -2614,26 +2608,11 @@ 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. - ExplicitSpecializationInfo *ExplicitInfo = nullptr; + SpecializationOrInstantiationInfo 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; @@ -2687,14 +2666,6 @@ 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 { @@ -2798,44 +2769,49 @@ public: SpecializedTemplate = TemplDecl; } - /// 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; + /// 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; } - /// 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; + /// Set the template argument list as written in the sources. + void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { + setTemplateArgsAsWritten( + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); } /// Gets the location of the extern keyword, if present. - SourceLocation getExternLoc() const { - return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); + SourceLocation getExternKeywordLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->ExternKeywordLoc; + return SourceLocation(); } /// Sets the location of the extern keyword. - 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; - } + void setExternKeywordLoc(SourceLocation Loc); /// Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { - return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateKeywordLoc; + return SourceLocation(); } + /// Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc); + SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { @@ -2863,10 +2839,6 @@ 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. /// @@ -2879,8 +2851,7 @@ class VarTemplatePartialSpecializationDecl ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args, - const ASTTemplateArgumentListInfo *ArgInfos); + StorageClass S, ArrayRef<TemplateArgument> Args); VarTemplatePartialSpecializationDecl(ASTContext &Context) : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, @@ -2897,8 +2868,8 @@ public: Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, - TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args, - const TemplateArgumentListInfo &ArgInfos); + TypeSourceInfo *TInfo, StorageClass S, + ArrayRef<TemplateArgument> Args); static VarTemplatePartialSpecializationDecl * CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -2914,11 +2885,6 @@ 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 f9b145b..782f608 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2030,6 +2030,15 @@ 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 \ @@ -2039,9 +2048,12 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) 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 getTypeAsWritten() to distinguish. */ \ - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ + We use getTemplateArgsAsWritten() to distinguish. */ \ + if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \ + /* The args that remains unspecialized. */ \ + TRY_TO(TraverseTemplateArgumentLocsHelper( \ + ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \ + } \ \ if (getDerived().shouldVisitTemplateInstantiations() || \ D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ @@ -2061,15 +2073,6 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) 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 8a2bbff..0f3257d 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 classTemplateSpecializations, templateSpecializationType and -/// functionDecl that have at least one TemplateArgument matching the given -/// InnerMatcher. +/// Matches templateSpecializationTypes, class template specializations, +/// variable template specializations, and function template specializations +/// 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, - TemplateSpecializationType, - FunctionDecl), + VarTemplateSpecializationDecl, FunctionDecl, + TemplateSpecializationType), internal::Matcher<TemplateArgument>, InnerMatcher) { ArrayRef<TemplateArgument> List = internal::getTemplateSpecializationArgs(Node); @@ -1047,8 +1047,9 @@ AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); } /// expr(isValueDependent()) matches return Size AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); } -/// Matches classTemplateSpecializations, templateSpecializationType and -/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher. +/// Matches templateSpecializationType, class template specializations, +/// variable template specializations, and function template specializations +/// where the n'th TemplateArgument matches the given InnerMatcher. /// /// Given /// \code @@ -1068,8 +1069,8 @@ AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); } AST_POLYMORPHIC_MATCHER_P2( hasTemplateArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - TemplateSpecializationType, - FunctionDecl), + VarTemplateSpecializationDecl, FunctionDecl, + TemplateSpecializationType), unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) { ArrayRef<TemplateArgument> List = internal::getTemplateSpecializationArgs(Node); @@ -4066,7 +4067,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD( /// Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, /// Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, /// Matcher<CXXUnresolvedConstructExpr>, -/// Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, +/// Matcher<CompoundLiteralExpr>, /// Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, /// Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, /// Matcher<TypedefNameDecl> @@ -4075,9 +4076,8 @@ AST_POLYMORPHIC_MATCHER_P( AST_POLYMORPHIC_SUPPORTED_TYPES( BlockDecl, CXXBaseSpecifier, CXXCtorInitializer, CXXFunctionalCastExpr, CXXNewExpr, CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr, - ClassTemplateSpecializationDecl, CompoundLiteralExpr, DeclaratorDecl, - ExplicitCastExpr, ObjCPropertyDecl, TemplateArgumentLoc, - TypedefNameDecl), + CompoundLiteralExpr, DeclaratorDecl, ExplicitCastExpr, ObjCPropertyDecl, + TemplateArgumentLoc, TypedefNameDecl), internal::Matcher<TypeLoc>, Inner) { TypeSourceInfo *source = internal::GetTypeSourceInfo(Node); if (source == nullptr) { @@ -5304,9 +5304,10 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs, return Node.getNumParams() == N; } -/// Matches classTemplateSpecialization, templateSpecializationType and -/// functionDecl nodes where the template argument matches the inner matcher. -/// This matcher may produce multiple matches. +/// 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 /// \code @@ -5330,7 +5331,8 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs, AST_POLYMORPHIC_MATCHER_P( forEachTemplateArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - TemplateSpecializationType, FunctionDecl), + VarTemplateSpecializationDecl, FunctionDecl, + TemplateSpecializationType), internal::Matcher<TemplateArgument>, InnerMatcher) { ArrayRef<TemplateArgument> TemplateArgs = clang::ast_matchers::internal::getTemplateSpecializationArgs(Node); @@ -6905,8 +6907,10 @@ extern const internal::VariadicDynCastAllOfMatcher< TypeLoc, TemplateSpecializationTypeLoc> templateSpecializationTypeLoc; -/// Matches template specialization `TypeLoc`s that have at least one -/// `TemplateArgumentLoc` matching the given `InnerMatcher`. +/// 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 /// \code @@ -6916,20 +6920,21 @@ extern const internal::VariadicDynCastAllOfMatcher< /// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( /// hasTypeLoc(loc(asString("int"))))))) /// matches `A<int> a`. -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; - } - } +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(); return false; } -/// Matches template specialization `TypeLoc`s where the n'th -/// `TemplateArgumentLoc` matches the given `InnerMatcher`. +/// 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 /// \code @@ -6942,10 +6947,13 @@ AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc, /// matches `A<double, int> b`, but not `A<int, double> c`. AST_POLYMORPHIC_MATCHER_P2( hasTemplateArgumentLoc, - AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, TemplateSpecializationTypeLoc), + AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, + VarTemplateSpecializationDecl, FunctionDecl, + DeclRefExpr, TemplateSpecializationTypeLoc), unsigned, Index, internal::Matcher<TemplateArgumentLoc>, InnerMatcher) { - return internal::MatchTemplateArgLocAt(Node, Index, InnerMatcher, Finder, - Builder); + auto Args = internal::getTemplateArgsWritten(Node); + return Index < Args.size() && + InnerMatcher.matches(Args[Index], 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 47d912c..c1cc63f 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -186,10 +186,6 @@ 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.. @@ -1940,6 +1936,11 @@ 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(); } @@ -1948,7 +1949,46 @@ inline ArrayRef<TemplateArgument> getTemplateSpecializationArgs(const FunctionDecl &FD) { if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs()) return TemplateArgs->asArray(); - return ArrayRef<TemplateArgument>(); + 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; } struct NotEqualsBoundNodePredicate { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 60f21332..9ff8e1e 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -443,8 +443,9 @@ namespace clang { Expected<FunctionTemplateAndArgsTy> ImportFunctionTemplateWithTemplateArgsFromSpecialization( FunctionDecl *FromFD); - Error ImportTemplateParameterLists(const DeclaratorDecl *FromD, - DeclaratorDecl *ToD); + + template <typename DeclTy> + Error ImportTemplateParameterLists(const DeclTy *FromD, DeclTy *ToD); Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); @@ -3322,8 +3323,9 @@ ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { return ToEnumerator; } -Error ASTNodeImporter::ImportTemplateParameterLists(const DeclaratorDecl *FromD, - DeclaratorDecl *ToD) { +template <typename DeclTy> +Error ASTNodeImporter::ImportTemplateParameterLists(const DeclTy *FromD, + DeclTy *ToD) { unsigned int Num = FromD->getNumTemplateParameterLists(); if (Num == 0) return Error::success(); @@ -6210,15 +6212,16 @@ 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())) @@ -6228,7 +6231,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, *IdLocOrErr, ToTPList, ClassTemplate, - llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo, + llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), CanonInjType, cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) return D2; @@ -6276,28 +6279,27 @@ 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 (auto *TSI = D->getTypeAsWritten()) { - if (auto TInfoOrErr = import(TSI)) - D2->setTypeAsWritten(*TInfoOrErr); - else - return TInfoOrErr.takeError(); + if (D->getTemplateArgsAsWritten()) + D2->setTemplateArgsAsWritten(ToTAInfo); - 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->getExternLoc())) - D2->setExternLoc(*LocOrErr); - else - return LocOrErr.takeError(); - } + if (auto LocOrErr = import(D->getExternKeywordLoc())) + D2->setExternKeywordLoc(*LocOrErr); + else + return LocOrErr.takeError(); if (D->getPointOfInstantiation().isValid()) { if (auto POIOrErr = import(D->getPointOfInstantiation())) @@ -6517,7 +6519,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *D2 = nullptr; TemplateArgumentListInfo ToTAInfo; - if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { + if (const auto *Args = D->getTemplateArgsAsWritten()) { if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) return std::move(Err); } @@ -6525,14 +6527,6 @@ 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(); @@ -6541,7 +6535,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, VarTemplate, QualType(), nullptr, - D->getStorageClass(), TemplateArgs, ArgInfos)) + D->getStorageClass(), TemplateArgs)) return ToPartial; if (Expected<PartVarSpecDecl *> ToInstOrErr = @@ -6584,7 +6578,9 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( } D2->setSpecializationKind(D->getSpecializationKind()); - D2->setTemplateArgsInfo(ToTAInfo); + + if (D->getTemplateArgsAsWritten()) + D2->setTemplateArgsAsWritten(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 599d379..c586825 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)) { - 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()); + 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); } } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index d27a30e..af2d8d72 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -985,41 +985,63 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { SourceRange ClassTemplateSpecializationDecl::getSourceRange() const { - 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 { + if (getSpecializationKind() == TSK_ExplicitInstantiationDeclaration) { + return SourceRange(getExternKeywordLoc(), + getTemplateArgsAsWritten()->getRAngleLoc()); + } else if (getSpecializationKind() == TSK_ExplicitInstantiationDefinition) { + return SourceRange(getTemplateKeywordLoc(), + getTemplateArgsAsWritten()->getRAngleLoc()); + } else if (!isExplicitSpecialization()) { // No explicit info available. llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> - inst_from = getInstantiatedFrom(); - if (inst_from.isNull()) + InstFrom = getInstantiatedFrom(); + if (InstFrom.isNull()) return getSpecializedTemplate()->getSourceRange(); - if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>()) - return ctd->getSourceRange(); - return inst_from.get<ClassTemplatePartialSpecializationDecl *>() - ->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; } + 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; } //===----------------------------------------------------------------------===// @@ -1087,43 +1109,29 @@ 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, - const ASTTemplateArgumentListInfo *ArgInfos, - ClassTemplatePartialSpecializationDecl *PrevDecl) - : ClassTemplateSpecializationDecl(Context, - ClassTemplatePartialSpecialization, - TK, DC, StartLoc, IdLoc, - SpecializedTemplate, Args, PrevDecl), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - InstantiatedFromMember(nullptr, false) { +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) { 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, - 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); +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); Result->setSpecializationKind(TSK_ExplicitSpecialization); Result->setMayHaveOutOfDateDef(false); @@ -1371,26 +1379,47 @@ 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 = getTemplateArgsInfo()) + if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) 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 @@ -1402,13 +1431,11 @@ VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args, - const ASTTemplateArgumentListInfo *ArgInfos) + StorageClass S, ArrayRef<TemplateArgument> Args) : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context, DC, StartLoc, IdLoc, SpecializedTemplate, T, TInfo, S, Args), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - InstantiatedFromMember(nullptr, false) { + TemplateParams(Params), InstantiatedFromMember(nullptr, false) { if (AdoptTemplateParameterList(Params, DC)) setInvalidDecl(); } @@ -1418,15 +1445,10 @@ VarTemplatePartialSpecializationDecl::Create( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - 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); + StorageClass S, ArrayRef<TemplateArgument> Args) { + auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl( + Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S, + Args); Result->setSpecializationKind(TSK_ExplicitSpecialization); return Result; } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 9602f44..87f0a87 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1472,21 +1472,18 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { // If this is a class template specialization, print the template // arguments. - 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(); - } + if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + const TemplateParameterList *TParams = + S->getSpecializedTemplate()->getTemplateParameters(); + const ASTTemplateArgumentListInfo *TArgAsWritten = + S->getTemplateArgsAsWritten(); IncludeStrongLifetimeRAII Strong(Policy); - printTemplateArgumentList( - OS, Args, Policy, - Spec->getSpecializedTemplate()->getTemplateParameters()); + if (TArgAsWritten && !Policy.PrintCanonicalTypes) + printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy, + TParams); + else + printTemplateArgumentList(OS, S->getTemplateArgs().asArray(), Policy, + TParams); } spaceBeforePlaceHolder(OS); diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 1c04aa1..8eb88f5 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -673,9 +673,12 @@ public: IndexCtx.indexTagDecl( D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), SpecializationOf)); - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) - IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, - D->getLexicalDeclContext()); + // Template specialization arguments. + if (const ASTTemplateArgumentListInfo *TemplateArgInfo = + D->getTemplateArgsAsWritten()) { + for (const auto &Arg : TemplateArgInfo->arguments()) + handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); + } return true; } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index a1e32d3..0febf4e 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->getTemplateArgsInfo()) + VTSD->getTemplateArgsAsWritten()) DiagRange.setEnd(ASTTAL->RAngleLoc); } if (DiagD->isReferenced()) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5c72270..b268d7c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5166,7 +5166,8 @@ DeclResult Sema::ActOnVarTemplateSpecialization( VarTemplatePartialSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, - CanonicalConverted, TemplateArgs); + CanonicalConverted); + Partial->setTemplateArgsAsWritten(TemplateArgs); if (!PrevPartial) VarTemplate->AddPartialSpecialization(Partial, InsertPos); @@ -5184,7 +5185,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( Specialization = VarTemplateSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, VarTemplate, DI->getType(), DI, SC, CanonicalConverted); - Specialization->setTemplateArgsInfo(TemplateArgs); + Specialization->setTemplateArgsAsWritten(TemplateArgs); if (!PrevDecl) VarTemplate->AddSpecialization(Specialization, InsertPos); @@ -5219,7 +5220,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization( } } - Specialization->setTemplateKeywordLoc(TemplateKWLoc); Specialization->setLexicalDeclContext(CurContext); // Add the specialization into its lexical context, so that it can @@ -9489,7 +9489,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( ClassTemplatePartialSpecializationDecl::Create( Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted, - TemplateArgs, CanonType, PrevPartial); + CanonType, PrevPartial); + Partial->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo( @@ -9512,6 +9513,7 @@ 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, @@ -9595,21 +9597,6 @@ 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. @@ -9625,6 +9612,15 @@ 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, @@ -10830,21 +10826,10 @@ DeclResult Sema::ActOnExplicitInstantiation( } } - // 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); + Specialization->setTemplateArgsAsWritten(TemplateArgs); // Set source locations for keywords. - Specialization->setExternLoc(ExternLoc); + Specialization->setExternKeywordLoc(ExternLoc); Specialization->setTemplateKeywordLoc(TemplateLoc); Specialization->setBraceRange(SourceRange()); @@ -11257,6 +11242,11 @@ 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 d544cfa..5315b14 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3858,15 +3858,16 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( // Substitute into the template arguments of the class template explicit // specialization. - 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; + 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; + } // Check that the template argument list is well-formed for this // class template. @@ -3920,6 +3921,7 @@ 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. @@ -3936,22 +3938,10 @@ 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->setTypeAsWritten(WrittenTy); - InstD->setExternLoc(D->getExternLoc()); + InstD->setExternKeywordLoc(D->getExternKeywordLoc()); InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc()); Owner->addDecl(InstD); @@ -3985,7 +3975,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( // Substitute the current template arguments. if (const ASTTemplateArgumentListInfo *TemplateArgsInfo = - D->getTemplateArgsInfo()) { + D->getTemplateArgsAsWritten()) { VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc()); VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc()); @@ -4043,7 +4033,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); - Var->setTemplateArgsInfo(TemplateArgsInfo); + Var->setTemplateArgsAsWritten(TemplateArgsInfo); if (!PrevDecl) { void *InsertPos = nullptr; VarTemplate->findSpecialization(Converted, InsertPos); @@ -4285,19 +4275,21 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( QualType CanonType = SemaRef.Context.getTemplateSpecializationType( TemplateName(ClassTemplate), CanonicalConverted); - // 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); + // 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); if (PrevDecl) { // We've already seen a partial specialization with the same template @@ -4315,28 +4307,14 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // // Outer<int, int> outer; // error: the partial specializations of Inner // // have the same signature. - SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) - << WrittenTy->getType(); + SemaRef.Diag(InstPartialSpec->getLocation(), + diag::err_partial_spec_redeclared) + << InstPartialSpec; 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); @@ -4405,46 +4383,6 @@ 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, @@ -4464,16 +4402,39 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplatePartialSpecializationDecl::Create( SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), - DI, PartialSpec->getStorageClass(), CanonicalConverted, - InstTemplateArgs); + DI, PartialSpec->getStorageClass(), CanonicalConverted); + + InstPartialSpec->setTemplateArgsAsWritten(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); @@ -5735,7 +5696,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, TemplateArgumentListInfo TemplateArgInfo; if (const ASTTemplateArgumentListInfo *ArgInfo = - VarSpec->getTemplateArgsInfo()) { + VarSpec->getTemplateArgsAsWritten()) { 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 089ede4..0c647086 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2548,16 +2548,17 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = readSourceLocation(); + // extern/template keyword locations for explicit instantiations + if (Record.readBool()) { + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; + ExplicitInfo->ExternKeywordLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; } + if (Record.readBool()) + D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo()); + return Redecl; } @@ -2567,7 +2568,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( // need them for profiling TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); @@ -2617,16 +2617,17 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = readSourceLocation(); + // extern/template keyword locations for explicit instantiations + if (Record.readBool()) { + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; + ExplicitInfo->ExternKeywordLoc = 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); @@ -2666,7 +2667,6 @@ 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 6201d28..c2f1d1b 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1765,20 +1765,28 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl()); } - // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { - Record.AddSourceLocation(D->getExternLoc()); + bool ExplicitInstantiation = + D->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration || + D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; + Record.push_back(ExplicitInstantiation); + if (ExplicitInstantiation) { + Record.AddSourceLocation(D->getExternKeywordLoc()); 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); @@ -1812,13 +1820,22 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); } - // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { - Record.AddSourceLocation(D->getExternLoc()); + bool ExplicitInstantiation = + D->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration || + D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; + Record.push_back(ExplicitInstantiation); + if (ExplicitInstantiation) { + Record.AddSourceLocation(D->getExternKeywordLoc()); 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()); @@ -1839,7 +1856,6 @@ 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 cd02619..3e50d67f 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -735,7 +735,8 @@ public: auto *Declaration = cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C)); foldExplicitTemplateInstantiation( - Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()), + Builder.getTemplateRange(C), + Builder.findToken(C->getExternKeywordLoc()), 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 142bc9e..37f6d8a 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 --check-prefix=DIRECT +// RUN: | FileCheck -strict-whitespace %s // // 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 --check-prefix=SERIALIZED +// RUN: | FileCheck --strict-whitespace %s template <typename Ty> // CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <{{.*}}:1, line:[[@LINE+2]]:10> col:6 a @@ -189,15 +189,13 @@ T unTempl = 1; template<> int 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: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:16> 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' cinit +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 unTempl 'float' // CHECK-NEXT: |-TemplateArgument type 'float' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float' // CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}} <col:24> 'float' <IntegralToFloating> @@ -222,7 +220,7 @@ int binTempl<int, U>; template<class U> float binTempl<float, U> = 1; -// CHECK: VarTemplatePartialSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 binTempl 'float' cinit +// CHECK: VarTemplatePartialSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:28> col:7 binTempl 'float' // 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' @@ -233,9 +231,7 @@ float binTempl<float, U> = 1; template<> int binTempl<int, 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: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:22> col:5 binTempl 'int' // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int' // CHECK-NEXT: `-TemplateArgument type 'int' @@ -243,7 +239,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' cinit +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:32> col:7 binTempl 'float' // 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 8f9fbc4..043e616 100644 --- a/clang/test/Index/Core/index-source.cpp +++ b/clang/test/Index/Core/index-source.cpp @@ -285,20 +285,17 @@ 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: [[@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 +// CHECK-NEXT: [[@LINE-3]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 template<> class PartialSpecilizationClass<Cls, Cls> : Cls { }; @@ -306,9 +303,10 @@ 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]]: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 +// 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_ template<typename T, int x> void functionSp() { } @@ -332,10 +330,14 @@ 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 | 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 +// 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 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 0e613e4..1494684 100644 --- a/clang/test/Index/index-refs.cpp +++ b/clang/test/Index/index-refs.cpp @@ -108,7 +108,6 @@ 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 b845a38..60241af 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -743,14 +743,10 @@ bool CursorVisitor::VisitClassTemplateSpecializationDecl( } // Visit the template arguments used in the specialization. - 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; - } + if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { + for (const TemplateArgumentLoc &Arg : ArgsWritten->arguments()) + if (VisitTemplateArgumentLoc(Arg)) + return true; } return ShouldVisitBody && VisitCXXRecordDecl(D); @@ -5659,16 +5655,19 @@ 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; - printTemplateArgumentList( - OS, ClassSpec->getTemplateArgs().asArray(), Policy, - ClassSpec->getSpecializedTemplate()->getTemplateParameters()); + // 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()); + } return cxstring::createDup(OS.str()); } diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index b76627c..65df513 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2213,18 +2213,6 @@ 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 f198dc7..af99c73 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -430,12 +430,6 @@ 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 };", @@ -6384,8 +6378,7 @@ TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) { "template<typename T> class A {}; template<> class A<int> {};", classTemplateSpecializationDecl( hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc( - hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))))); + hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))); } TEST(HasAnyTemplateArgumentLoc, @@ -6394,8 +6387,7 @@ TEST(HasAnyTemplateArgumentLoc, "template<typename T> class A {}; template<> class A<double> {};", classTemplateSpecializationDecl( hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( - hasTypeLoc(loc(asString("double"))))))))); + hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double"))))))); } TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { @@ -6405,24 +6397,20 @@ TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { )"; EXPECT_TRUE( matches(code, classTemplateSpecializationDecl( - hasName("A"), hasTypeLoc(templateSpecializationTypeLoc( - hasAnyTemplateArgumentLoc(hasTypeLoc( - loc(asString("double"))))))))); + hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc( + loc(asString("double"))))))); + EXPECT_TRUE(matches( - code, - classTemplateSpecializationDecl( - hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc( - hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))))); + code, classTemplateSpecializationDecl( + hasName("A"), + hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int"))))))); } TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) { - EXPECT_TRUE(notMatches( - "template<typename T> class A {}; A<int> a;", - classTemplateSpecializationDecl( - hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( - hasTypeLoc(loc(asString("double"))))))))); + EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;", + classTemplateSpecializationDecl( + hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc( + loc(asString("double"))))))); } TEST(HasAnyTemplateArgumentLoc, @@ -6431,8 +6419,7 @@ TEST(HasAnyTemplateArgumentLoc, "template<typename T> class A {}; template<> class A<int> {};", classTemplateSpecializationDecl( hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( - hasTypeLoc(loc(asString("double"))))))))); + hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double"))))))); } TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) { @@ -6453,13 +6440,21 @@ 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"), - hasTypeLoc(templateSpecializationTypeLoc( - hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int"))))))))); + hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int"))))))); } TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) { @@ -6467,8 +6462,7 @@ TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) { "template<typename T> class A {}; template<> class A<double> {};", classTemplateSpecializationDecl( hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( - 0, hasTypeLoc(loc(asString("double"))))))))); + hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double"))))))); } TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { @@ -6478,23 +6472,12 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) { )"; EXPECT_TRUE(matches( code, classTemplateSpecializationDecl( - hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( - 0, hasTypeLoc(loc(asString("double"))))))))); + hasName("A"), hasTemplateArgumentLoc( + 0, hasTypeLoc(loc(asString("double"))))))); EXPECT_TRUE(matches( code, classTemplateSpecializationDecl( hasName("A"), - 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"))))))))); + hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int"))))))); } TEST(HasTemplateArgumentLoc, @@ -6503,8 +6486,7 @@ TEST(HasTemplateArgumentLoc, "template<typename T> class A {}; template<> class A<int> {};", classTemplateSpecializationDecl( hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( - 0, hasTypeLoc(loc(asString("double"))))))))); + hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double"))))))); } TEST(HasTemplateArgumentLoc, @@ -6515,14 +6497,12 @@ TEST(HasTemplateArgumentLoc, )"; EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( - hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( - 1, hasTypeLoc(loc(asString("double"))))))))); + hasName("A"), hasTemplateArgumentLoc( + 1, hasTypeLoc(loc(asString("double"))))))); EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( - 0, hasTypeLoc(loc(asString("int"))))))))); + hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int"))))))); } TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) { @@ -6532,14 +6512,12 @@ TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) { )"; EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( - hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( - -1, hasTypeLoc(loc(asString("double"))))))))); + hasName("A"), hasTemplateArgumentLoc( + -1, hasTypeLoc(loc(asString("double"))))))); EXPECT_TRUE(notMatches( code, classTemplateSpecializationDecl( - hasName("A"), - hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( - 100, hasTypeLoc(loc(asString("int"))))))))); + hasName("A"), hasTemplateArgumentLoc( + 100, hasTypeLoc(loc(asString("int"))))))); } TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) { |