summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/Index/index-refs.cpp8
-rw-r--r--tools/libclang/IndexBody.cpp69
2 files changed, 66 insertions, 11 deletions
diff --git a/test/Index/index-refs.cpp b/test/Index/index-refs.cpp
index adbf02a7c6..5a1ba1e8b4 100644
--- a/test/Index/index-refs.cpp
+++ b/test/Index/index-refs.cpp
@@ -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
diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp
index 64df4b85be..58dc11722b 100644
--- a/tools/libclang/IndexBody.cpp
+++ b/tools/libclang/IndexBody.cpp
@@ -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