[libclang] Indexing API: Fix indexing of missed references.

rdar://10567864&10567916

llvm-svn: 146497
This commit is contained in:
Argyrios Kyrtzidis 2011-12-13 18:47:41 +00:00
parent ccdf8276a3
commit 25cb0ff3d8
7 changed files with 142 additions and 31 deletions

View File

@ -4311,11 +4311,12 @@ typedef struct {
* \endcode
*
* The parent of reference of type 'Foo' is the variable 'var'.
* parentEntity will be null for references inside statement bodies.
* For references inside statement bodies of functions/methods,
* the parentEntity will be the function/method.
*/
const CXIdxEntityInfo *parentEntity;
/**
* \brief Container context of the reference.
* \brief Lexical container context of the reference.
*/
const CXIdxContainerInfo *container;
} CXIdxEntityRefInfo;

View File

@ -1566,6 +1566,8 @@ DEF_TRAVERSE_DECL(FieldDecl, {
TRY_TO(TraverseDeclaratorHelper(D));
if (D->isBitField())
TRY_TO(TraverseStmt(D->getBitWidth()));
else if (D->hasInClassInitializer())
TRY_TO(TraverseStmt(D->getInClassInitializer()));
})
DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {

View File

@ -0,0 +1,37 @@
namespace NS {
extern int gx;
typedef int MyInt;
}
enum {
EnumVal = 1
};
NS::MyInt NS::gx = EnumVal;
void foo() {
NS::MyInt x;
}
enum {
SecondVal = EnumVal
};
// RUN: c-index-test -index-file %s | FileCheck %s
// CHECK: [indexDeclaration]: kind: namespace | name: NS
// CHECK-NEXT: [indexDeclaration]: kind: variable | name: gx
// CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt
// CHECK-NEXT: [indexDeclaration]: kind: enum
// CHECK-NEXT: [indexDeclaration]: kind: enumerator | name: EnumVal
// CHECK-NEXT: [indexDeclaration]: kind: variable | name: gx
// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS
// CHECK-NEXT: [indexEntityReference]: kind: typedef | name: MyInt
// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS
// CHECK-NEXT: [indexEntityReference]: kind: enumerator | name: EnumVal
// CHECK-NEXT: [indexDeclaration]: kind: function | name: foo
// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS
// CHECK-NEXT: [indexEntityReference]: kind: typedef | name: MyInt
// CHECK-NEXT: [indexDeclaration]: kind: enum
// CHECK-NEXT: [indexDeclaration]: kind: enumerator | name: SecondVal
// CHECK-NEXT: [indexEntityReference]: kind: enumerator | name: EnumVal

View File

@ -19,43 +19,49 @@ namespace {
class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
IndexingContext &IndexCtx;
const NamedDecl *Parent;
const DeclContext *ParentDC;
bool InPseudoObject;
typedef RecursiveASTVisitor<BodyIndexer> base;
public:
BodyIndexer(IndexingContext &indexCtx, const DeclContext *DC)
: IndexCtx(indexCtx), ParentDC(DC), InPseudoObject(false) { }
BodyIndexer(IndexingContext &indexCtx,
const NamedDecl *Parent, const DeclContext *DC)
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC),
InPseudoObject(false) { }
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool TraverseTypeLoc(TypeLoc TL) {
IndexCtx.indexTypeLoc(TL, 0, ParentDC);
IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
return true;
}
bool VisitDeclRefExpr(DeclRefExpr *E) {
IndexCtx.handleReference(E->getDecl(), E->getLocation(), 0, ParentDC, E);
IndexCtx.handleReference(E->getDecl(), E->getLocation(),
Parent, ParentDC, E);
return true;
}
bool VisitMemberExpr(MemberExpr *E) {
IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(), 0, ParentDC,
E);
IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(),
Parent, ParentDC, E);
return true;
}
bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
IndexCtx.handleReference(E->getDecl(), E->getLocation(), 0, ParentDC, E);
IndexCtx.handleReference(E->getDecl(), E->getLocation(),
Parent, ParentDC, E);
return true;
}
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
if (TypeSourceInfo *Cls = E->getClassReceiverTypeInfo())
IndexCtx.indexTypeSourceInfo(Cls, 0, ParentDC);
IndexCtx.indexTypeSourceInfo(Cls, Parent, ParentDC);
if (ObjCMethodDecl *MD = E->getMethodDecl())
IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 0, ParentDC, E,
IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
Parent, ParentDC, E,
InPseudoObject ? CXIdxEntityRef_Implicit
: CXIdxEntityRef_Direct);
return true;
@ -64,14 +70,14 @@ public:
bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
if (E->isImplicitProperty()) {
if (ObjCMethodDecl *MD = E->getImplicitPropertyGetter())
IndexCtx.handleReference(MD, E->getLocation(), 0, ParentDC, E,
IndexCtx.handleReference(MD, E->getLocation(), Parent, ParentDC, E,
CXIdxEntityRef_Implicit);
if (ObjCMethodDecl *MD = E->getImplicitPropertySetter())
IndexCtx.handleReference(MD, E->getLocation(), 0, ParentDC, E,
IndexCtx.handleReference(MD, E->getLocation(), Parent, ParentDC, E,
CXIdxEntityRef_Implicit);
} else {
IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 0,
ParentDC, E);
IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
Parent, ParentDC, E);
}
return true;
}
@ -82,14 +88,20 @@ public:
}
bool VisitCXXConstructExpr(CXXConstructExpr *E) {
IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 0,
ParentDC, E);
IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
Parent, ParentDC, E);
return true;
}
};
} // anonymous namespace
void IndexingContext::indexBody(const Stmt *S, const DeclContext *DC) {
BodyIndexer(*this, DC).TraverseStmt(const_cast<Stmt*>(S));
void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
const DeclContext *DC) {
if (!S)
return;
if (DC == 0)
DC = Parent->getLexicalDeclContext();
BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
}

View File

@ -23,13 +23,19 @@ public:
explicit IndexingDeclVisitor(IndexingContext &indexCtx)
: IndexCtx(indexCtx) { }
void handleDeclarator(DeclaratorDecl *D, const NamedDecl *Parent = 0) {
if (!Parent) Parent = D;
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
}
bool VisitFunctionDecl(FunctionDecl *D) {
IndexCtx.handleFunction(D);
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
handleDeclarator(D);
if (D->isThisDeclarationADefinition()) {
const Stmt *Body = D->getBody();
if (Body) {
IndexCtx.indexBody(Body, D);
IndexCtx.indexBody(Body, D, D);
}
}
return true;
@ -37,18 +43,24 @@ public:
bool VisitVarDecl(VarDecl *D) {
IndexCtx.handleVar(D);
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
handleDeclarator(D);
IndexCtx.indexBody(D->getInit(), D);
return true;
}
bool VisitFieldDecl(FieldDecl *D) {
IndexCtx.handleField(D);
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
handleDeclarator(D);
if (D->isBitField())
IndexCtx.indexBody(D->getBitWidth(), D);
else if (D->hasInClassInitializer())
IndexCtx.indexBody(D->getInClassInitializer(), D);
return true;
}
bool VisitEnumConstantDecl(EnumConstantDecl *D) {
IndexCtx.handleEnumerator(D);
IndexCtx.indexBody(D->getInitExpr(), D);
return true;
}
@ -147,12 +159,12 @@ public:
IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D);
for (ObjCMethodDecl::param_iterator
I = D->param_begin(), E = D->param_end(); I != E; ++I)
IndexCtx.indexTypeSourceInfo((*I)->getTypeSourceInfo(), D);
handleDeclarator(*I, D);
if (D->isThisDeclarationADefinition()) {
const Stmt *Body = D->getBody();
if (Body) {
IndexCtx.indexBody(Body, D);
IndexCtx.indexBody(Body, D, D);
}
}
return true;
@ -205,11 +217,11 @@ public:
bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
IndexCtx.handleFunctionTemplate(D);
FunctionDecl *FD = D->getTemplatedDecl();
IndexCtx.indexTypeSourceInfo(FD->getTypeSourceInfo(), D);
handleDeclarator(FD, D);
if (FD->isThisDeclarationADefinition()) {
const Stmt *Body = FD->getBody();
if (Body) {
IndexCtx.indexBody(Body, FD);
IndexCtx.indexBody(Body, D, FD);
}
}
return true;

View File

@ -34,6 +34,11 @@ public:
return true;
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
return true;
}
bool VisitTagTypeLoc(TagTypeLoc TL) {
TagDecl *D = TL.getDecl();
if (D->getParentFunctionOrMethod())
@ -75,17 +80,54 @@ void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
if (!TInfo || TInfo->getTypeLoc().isNull())
return;
if (DC == 0)
DC = Parent->getDeclContext();
indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
}
void IndexingContext::indexTypeLoc(TypeLoc TL,
const NamedDecl *Parent,
const DeclContext *DC) {
if (TL.isNull())
return;
if (DC == 0)
DC = Parent->getLexicalDeclContext();
TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
}
void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
const NamedDecl *Parent,
const DeclContext *DC) {
if (!NNS)
return;
if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
indexNestedNameSpecifierLoc(Prefix, Parent, DC);
if (DC == 0)
DC = Parent->getLexicalDeclContext();
SourceLocation Loc = NNS.getSourceRange().getBegin();
switch (NNS.getNestedNameSpecifier()->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Global:
break;
case NestedNameSpecifier::Namespace:
handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
Loc, Parent, DC);
break;
case NestedNameSpecifier::NamespaceAlias:
handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
Loc, Parent, DC);
break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
break;
}
}
void IndexingContext::indexTagDecl(const TagDecl *D) {
if (handleTagDecl(D)) {
if (D->isThisDeclarationADefinition())

View File

@ -334,11 +334,16 @@ public:
const DeclContext *DC = 0);
void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
const DeclContext *DC);
const DeclContext *DC = 0);
void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
const NamedDecl *Parent,
const DeclContext *DC = 0);
void indexDeclContext(const DeclContext *DC);
void indexBody(const Stmt *S, const DeclContext *DC);
void indexBody(const Stmt *S, const NamedDecl *Parent,
const DeclContext *DC = 0);
void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);