================
@@ -2196,23 +2208,23 @@ bool 
RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
        the source code anywhere.  (Note the instatiated *type* --              
\
        set<int> -- is written, and will still get a callback of                
\
        TemplateSpecializationType).  For explicit instantiations               
\
-       ("template set<int>;"), we do need a callback, since this               
\
-       is the only callback that's made for this instantiation.                
\
-       We use getTemplateArgsAsWritten() to distinguish. */                    
\
+       ("template set<int>;"), the ExplicitInstantiationDecl node              
\
+       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); 
\
-      /* The args that remains unspecialized. */                               
\
-      TRY_TO(TraverseTemplateArgumentLocsHelper(                               
\
-          ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs));      
\
+      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 {                                                                   
\
-      TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));            
\
-                                                                               
\
----------------
16bit-ykiko wrote:

The canonical decl for an explicit instantiation here is the 
`ClassTemplateSpecializationDecl` / `VarTemplateSpecializationDecl`. Before 
EID, these nodes partially assumed the responsibility of recording the source 
location information for explicit instantiations (though sometimes 
inaccurately, like with the NNS), which is why RAV traversed those locations 
here.

Now that we have EID, the location information is both more complete and 
accurate, so the traversal should be handled uniformly when visiting the EID 
instead. If we also traverse the specialization node, downstream tools like 
clang-tidy will receive duplicate callbacks (for example, `avoid-c-arrays` 
would report two warnings for the same type, which was fixed in a previous 
commit).

Note that we didn't just delete the traversal entirely; the 
`TSK_ExplicitSpecialization` branch is kept because explicit specializations 
(`template<>`) do not have a corresponding EID, meaning they still need to 
traverse their own template arguments.

https://github.com/llvm/llvm-project/pull/191658
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to