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

Argyrios Kyrtzidis via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 9 11:07:24 PST 2016


Author: akirtzidis
Date: Tue Feb  9 13:07:24 2016
New Revision: 260255

URL: http://llvm.org/viewvc/llvm-project?rev=260255&view=rev
Log:
[libclang] indexing: make sure to not visit init-list expressions twice.

Modified:
    cfe/trunk/test/Index/index-refs.cpp
    cfe/trunk/tools/libclang/IndexBody.cpp

Modified: cfe/trunk/test/Index/index-refs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/index-refs.cpp?rev=260255&r1=260254&r2=260255&view=diff
==============================================================================
--- cfe/trunk/test/Index/index-refs.cpp (original)
+++ cfe/trunk/test/Index/index-refs.cpp Tue Feb  9 13:07:24 2016
@@ -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

Modified: cfe/trunk/tools/libclang/IndexBody.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=260255&r1=260254&r2=260255&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexBody.cpp (original)
+++ cfe/trunk/tools/libclang/IndexBody.cpp Tue Feb  9 13:07:24 2016
@@ -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




More information about the cfe-commits mailing list