[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:
Argyrios Kyrtzidis 2017-02-26 05:37:56 +00:00
parent 42ef2177af
commit 6d1a15b2d4
9 changed files with 98 additions and 44 deletions

View File

@ -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);

View File

@ -269,7 +269,7 @@ public:
const Decl *D = *I;
if (!D)
continue;
if (!IndexCtx.isFunctionLocalDecl(D))
if (!isFunctionLocalSymbol(D))
IndexCtx.indexTopLevelDecl(D);
}

View File

@ -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;
}
});
}

View File

@ -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)) {

View File

@ -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

View File

@ -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(),

View File

@ -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

View File

@ -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;

View File

@ -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");
}