forked from OSchip/llvm-project
[index] Add 'Parameter' symbol kind and 'Local' symbol property to distinguish function-local symbols
Parameters have a 'child' relation to their function/method. Also add an option '-include-locals' to 'c-index-test core' to enable indexing of function-local symbols. Original patch from Nathan Hawes with some changes by me. https://reviews.llvm.org/D30304 llvm-svn: 296282
This commit is contained in:
parent
42ef2177af
commit
6d1a15b2d4
|
@ -51,6 +51,8 @@ enum class SymbolKind : uint8_t {
|
|||
Constructor,
|
||||
Destructor,
|
||||
ConversionFunction,
|
||||
|
||||
Parameter,
|
||||
};
|
||||
|
||||
enum class SymbolLanguage {
|
||||
|
@ -77,8 +79,9 @@ enum class SymbolProperty : uint8_t {
|
|||
IBAnnotated = 1 << 4,
|
||||
IBOutletCollection = 1 << 5,
|
||||
GKInspectable = 1 << 6,
|
||||
Local = 1 << 7,
|
||||
};
|
||||
static const unsigned SymbolPropertyBitNum = 7;
|
||||
static const unsigned SymbolPropertyBitNum = 8;
|
||||
typedef unsigned SymbolPropertySet;
|
||||
|
||||
/// Set of roles that are attributed to symbol occurrences.
|
||||
|
@ -125,6 +128,8 @@ struct SymbolInfo {
|
|||
|
||||
SymbolInfo getSymbolInfo(const Decl *D);
|
||||
|
||||
bool isFunctionLocalSymbol(const Decl *D);
|
||||
|
||||
void applyForEachSymbolRole(SymbolRoleSet Roles,
|
||||
llvm::function_ref<void(SymbolRole)> Fn);
|
||||
void printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS);
|
||||
|
|
|
@ -269,7 +269,7 @@ public:
|
|||
const Decl *D = *I;
|
||||
if (!D)
|
||||
continue;
|
||||
if (!IndexCtx.isFunctionLocalDecl(D))
|
||||
if (!isFunctionLocalSymbol(D))
|
||||
IndexCtx.indexTopLevelDecl(D);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,37 @@ static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) {
|
|||
}
|
||||
}
|
||||
|
||||
bool index::isFunctionLocalSymbol(const Decl *D) {
|
||||
assert(D);
|
||||
|
||||
if (isa<ParmVarDecl>(D))
|
||||
return true;
|
||||
|
||||
if (isa<TemplateTemplateParmDecl>(D))
|
||||
return true;
|
||||
|
||||
if (isa<ObjCTypeParamDecl>(D))
|
||||
return true;
|
||||
|
||||
if (!D->getParentFunctionOrMethod())
|
||||
return false;
|
||||
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
||||
switch (ND->getFormalLinkage()) {
|
||||
case NoLinkage:
|
||||
case VisibleNoLinkage:
|
||||
case InternalLinkage:
|
||||
return true;
|
||||
case UniqueExternalLinkage:
|
||||
llvm_unreachable("Not a sema linkage");
|
||||
case ExternalLinkage:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SymbolInfo index::getSymbolInfo(const Decl *D) {
|
||||
assert(D);
|
||||
SymbolInfo Info;
|
||||
|
@ -57,6 +88,10 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
|
|||
Info.Properties = SymbolPropertySet();
|
||||
Info.Lang = SymbolLanguage::C;
|
||||
|
||||
if (isFunctionLocalSymbol(D)) {
|
||||
Info.Properties |= (unsigned)SymbolProperty::Local;
|
||||
}
|
||||
|
||||
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
||||
switch (TD->getTagKind()) {
|
||||
case TTK_Struct:
|
||||
|
@ -94,10 +129,13 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
|
|||
|
||||
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
|
||||
Info.Kind = SymbolKind::Variable;
|
||||
if (isa<CXXRecordDecl>(D->getDeclContext())) {
|
||||
if (isa<ParmVarDecl>(D)) {
|
||||
Info.Kind = SymbolKind::Parameter;
|
||||
} else if (isa<CXXRecordDecl>(D->getDeclContext())) {
|
||||
Info.Kind = SymbolKind::StaticProperty;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
}
|
||||
|
||||
if (isa<VarTemplatePartialSpecializationDecl>(D)) {
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
Info.Properties |= (unsigned)SymbolProperty::Generic;
|
||||
|
@ -378,6 +416,7 @@ StringRef index::getSymbolKindString(SymbolKind K) {
|
|||
case SymbolKind::Constructor: return "constructor";
|
||||
case SymbolKind::Destructor: return "destructor";
|
||||
case SymbolKind::ConversionFunction: return "coversion-func";
|
||||
case SymbolKind::Parameter: return "param";
|
||||
}
|
||||
llvm_unreachable("invalid symbol kind");
|
||||
}
|
||||
|
@ -415,6 +454,7 @@ void index::applyForEachSymbolProperty(SymbolPropertySet Props,
|
|||
APPLY_FOR_PROPERTY(IBAnnotated);
|
||||
APPLY_FOR_PROPERTY(IBOutletCollection);
|
||||
APPLY_FOR_PROPERTY(GKInspectable);
|
||||
APPLY_FOR_PROPERTY(Local);
|
||||
|
||||
#undef APPLY_FOR_PROPERTY
|
||||
}
|
||||
|
@ -434,6 +474,7 @@ void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) {
|
|||
case SymbolProperty::IBAnnotated: OS << "IB"; break;
|
||||
case SymbolProperty::IBOutletCollection: OS << "IBColl"; break;
|
||||
case SymbolProperty::GKInspectable: OS << "GKI"; break;
|
||||
case SymbolProperty::Local: OS << "local"; break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
|
|||
}
|
||||
|
||||
void IndexingContext::indexTagDecl(const TagDecl *D) {
|
||||
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
|
||||
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
|
||||
return;
|
||||
|
||||
if (handleDecl(D)) {
|
||||
|
|
|
@ -50,7 +50,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
|
|||
ArrayRef<SymbolRelation> Relations,
|
||||
const Expr *RefE,
|
||||
const Decl *RefD) {
|
||||
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
|
||||
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
|
||||
return true;
|
||||
|
||||
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
|
||||
|
@ -100,34 +100,6 @@ bool IndexingContext::importedModule(const ImportDecl *ImportD) {
|
|||
return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
|
||||
}
|
||||
|
||||
bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
|
||||
assert(D);
|
||||
|
||||
if (isa<TemplateTemplateParmDecl>(D))
|
||||
return true;
|
||||
|
||||
if (isa<ObjCTypeParamDecl>(D))
|
||||
return true;
|
||||
|
||||
if (!D->getParentFunctionOrMethod())
|
||||
return false;
|
||||
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
||||
switch (ND->getFormalLinkage()) {
|
||||
case NoLinkage:
|
||||
case VisibleNoLinkage:
|
||||
case InternalLinkage:
|
||||
return true;
|
||||
case UniqueExternalLinkage:
|
||||
llvm_unreachable("Not a sema linkage");
|
||||
case ExternalLinkage:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
|
||||
TemplateSpecializationKind TKind = TSK_Undeclared;
|
||||
if (const ClassTemplateSpecializationDecl *
|
||||
|
@ -316,12 +288,12 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
|
|||
};
|
||||
|
||||
if (Parent) {
|
||||
if (IsRef) {
|
||||
if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
|
||||
addRelation(SymbolRelation{
|
||||
(unsigned)SymbolRole::RelationContainedBy,
|
||||
Parent
|
||||
});
|
||||
} else if (!cast<DeclContext>(Parent)->isFunctionOrMethod()) {
|
||||
} else {
|
||||
addRelation(SymbolRelation{
|
||||
(unsigned)SymbolRole::RelationChildOf,
|
||||
Parent
|
||||
|
|
|
@ -58,7 +58,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool isFunctionLocalDecl(const Decl *D);
|
||||
static bool isTemplateImplicitInstantiation(const Decl *D);
|
||||
|
||||
bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
|
||||
// RUN: c-index-test core -print-source-symbols -include-locals -- %s -target x86_64-apple-macosx10.7 | FileCheck -check-prefix=LOCAL %s
|
||||
|
||||
@interface Base
|
||||
// CHECK: [[@LINE-1]]:12 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Decl | rel: 0
|
||||
|
@ -13,10 +14,33 @@
|
|||
@end
|
||||
|
||||
void foo();
|
||||
// CHECK: [[@LINE+3]]:6 | function/C | goo | c:@F@goo | _goo | Def | rel: 0
|
||||
// CHECK: [[@LINE+2]]:10 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+6]]:6 | function/C | goo | c:@F@goo | _goo | Def | rel: 0
|
||||
// CHECK: [[@LINE+5]]:10 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref,RelCont | rel: 1
|
||||
// CHECK-NEXT: RelCont | goo | c:@F@goo
|
||||
// CHECK-NOT: [[@LINE+3]]:16 | param
|
||||
// LOCAL: [[@LINE+2]]:16 | param(local)/C | b | [[b_USR:c:.*]] | _b | Def,RelChild | rel: 1
|
||||
// LOCAL-NEXT: RelChild | goo | c:@F@goo
|
||||
void goo(Base *b) {
|
||||
// CHECK-NOT: [[@LINE+6]]:7 | variable
|
||||
// LOCAL: [[@LINE+5]]:7 | variable(local)/C | x | [[x_USR:c:.*]] | _x | Def,RelCont | rel: 1
|
||||
// LOCAL-NEXT: RelCont | goo | c:@F@goo
|
||||
// CHECK-NOT: [[@LINE+3]]:11 | param
|
||||
// LOCAL: [[@LINE+2]]:11 | param(local)/C | b | [[b_USR]] | _b | Ref,Read,RelCont | rel: 1
|
||||
// LOCAL-NEXT: RelCont | x | [[x_USR]]
|
||||
int x = b;
|
||||
// CHECK-NOT: [[@LINE+5]]:7 | variable
|
||||
// LOCAL: [[@LINE+4]]:7 | variable(local)/C | y | [[y_USR:c:.*]] | _y | Def,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE+3]]:11 | variable
|
||||
// LOCAL: [[@LINE+2]]:11 | variable(local)/C | x | [[x_USR]] | _x | Ref,Read,RelCont | rel: 1
|
||||
// LOCAL-NEXT: RelCont | y | [[y_USR]]
|
||||
int y = x;
|
||||
|
||||
// CHECK-NOT: [[@LINE+1]]:10 | struct
|
||||
// LOCAL: [[@LINE+1]]:10 | struct(local)/C | Foo | c:{{.*}} | <no-cgname> | Def,RelCont | rel: 1
|
||||
struct Foo {
|
||||
int i;
|
||||
};
|
||||
|
||||
// CHECK: [[@LINE+2]]:3 | function/C | foo | c:@F@foo | _foo | Ref,Call,RelCall,RelCont | rel: 1
|
||||
// CHECK-NEXT: RelCall,RelCont | goo | c:@F@goo
|
||||
foo();
|
||||
|
@ -118,11 +142,17 @@ extern int setjmp(jmp_buf);
|
|||
// CHECK-NEXT: RelChild | I2 | c:objc(cs)I2
|
||||
@synthesize prop = _prop;
|
||||
|
||||
// CHECK: [[@LINE+5]]:12 | instance-method(IB)/ObjC | doAction:foo: | c:objc(cs)I2(im)doAction:foo: | -[I2 doAction:foo:] | Def,Dyn,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+11]]:12 | instance-method(IB)/ObjC | doAction:foo: | c:objc(cs)I2(im)doAction:foo: | -[I2 doAction:foo:] | Def,Dyn,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | I2 | c:objc(cs)I2
|
||||
// CHECK: [[@LINE+3]]:22 | class/ObjC | I1 | c:objc(cs)I1 | _OBJC_CLASS_$_I1 | Ref,RelCont,RelIBType | rel: 1
|
||||
// CHECK: [[@LINE+9]]:22 | class/ObjC | I1 | c:objc(cs)I1 | _OBJC_CLASS_$_I1 | Ref,RelCont,RelIBType | rel: 1
|
||||
// CHECK-NEXT: RelCont,RelIBType | doAction:foo: | c:objc(cs)I2(im)doAction:foo:
|
||||
// CHECK: [[@LINE+1]]:39 | class/ObjC | I1 | c:objc(cs)I1 | _OBJC_CLASS_$_I1 | Ref,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE+7]]:27 | param
|
||||
// LOCAL: [[@LINE+6]]:27 | param(local)/C | sender | c:{{.*}} | _sender | Def,RelChild | rel: 1
|
||||
// LOCAL-NEXT: RelChild | doAction:foo: | c:objc(cs)I2(im)doAction:foo:
|
||||
// CHECK: [[@LINE+4]]:39 | class/ObjC | I1 | c:objc(cs)I1 | _OBJC_CLASS_$_I1 | Ref,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE+3]]:44 | param
|
||||
// LOCAL: [[@LINE+2]]:44 | param(local)/C | bar | c:{{.*}} | _bar | Def,RelChild | rel: 1
|
||||
// LOCAL-NEXT: RelChild | doAction:foo: | c:objc(cs)I2(im)doAction:foo:
|
||||
-(IBAction)doAction:(I1 *)sender foo:(I1 *)bar {}
|
||||
@end
|
||||
|
||||
|
@ -132,9 +162,10 @@ extern int setjmp(jmp_buf);
|
|||
// CHECK-NEXT: RelChild | I3 | c:objc(cs)I3
|
||||
// CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop
|
||||
-(id)prop;
|
||||
// CHECK: [[@LINE+3]]:8 | instance-method/acc-set/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Decl,Dyn,RelChild,RelAcc | rel: 2
|
||||
// CHECK: [[@LINE+4]]:8 | instance-method/acc-set/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Decl,Dyn,RelChild,RelAcc | rel: 2
|
||||
// CHECK-NEXT: RelChild | I3 | c:objc(cs)I3
|
||||
// CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop
|
||||
// LOCAL-NOT: [[@LINE+1]]:20 | param
|
||||
-(void)setProp:(id)p;
|
||||
@end
|
||||
|
||||
|
|
|
@ -55,6 +55,9 @@ static cl::opt<bool>
|
|||
DumpModuleImports("dump-imported-module-files",
|
||||
cl::desc("Print symbols and input files from imported modules"));
|
||||
|
||||
static cl::opt<bool>
|
||||
IncludeLocals("include-locals", cl::desc("Print local symbols"));
|
||||
|
||||
static cl::opt<std::string>
|
||||
ModuleFilePath("module-file",
|
||||
cl::desc("Path to module file to print symbols from"));
|
||||
|
@ -159,7 +162,8 @@ static void dumpModuleFileInputs(serialization::ModuleFile &Mod,
|
|||
}
|
||||
|
||||
static bool printSourceSymbols(ArrayRef<const char *> Args,
|
||||
bool dumpModuleImports) {
|
||||
bool dumpModuleImports,
|
||||
bool indexLocals) {
|
||||
SmallVector<const char *, 4> ArgsWithProgName;
|
||||
ArgsWithProgName.push_back("clang");
|
||||
ArgsWithProgName.append(Args.begin(), Args.end());
|
||||
|
@ -172,6 +176,7 @@ static bool printSourceSymbols(ArrayRef<const char *> Args,
|
|||
raw_ostream &OS = outs();
|
||||
auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(OS);
|
||||
IndexingOptions IndexOpts;
|
||||
IndexOpts.IndexFunctionLocals = indexLocals;
|
||||
std::unique_ptr<FrontendAction> IndexAction;
|
||||
IndexAction = createIndexingAction(DataConsumer, IndexOpts,
|
||||
/*WrappedAction=*/nullptr);
|
||||
|
@ -297,7 +302,7 @@ int indextest_core_main(int argc, const char **argv) {
|
|||
errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n";
|
||||
return 1;
|
||||
}
|
||||
return printSourceSymbols(CompArgs, options::DumpModuleImports);
|
||||
return printSourceSymbols(CompArgs, options::DumpModuleImports, options::IncludeLocals);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1294,6 +1294,7 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage
|
|||
case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor;
|
||||
case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor;
|
||||
case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction;
|
||||
case SymbolKind::Parameter: return CXIdxEntity_Variable;
|
||||
}
|
||||
llvm_unreachable("invalid symbol kind");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue