[clang-tools-extra] c119a17 - [AST] Fix clang RecursiveASTVisitor for definition of XXXTemplateSpecializationDecl

Nathan Ridge via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 5 23:35:40 PDT 2022


Author: Qingyuan Zheng
Date: 2022-06-06T02:35:34-04:00
New Revision: c119a17e7fd6fb528d8c1e1bbb0ad1fac93f896a

URL: https://github.com/llvm/llvm-project/commit/c119a17e7fd6fb528d8c1e1bbb0ad1fac93f896a
DIFF: https://github.com/llvm/llvm-project/commit/c119a17e7fd6fb528d8c1e1bbb0ad1fac93f896a.diff

LOG: [AST] Fix clang RecursiveASTVisitor for definition of XXXTemplateSpecializationDecl

Fixes https://github.com/clangd/clangd/issues/1132
where clangd's semantic highlighting is missing for symbols of a template
specialization definition. It turns out the visitor didn't traverse the
base classes of Class/Var##TemplateSpecializationDecl, i.e.
CXXRecordDecl/VarDecl. This patch adds them back as what is done in
DEF_TRAVERSE_TMPL_PART_SPEC_DECL.

Reviewed By: rsmith

Differential Revision: https://reviews.llvm.org/D126757

Added: 
    

Modified: 
    clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
    clang/include/clang/AST/RecursiveASTVisitor.h

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
index 2f4e8e57a81f1..f60c62500c7de 100644
--- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -807,6 +807,19 @@ sizeof...($TemplateParameter[[Elements]]);
             $Function_deprecated[[Foo]]($Parameter[[x]]); 
             $Function_deprecated[[Foo]]($Parameter[[x]]); 
         }
+      )cpp",
+      // Explicit template specialization
+      R"cpp(
+        struct $Class_decl[[Base]]{};
+        template <typename $TemplateParameter_decl[[T]]>
+        struct $Class_decl[[S]] : public $Class[[Base]] {};
+        template <> 
+        struct $Class_decl[[S]]<void> : public $Class[[Base]] {};
+
+        template <typename $TemplateParameter_decl[[T]]>
+        $TemplateParameter[[T]] $Variable_decl[[x]] = {};
+        template <>
+        int $Variable_decl[[x]]<int> = (int)sizeof($Class[[Base]]);
       )cpp"};
   for (const auto &TestCase : TestCases)
     // Mask off scope modifiers to keep the tests manageable.

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index ae6442d75dd4b..c6d74d94194bd 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2021,7 +2021,7 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); })
 
 DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
 
-#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND)                              \
+#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND)                    \
   DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, {                \
     /* For implicit instantiations ("set<int> x;"), we don't want to           \
        recurse at all, since the instatiated template isn't written in         \
@@ -2034,18 +2034,23 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
     if (TypeSourceInfo *TSI = D->getTypeAsWritten())                           \
       TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));                              \
                                                                                \
-    TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));              \
-    if (!getDerived().shouldVisitTemplateInstantiations() &&                   \
-        D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)      \
+    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()));            \
+                                                                               \
       /* 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;                                                             \
+    }                                                                          \
   })
 
-DEF_TRAVERSE_TMPL_SPEC_DECL(Class)
-DEF_TRAVERSE_TMPL_SPEC_DECL(Var)
+DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord)
+DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var)
 
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(


        


More information about the cfe-commits mailing list