[clang] bb9e92b - [clang][Index] Fix the incomplete instantiations in libindex.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 20 05:53:44 PST 2020


Author: Haojian Wu
Date: 2020-02-20T14:42:30+01:00
New Revision: bb9e92bad55f65f2de58bf29548bdfd3dea2d7ab

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

LOG: [clang][Index] Fix the incomplete instantiations in libindex.

Summary:
libindex will canonicalize references to template instantiations:
- 1) reference to an explicit template specialization, report the specializatiion
- 2) otherwise, report the primary template

but 2) is not true for incomplete instantiations, this patch fixes this.

Fixes https://github.com/clangd/clangd/issues/287

Reviewers: kadircet

Subscribers: ilya-biryukov, jkorous, arphaman, usaxena95, cfe-commits

Tags: #clang

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

Added: 
    

Modified: 
    clang-tools-extra/clangd/unittests/XRefsTests.cpp
    clang/lib/Index/IndexingContext.cpp
    clang/test/Index/Core/index-instantiated-source.cpp
    clang/test/Index/Core/index-source.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index b75c218d143f..31c965087547 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -948,6 +948,12 @@ TEST(FindReferences, WithinAST) {
         int [[v^ar]] = 0;
         void foo(int s = [[var]]);
       )cpp",
+
+      R"cpp(
+       template <typename T>
+       class [[Fo^o]] {};
+       void func([[Foo]]<int>);
+      )cpp",
   };
   for (const char *Test : Tests) {
     Annotations T(Test);

diff  --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp
index a7c37e8528d1..784a6008575b 100644
--- a/clang/lib/Index/IndexingContext.cpp
+++ b/clang/lib/Index/IndexingContext.cpp
@@ -169,6 +169,10 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
   }
   switch (TKind) {
     case TSK_Undeclared:
+      // Instantiation maybe not happen yet when we see a SpecializationDecl,
+      // e.g. when the type doesn't need to be complete, we still treat it as an
+      // instantiation as we'd like to keep the canonicalized result consistent.
+      return isa<ClassTemplateSpecializationDecl>(D);
     case TSK_ExplicitSpecialization:
       return false;
     case TSK_ImplicitInstantiation:
@@ -206,7 +210,12 @@ getDeclContextForTemplateInstationPattern(const Decl *D) {
 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
   if (const ClassTemplateSpecializationDecl *
       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
-    return SD->getTemplateInstantiationPattern();
+    const auto *Template = SD->getTemplateInstantiationPattern();
+    if (Template)
+      return Template;
+    // Fallback to primary template if no instantiation is available yet (e.g.
+    // the type doesn't need to be complete).
+    return SD->getSpecializedTemplate()->getTemplatedDecl();
   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     return FD->getTemplateInstantiationPattern();
   } else if (auto *VD = dyn_cast<VarDecl>(D)) {

diff  --git a/clang/test/Index/Core/index-instantiated-source.cpp b/clang/test/Index/Core/index-instantiated-source.cpp
index 7a810fbdf3a8..2a67a3a3c793 100644
--- a/clang/test/Index/Core/index-instantiated-source.cpp
+++ b/clang/test/Index/Core/index-instantiated-source.cpp
@@ -86,3 +86,37 @@ void canonicalizeInstaniationReferences(TemplateClass<int, float> &object) {
   (void)TT::NestedType::Enum::EnumCase;
 // CHECK: [[@LINE-1]]:31 | enumerator/C | EnumCase | c:@ST>2#T#T at TemplateClass@S at NestedType@E at Enum@EnumCase |
 }
+
+namespace index_specialization {
+template <typename T>
+class Foo {};
+
+// if there are no explicit template specializations provided, report the
+// primary templates.
+Foo<int> *t1; // incomplete instantiation.
+// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | Foo | c:@N at index_specialization@ST>1#T at Foo | <no-cgname> | Ref,RelCont | rel: 1
+
+Foo<double> t2;
+// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | Foo | c:@N at index_specialization@ST>1#T at Foo | <no-cgname> | Ref,RelCont | rel: 1
+
+// explicit instantiations.
+template class Foo<float>;
+Foo<float> t3;
+// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | Foo | c:@N at index_specialization@ST>1#T at Foo | <no-cgname> | Ref,RelCont | rel: 1
+
+
+template <typename T>
+class Bar {};
+
+// explicit template specialization definition!
+template <>class Bar<int> {};
+// report the explicit template specialization if it exists.
+Bar<int> *b1;
+// CHECK: [[@LINE-1]]:1 | class(Gen,TS)/C++ | Bar | c:@N at index_specialization@S at Bar>#I | <no-cgname> | Ref,RelCont | rel: 1
+
+// explicit template declaration, not a definition!
+template <> class Bar <float>;
+Bar<float> *b2;
+// CHECK: [[@LINE-1]]:1 | class(Gen,TS)/C++ | Bar | c:@N at index_specialization@S at Bar>#f | <no-cgname> | Ref,RelCont | rel: 1
+
+} // namespace index_specialization

diff  --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp
index f159b1c88430..371265b115b2 100644
--- a/clang/test/Index/Core/index-source.cpp
+++ b/clang/test/Index/Core/index-source.cpp
@@ -321,7 +321,7 @@ template<>
 void functionSp<SpecializationDecl<Cls>, Record::C>() {
 // CHECK: [[@LINE-1]]:6 | function(Gen,TS)/C++ | functionSp | c:@F at functionSp<#$@S at SpecializationDecl>#$@S at Cls#VI2># | __Z10functionSpI18SpecializationDeclI3ClsELi2EEvv | Def,RelSpecialization | rel: 1
 // CHECK:   RelSpecialization | functionSp | c:@FT@>2#T#NIfunctionSp#v#
-// CHECK: [[@LINE-3]]:17 | class(Gen,TS)/C++ | SpecializationDecl | c:@S at SpecializationDecl>#$@S at Cls | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK: [[@LINE-3]]:17 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T at SpecializationDecl | <no-cgname> | Ref,RelCont | rel: 1
 // CHECK: [[@LINE-4]]:36 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref,RelCont | rel: 1
 // CHECK: [[@LINE-5]]:50 | static-property/C++ | C | c:@S at Record@C | __ZN6Record1CE | Ref,RelCont | rel: 1
 // CHECK: [[@LINE-6]]:42 | struct/C++ | Record | c:@S at Record | <no-cgname> | Ref,RelCont | rel: 1
@@ -332,7 +332,7 @@ class ClassWithCorrectSpecialization { };
 
 template<>
 class ClassWithCorrectSpecialization<SpecializationDecl<Cls>, Record::C> { };
-// CHECK: [[@LINE-1]]:38 | class(Gen,TS)/C++ | SpecializationDecl | c:@S at SpecializationDecl>#$@S at Cls | <no-cgname> | Ref | rel: 0
+// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T at SpecializationDecl | <no-cgname> | Ref | rel: 0
 // CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref | rel: 0
 // CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S at Record@C | __ZN6Record1CE | Ref,Read | rel: 0
 // CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S at Record | <no-cgname> | Ref | rel: 0
@@ -505,7 +505,7 @@ struct Guided { T t; };
 // CHECK-NEXT: [[@LINE-2]]:19 | field/C++ | t | c:@ST>1#T at Guided@FI at t | <no-cgname> | Def,RelChild | rel: 1
 // CHECK-NEXT: RelChild | Guided | c:@ST>1#T at Guided
 Guided(double) -> Guided<float>;
-// CHECK: [[@LINE-1]]:19 | struct(Gen,TS)/C++ | Guided | c:@S at Guided>#f | <no-cgname> | Ref | rel: 0
+// CHECK: [[@LINE-1]]:19 | struct(Gen)/C++ | Guided | c:@ST>1#T at Guided | <no-cgname> | Ref | rel: 0
 // CHECK-NEXT: [[@LINE-2]]:1 | struct(Gen)/C++ | Guided | c:@ST>1#T at Guided | <no-cgname> | Ref | rel: 0
 auto guided = Guided{1.0};
 // CHECK: [[@LINE-1]]:6 | variable/C | guided | c:@guided | _guided | Def | rel: 0


        


More information about the cfe-commits mailing list