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

Reply via email to