[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
This commit is contained in:
parent
2f215cf36a
commit
bb9e92bad5
@ -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);
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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@TemplateClass@S@NestedType@E@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@index_specialization@ST>1#T@Foo | <no-cgname> | Ref,RelCont | rel: 1
|
||||
|
||||
Foo<double> t2;
|
||||
// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | Foo | c:@N@index_specialization@ST>1#T@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@index_specialization@ST>1#T@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@index_specialization@S@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@index_specialization@S@Bar>#f | <no-cgname> | Ref,RelCont | rel: 1
|
||||
|
||||
} // namespace index_specialization
|
||||
|
||||
@ -321,7 +321,7 @@ template<>
|
||||
void functionSp<SpecializationDecl<Cls>, Record::C>() {
|
||||
// CHECK: [[@LINE-1]]:6 | function(Gen,TS)/C++ | functionSp | c:@F@functionSp<#$@S@SpecializationDecl>#$@S@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@SpecializationDecl>#$@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-3]]:17 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-4]]:36 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-5]]:50 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-6]]:42 | struct/C++ | Record | c:@S@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@SpecializationDecl>#$@S@Cls | <no-cgname> | Ref | rel: 0
|
||||
// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | <no-cgname> | Ref | rel: 0
|
||||
// CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0
|
||||
// CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S@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@Guided@FI@t | <no-cgname> | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | Guided | c:@ST>1#T@Guided
|
||||
Guided(double) -> Guided<float>;
|
||||
// CHECK: [[@LINE-1]]:19 | struct(Gen,TS)/C++ | Guided | c:@S@Guided>#f | <no-cgname> | Ref | rel: 0
|
||||
// CHECK: [[@LINE-1]]:19 | struct(Gen)/C++ | Guided | c:@ST>1#T@Guided | <no-cgname> | Ref | rel: 0
|
||||
// CHECK-NEXT: [[@LINE-2]]:1 | struct(Gen)/C++ | Guided | c:@ST>1#T@Guided | <no-cgname> | Ref | rel: 0
|
||||
auto guided = Guided{1.0};
|
||||
// CHECK: [[@LINE-1]]:6 | variable/C | guided | c:@guided | _guided | Def | rel: 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user