https://github.com/hvdijk updated https://github.com/llvm/llvm-project/pull/199131
>From e06fcbe5d6945a68b00457212352bc4832b2e339 Mon Sep 17 00:00:00 2001 From: Harald van Dijk <[email protected]> Date: Thu, 21 May 2026 23:49:43 +0100 Subject: [PATCH 1/2] [Clang][RAV] Simplify TraverseTemplateArgumentLocsHelper We were checking the result of getTemplateArgsAsWritten() to skip over implicit instantiations, with an assert to ensure that it has the desired effect, before checking getTemplateSpecializationKind() == TSK_ExplicitSpecialization which would skip over implicit instantiations anyway. As the included tests show, the invariant that we were relying on did not hold, but we no longer have any need to rely on that, we can now just check the result of getTemplateSpecializationKind() directly. Fixes: #198903 Fixes: #169302 --- clang/include/clang/AST/RecursiveASTVisitor.h | 21 ++++++---------- clang/test/AST/pr198903.cpp | 25 +++++++++++++++++++ clang/test/Analysis/pr169302.cpp | 25 +++++++++++++++++++ 3 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 clang/test/AST/pr198903.cpp create mode 100644 clang/test/Analysis/pr169302.cpp diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index febdf715698d9..2efdde5450f3c 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2222,25 +2222,20 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( handles traversal of template args and qualifier. \ For explicit specializations ("template<> set<int> {...};"), \ we traverse template args here since there is no EID. */ \ - if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \ - assert(D->getTemplateSpecializationKind() != TSK_ImplicitInstantiation); \ - if (D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ - TRY_TO(TraverseTemplateArgumentLocsHelper( \ - ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \ - } \ - } \ - \ - if (getDerived().shouldVisitTemplateInstantiations() || \ - D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ - /* Traverse base definition for explicit specializations */ \ - TRY_TO(Traverse##DECLKIND##Helper(D)); \ - } else { \ + if (D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ + const auto *ArgsWritten = D->getTemplateArgsAsWritten(); \ + TRY_TO(TraverseTemplateArgumentLocsHelper( \ + ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \ + } else if (!getDerived().shouldVisitTemplateInstantiations()) { \ /* Returning from here skips traversing the \ declaration context of the *TemplateSpecializationDecl \ (embedded in the DEF_TRAVERSE_DECL() macro) \ which contains the instantiated members of the template. */ \ return true; \ } \ + \ + /* Traverse base definition for explicit specializations */ \ + TRY_TO(Traverse##DECLKIND##Helper(D)); \ }) DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord) diff --git a/clang/test/AST/pr198903.cpp b/clang/test/AST/pr198903.cpp new file mode 100644 index 0000000000000..1f0f68f92b7e4 --- /dev/null +++ b/clang/test/AST/pr198903.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -ast-list %s | FileCheck -strict-whitespace %s + +template <typename> +struct Tpl { + template <typename> + static int var; +}; +// CHECK: Tpl +// CHECK-NEXT: Tpl::(anonymous) +// CHECK-NEXT: Tpl +// CHECK-NEXT: Tpl::var +// CHECK-NEXT: Tpl::(anonymous) +// CHECK-NEXT: Tpl::var + +template <typename T> +template <typename> +int Tpl<T>::var; +// CHECK-NEXT: Tpl::var +// CHECK-NEXT: Tpl::(anonymous) +// CHECK-NEXT: Tpl::var +// CHECK-NEXT: T + +int i = Tpl<int>::var<int>; +// CHECK-NEXT: i +// CHECK-NEXT: Tpl<int>::var diff --git a/clang/test/Analysis/pr169302.cpp b/clang/test/Analysis/pr169302.cpp new file mode 100644 index 0000000000000..9aa594627708a --- /dev/null +++ b/clang/test/Analysis/pr169302.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -verify %s + +// expected-no-diagnostics + +template <typename> struct S; + +class Sp { +public: + template <bool> void M() {} + template <unsigned> struct I { + static void IM(); + }; +}; + +template <> struct S<Sp> { + using F = void (Sp::*)(); + template <bool P> static constexpr F SpM = &Sp::template M<P>; +}; + +template <bool> constexpr S<Sp>::F S<Sp>::SpM; + +template <unsigned X> void Sp::I<X>::IM() { + using Spec = S<Sp>; + typename Spec::F E = Spec::template SpM<true>; +} >From ad7876bf1e47842d2c916d40ad73b430c6c07c94 Mon Sep 17 00:00:00 2001 From: Harald van Dijk <[email protected]> Date: Fri, 22 May 2026 00:46:27 +0100 Subject: [PATCH 2/2] Use -std=c++14 --- clang/test/Analysis/pr169302.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Analysis/pr169302.cpp b/clang/test/Analysis/pr169302.cpp index 9aa594627708a..9ff73bc8535e3 100644 --- a/clang/test/Analysis/pr169302.cpp +++ b/clang/test/Analysis/pr169302.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -verify %s +// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core -verify %s // expected-no-diagnostics _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
