forked from OSchip/llvm-project
[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 llvm-svn: 311053
This commit is contained in:
parent
4abc3f6036
commit
fd6e39c40b
|
@ -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.
|
||||
|
|
|
@ -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<NamedDecl>(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<NamedDecl>(DC);
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
|
||||
D->getLexicalDeclContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitClassTemplateSpecializationDecl(const
|
||||
ClassTemplateSpecializationDecl *D) {
|
||||
// FIXME: Notify subsequent callbacks if info comes from implicit
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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<DependentNameType>()) {
|
||||
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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -158,3 +158,69 @@ void infiniteTraitRecursion(Trait<T> &t) {
|
|||
// Shouldn't crash!
|
||||
t.lookup;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct UsingA {
|
||||
// CHECK: [[@LINE+1]]:15 | type-alias/C | Type | c:index-dependent-source.cpp@ST>1#T@UsingA@T@Type | <no-cgname> | Def,RelChild | rel: 1
|
||||
typedef int Type;
|
||||
// CHECK: [[@LINE+1]]:15 | static-method/C++ | func | c:@ST>1#T@UsingA@F@func#S | <no-cgname> | Decl,RelChild | rel: 1
|
||||
static void func();
|
||||
// CHECK: [[@LINE+1]]:8 | instance-method/C++ | operator() | c:@ST>1#T@UsingA@F@operator()#I# | <no-cgname> | 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# | <no-cgname> | Decl,RelChild | rel: 1
|
||||
void operator+(const UsingA &);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OtherUsing {};
|
||||
|
||||
template <typename T>
|
||||
struct UsingB : public UsingA<T> {
|
||||
// CHECK: [[@LINE+2]]:40 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | <no-cgname> | Def,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:20 | struct(Gen)/C++ | OtherUsing | c:@ST>1#T@OtherUsing | <no-cgname> | Ref,RelCont | rel: 1
|
||||
typedef typename OtherUsing<T>::Type TypeB;
|
||||
// CHECK: [[@LINE+2]]:29 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA<T>::Type | <no-cgname> | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:18 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
|
||||
using typename UsingA<T>::Type;
|
||||
// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::func | <no-cgname> | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
|
||||
using UsingA<T>::func;
|
||||
|
||||
// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator() | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::operator() | <no-cgname> | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
|
||||
using UsingA<T>::operator();
|
||||
// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator+ | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::operator+ | <no-cgname> | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | <no-cgname> | Ref,RelCont | rel: 1
|
||||
using UsingA<T>::operator+;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UsingC : public UsingB<T> {
|
||||
static void test() {
|
||||
// CHECK: [[@LINE+2]]:25 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | <no-cgname> | Ref,RelCont | rel: 1
|
||||
typename UsingB<T>::TypeB value1;
|
||||
// CHECK: [[@LINE+2]]:25 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA<T>::Type | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | <no-cgname> | Ref,RelCont | rel: 1
|
||||
typename UsingB<T>::Type value2;
|
||||
// CHECK: [[@LINE+2]]:16 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA<T>::func | <no-cgname> | Ref,Call,RelCall,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+1]]:5 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | <no-cgname> | Ref,RelCont | rel: 1
|
||||
UsingB<T>::func();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UsingD {
|
||||
// CHECK: [[@LINE+1]]:8 | instance-method/C++ | foo | c:@ST>1#T@UsingD@F@foo#t0.0# | <no-cgname> | Decl,RelChild | rel: 1
|
||||
void foo(T);
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct UsingE : public UsingD<T>, public UsingD<U> {
|
||||
// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD<T>::foo | <no-cgname> | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | <no-cgname> | Ref,RelCont | rel: 1
|
||||
using UsingD<T>::foo;
|
||||
// CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD<U>::foo | <no-cgname> | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | <no-cgname> | Ref,RelCont | rel: 1
|
||||
using UsingD<U>::foo;
|
||||
};
|
||||
|
|
|
@ -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_#
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue