]> granicus.if.org Git - clang/commitdiff
[libclang] indexing: make sure to not visit init-list expressions twice.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 9 Feb 2016 19:07:24 +0000 (19:07 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 9 Feb 2016 19:07:24 +0000 (19:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@260255 91177308-0d34-0410-b5e6-96231b3b80d8

test/Index/index-refs.cpp
tools/libclang/IndexBody.cpp

index adbf02a7c6e221e0390d3bdc2243feb163629b53..5a1ba1e8b43ae2afef5944917dde62f0ed59fc80 100644 (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
index 64df4b85beac7b5d1487e2319b0f19691f079fd9..58dc11722bf1cb047ecd540ffe264a0f206642d5 100644 (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