[libclang] indexing: make sure to not visit init-list expressions twice.

llvm-svn: 260255
This commit is contained in:
Argyrios Kyrtzidis 2016-02-09 19:07:24 +00:00
parent 49385e8bd5
commit ca4ad1937c
2 changed files with 66 additions and 11 deletions

View File

@ -69,6 +69,8 @@ void foo5() {
struct S2 s = { .y = 1, .x = 4};
}
int ginitlist[] = {EnumVal};
// RUN: c-index-test -index-file %s | FileCheck %s
// CHECK: [indexDeclaration]: kind: namespace | name: NS
// CHECK-NEXT: [indexDeclaration]: kind: variable | name: gx
@ -119,3 +121,9 @@ void foo5() {
// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20
// CHECK-NEXT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 69:28
// CHECK-NOT: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20
// CHECK-NOT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 69:28
// CHECK: [indexDeclaration]: kind: variable | name: ginitlist |
// CHECK: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 72:20
// CHECK-NOT: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 72:20

View File

@ -50,17 +50,6 @@ public:
return true;
}
bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
for (DesignatedInitExpr::reverse_designators_iterator
D = E->designators_rbegin(), DEnd = E->designators_rend();
D != DEnd; ++D) {
if (D->isFieldDesignator())
IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
Parent, ParentDC, E);
}
return true;
}
bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
IndexCtx.handleReference(E->getDecl(), E->getLocation(),
Parent, ParentDC, E);
@ -162,6 +151,64 @@ public:
return true;
}
// RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
// the things that we visit. Make sure to only visit the semantic form.
// Also visit things that are in the syntactic form but not the semantic one,
// for example the indices in DesignatedInitExprs.
bool TraverseInitListExpr(InitListExpr *S) {
class SyntacticFormIndexer :
public RecursiveASTVisitor<SyntacticFormIndexer> {
IndexingContext &IndexCtx;
const NamedDecl *Parent;
const DeclContext *ParentDC;
public:
SyntacticFormIndexer(IndexingContext &indexCtx,
const NamedDecl *Parent, const DeclContext *DC)
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
for (DesignatedInitExpr::reverse_designators_iterator
D = E->designators_rbegin(), DEnd = E->designators_rend();
D != DEnd; ++D) {
if (D->isFieldDesignator())
IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
Parent, ParentDC, E);
}
return true;
}
};
auto visitForm = [&](InitListExpr *Form) {
for (Stmt *SubStmt : Form->children()) {
if (!TraverseStmt(SubStmt))
return false;
}
return true;
};
InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
if (SemaForm) {
// Visit things present in syntactic form but not the semantic form.
if (SyntaxForm) {
SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
}
return visitForm(SemaForm);
}
// No semantic, try the syntactic.
if (SyntaxForm) {
return visitForm(SyntaxForm);
}
return true;
}
};
} // anonymous namespace