From 1cfec5f606b4c8c132ce790cf0661a0d5b3f6b70 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Wed, 16 Aug 2017 23:12:21 +0000 Subject: [PATCH] [index] Add indexing for unresolved-using declarations In dependent contexts we end up referencing these, so make sure they have USRs, and have their declarations indexed. For the most part they behave like typedefs, but we also need to worry about having multiple using declarations with the same "name". rdar://problem/33883650 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311053 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Index/IndexSymbol.h | 3 + lib/Index/IndexDecl.cpp | 18 ++++++ lib/Index/IndexSymbol.cpp | 15 +++++ lib/Index/USRGeneration.cpp | 48 +++++++++++----- test/Index/Core/index-dependent-source.cpp | 66 ++++++++++++++++++++++ test/Index/index-templates.cpp | 2 +- tools/libclang/CXIndexDataConsumer.cpp | 1 + 7 files changed, 137 insertions(+), 16 deletions(-) diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index abb132f9e4..ae591364f2 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -53,6 +53,7 @@ enum class SymbolKind : uint8_t { ConversionFunction, Parameter, + Using, }; enum class SymbolLanguage { @@ -69,6 +70,8 @@ enum class SymbolSubKind { CXXMoveConstructor, AccessorGetter, AccessorSetter, + UsingTypename, + UsingValue, }; /// Set of properties that provide additional info about a symbol. diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index fe6beef670..ee28ef737d 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -611,6 +611,24 @@ public: SymbolRoleSet()); } + bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { + TRY_DECL(D, IndexCtx.handleDecl(D)); + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + const NamedDecl *Parent = dyn_cast(DC); + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, + D->getLexicalDeclContext()); + return true; + } + + bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { + TRY_DECL(D, IndexCtx.handleDecl(D)); + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + const NamedDecl *Parent = dyn_cast(DC); + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, + D->getLexicalDeclContext()); + return true; + } + bool VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl *D) { // FIXME: Notify subsequent callbacks if info comes from implicit diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp index 95b3ac1966..03db0cd53f 100644 --- a/lib/Index/IndexSymbol.cpp +++ b/lib/Index/IndexSymbol.cpp @@ -300,6 +300,18 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { Info.Kind = SymbolKind::TypeAlias; Info.Lang = SymbolLanguage::CXX; break; + case Decl::UnresolvedUsingTypename: + Info.Kind = SymbolKind::Using; + Info.SubKind = SymbolSubKind::UsingTypename; + Info.Lang = SymbolLanguage::CXX; + Info.Properties |= (unsigned)SymbolProperty::Generic; + break; + case Decl::UnresolvedUsingValue: + Info.Kind = SymbolKind::Using; + Info.SubKind = SymbolSubKind::UsingValue; + Info.Lang = SymbolLanguage::CXX; + Info.Properties |= (unsigned)SymbolProperty::Generic; + break; case Decl::Binding: Info.Kind = SymbolKind::Variable; Info.Lang = SymbolLanguage::CXX; @@ -448,6 +460,7 @@ StringRef index::getSymbolKindString(SymbolKind K) { case SymbolKind::Destructor: return "destructor"; case SymbolKind::ConversionFunction: return "coversion-func"; case SymbolKind::Parameter: return "param"; + case SymbolKind::Using: return "using"; } llvm_unreachable("invalid symbol kind"); } @@ -459,6 +472,8 @@ StringRef index::getSymbolSubKindString(SymbolSubKind K) { case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor"; case SymbolSubKind::AccessorGetter: return "acc-get"; case SymbolSubKind::AccessorSetter: return "acc-set"; + case SymbolSubKind::UsingTypename: return "using-typename"; + case SymbolSubKind::UsingValue: return "using-value"; } llvm_unreachable("invalid symbol subkind"); } diff --git a/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp index 21054b099a..c4fe737e51 100644 --- a/lib/Index/USRGeneration.cpp +++ b/lib/Index/USRGeneration.cpp @@ -99,6 +99,8 @@ public: void VisitVarDecl(const VarDecl *D); void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); + void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); + void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { IgnoreResults = true; @@ -112,14 +114,6 @@ public: IgnoreResults = true; } - void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { - IgnoreResults = true; - } - - void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { - IgnoreResults = true; - } - bool ShouldGenerateLocation(const NamedDecl *D); bool isLocal(const NamedDecl *D) { @@ -609,6 +603,16 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { return IgnoreResults; } +static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) { + // FIXME: Encode the qualifier, don't just print it. + PrintingPolicy PO(Ctx.getLangOpts()); + PO.SuppressTagKeyword = true; + PO.SuppressUnwrittenScope = true; + PO.ConstantArraySizeAsWritten = false; + PO.AnonymousTagLocations = false; + NNS->print(Out, PO); +} + void USRGenerator::VisitType(QualType T) { // This method mangles in USR information for types. It can possibly // just reuse the naming-mangling logic used by codegen, although the @@ -797,13 +801,7 @@ void USRGenerator::VisitType(QualType T) { } if (const DependentNameType *DNT = T->getAs()) { Out << '^'; - // FIXME: Encode the qualifier, don't just print it. - PrintingPolicy PO(Ctx.getLangOpts()); - PO.SuppressTagKeyword = true; - PO.SuppressUnwrittenScope = true; - PO.ConstantArraySizeAsWritten = false; - PO.AnonymousTagLocations = false; - DNT->getQualifier()->print(Out, PO); + printQualifier(Out, Ctx, DNT->getQualifier()); Out << ':' << DNT->getIdentifier()->getName(); return; } @@ -912,6 +910,26 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { } } +void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { + if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) + return; + VisitDeclContext(D->getDeclContext()); + Out << "@UUV@"; + printQualifier(Out, D->getASTContext(), D->getQualifier()); + EmitDeclName(D); +} + +void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { + if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) + return; + VisitDeclContext(D->getDeclContext()); + Out << "@UUT@"; + printQualifier(Out, D->getASTContext(), D->getQualifier()); + Out << D->getName(); // Simple name. +} + + + //===----------------------------------------------------------------------===// // USR generation functions. //===----------------------------------------------------------------------===// diff --git a/test/Index/Core/index-dependent-source.cpp b/test/Index/Core/index-dependent-source.cpp index 59c6286cd3..2e111339af 100644 --- a/test/Index/Core/index-dependent-source.cpp +++ b/test/Index/Core/index-dependent-source.cpp @@ -158,3 +158,69 @@ void infiniteTraitRecursion(Trait &t) { // Shouldn't crash! t.lookup; } + +template +struct UsingA { +// CHECK: [[@LINE+1]]:15 | type-alias/C | Type | c:index-dependent-source.cpp@ST>1#T@UsingA@T@Type | | Def,RelChild | rel: 1 + typedef int Type; +// CHECK: [[@LINE+1]]:15 | static-method/C++ | func | c:@ST>1#T@UsingA@F@func#S | | Decl,RelChild | rel: 1 + static void func(); +// CHECK: [[@LINE+1]]:8 | instance-method/C++ | operator() | c:@ST>1#T@UsingA@F@operator()#I# | | Decl,RelChild | rel: 1 + void operator()(int); +// CHECK: [[@LINE+1]]:8 | instance-method/C++ | operator+ | c:@ST>1#T@UsingA@F@operator+#&1>@ST>1#T@UsingA1t0.0# | | Decl,RelChild | rel: 1 + void operator+(const UsingA &); +}; + +template +struct OtherUsing {}; + +template +struct UsingB : public UsingA { +// CHECK: [[@LINE+2]]:40 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | | Def,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:20 | struct(Gen)/C++ | OtherUsing | c:@ST>1#T@OtherUsing | | Ref,RelCont | rel: 1 + typedef typename OtherUsing::Type TypeB; +// CHECK: [[@LINE+2]]:29 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA::Type | | Decl,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:18 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 + using typename UsingA::Type; +// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::func | | Decl,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 + using UsingA::func; + +// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator() | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::operator() | | Decl,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 + using UsingA::operator(); +// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator+ | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::operator+ | | Decl,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 + using UsingA::operator+; +}; + +template +struct UsingC : public UsingB { + static void test() { +// CHECK: [[@LINE+2]]:25 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | | Ref,RelCont | rel: 1 + typename UsingB::TypeB value1; +// CHECK: [[@LINE+2]]:25 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA::Type | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | | Ref,RelCont | rel: 1 + typename UsingB::Type value2; +// CHECK: [[@LINE+2]]:16 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::func | | Ref,Call,RelCall,RelCont | rel: 1 +// CHECK: [[@LINE+1]]:5 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | | Ref,RelCont | rel: 1 + UsingB::func(); + } +}; + +template +struct UsingD { +// CHECK: [[@LINE+1]]:8 | instance-method/C++ | foo | c:@ST>1#T@UsingD@F@foo#t0.0# | | Decl,RelChild | rel: 1 + void foo(T); +}; + +template +struct UsingE : public UsingD, public UsingD { +// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD::foo | | Decl,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | | Ref,RelCont | rel: 1 + using UsingD::foo; +// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD::foo | | Decl,RelChild | rel: 1 +// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | | Ref,RelCont | rel: 1 + using UsingD::foo; +}; diff --git a/test/Index/index-templates.cpp b/test/Index/index-templates.cpp index 966cc4f5ea..424a638ffb 100644 --- a/test/Index/index-templates.cpp +++ b/test/Index/index-templates.cpp @@ -219,6 +219,6 @@ using alias = T; // CHECK-USRS: index-templates.cpp c:@ST>2#T#T@Y Extent=[27:1 - 31:2] // CHECK-USRS: index-templates.cpp c:index-templates.cpp@443 Extent=[27:10 - 27:20] // CHECK-USRS: index-templates.cpp c:index-templates.cpp@455 Extent=[27:22 - 27:32] -// CHECK-USRS-NOT: type +// CHECK-USRS: index-templates.cpp c:index-templates.cpp@ST>2#T#T@Y@UUT@T::type Extent=[29:3 - 29:25] // CHECK-USRS: index-templates.cpp c:@S@Z3 Extent=[33:1 - 33:14] // CHECK-USRS: index-templates.cpp c:@F@f#$@S@map>#$@S@Z4#$@S@Pair>#I#S1_#$@S@compare>#$@S@Pair>#S1_#S2_#$@S@allocator>#S4_# diff --git a/tools/libclang/CXIndexDataConsumer.cpp b/tools/libclang/CXIndexDataConsumer.cpp index a2ef68be49..ffe5c486dd 100644 --- a/tools/libclang/CXIndexDataConsumer.cpp +++ b/tools/libclang/CXIndexDataConsumer.cpp @@ -1258,6 +1258,7 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage case SymbolKind::Module: case SymbolKind::Macro: case SymbolKind::ClassProperty: + case SymbolKind::Using: return CXIdxEntity_Unexposed; case SymbolKind::Enum: return CXIdxEntity_Enum; -- 2.40.0