[libclang] Indexing API: Fix indexing of missed references.
rdar://10567864&10567916 llvm-svn: 146497
This commit is contained in:
parent
ccdf8276a3
commit
25cb0ff3d8
|
@ -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;
|
||||
|
|
|
@ -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, {
|
||||
|
|
|
@ -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
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue