[index] When indexing system headers make sure to report important reference relations
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 23 Mar 2017 16:34:47 +0000 (16:34 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 23 Mar 2017 16:34:47 +0000 (16:34 +0000)
Even if we exclude plain reference occurrences, we should include relation-based references, like the 'base' one.

rdar://31010737

llvm-svn: 298622

clang/include/clang/Index/IndexSymbol.h
clang/lib/Index/IndexSymbol.cpp
clang/lib/Index/IndexingContext.cpp
clang/test/Index/Core/Inputs/sys/system-head.h [new file with mode: 0644]
clang/test/Index/Core/index-system.mm [new file with mode: 0644]

index eb718d7..217d6b1 100644 (file)
@@ -132,6 +132,8 @@ bool isFunctionLocalSymbol(const Decl *D);
 
 void applyForEachSymbolRole(SymbolRoleSet Roles,
                             llvm::function_ref<void(SymbolRole)> Fn);
+bool applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
+                            llvm::function_ref<bool(SymbolRole)> Fn);
 void printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS);
 
 /// \returns true if no name was printed, false otherwise.
index 785125c..fe3c178 100644 (file)
@@ -321,11 +321,12 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
   return Info;
 }
 
-void index::applyForEachSymbolRole(SymbolRoleSet Roles,
-                                   llvm::function_ref<void(SymbolRole)> Fn) {
+bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
+                                   llvm::function_ref<bool(SymbolRole)> Fn) {
 #define APPLY_FOR_ROLE(Role) \
   if (Roles & (unsigned)SymbolRole::Role) \
-    Fn(SymbolRole::Role)
+    if (!Fn(SymbolRole::Role)) \
+      return false;
 
   APPLY_FOR_ROLE(Declaration);
   APPLY_FOR_ROLE(Definition);
@@ -347,6 +348,16 @@ void index::applyForEachSymbolRole(SymbolRoleSet Roles,
   APPLY_FOR_ROLE(RelationIBTypeOf);
 
 #undef APPLY_FOR_ROLE
+
+  return true;
+}
+
+void index::applyForEachSymbolRole(SymbolRoleSet Roles,
+                                   llvm::function_ref<void(SymbolRole)> Fn) {
+  applyForEachSymbolRoleInterruptible(Roles, [&](SymbolRole r) -> bool {
+    Fn(r);
+    return true;
+  });
 }
 
 void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
index 9a4028f..c5ccf45 100644 (file)
@@ -204,6 +204,49 @@ static const Decl *getCanonicalDecl(const Decl *D) {
   return D;
 }
 
+static bool shouldReportOccurrenceForSystemDeclOnlyMode(
+    bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
+  if (!IsRef)
+    return true;
+
+  auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
+    bool accept = false;
+    applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
+      switch (r) {
+      case SymbolRole::RelationChildOf:
+      case SymbolRole::RelationBaseOf:
+      case SymbolRole::RelationOverrideOf:
+      case SymbolRole::RelationExtendedBy:
+      case SymbolRole::RelationAccessorOf:
+      case SymbolRole::RelationIBTypeOf:
+        accept = true;
+        return false;
+      case SymbolRole::Declaration:
+      case SymbolRole::Definition:
+      case SymbolRole::Reference:
+      case SymbolRole::Read:
+      case SymbolRole::Write:
+      case SymbolRole::Call:
+      case SymbolRole::Dynamic:
+      case SymbolRole::AddressOf:
+      case SymbolRole::Implicit:
+      case SymbolRole::RelationReceivedBy:
+      case SymbolRole::RelationCalledBy:
+      case SymbolRole::RelationContainedBy:
+        return true;
+      }
+    });
+    return accept;
+  };
+
+  for (auto &Rel : Relations) {
+    if (acceptForRelation(Rel.Roles))
+      return true;
+  }
+
+  return false;
+}
+
 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
                                            bool IsRef, const Decl *Parent,
                                            SymbolRoleSet Roles,
@@ -239,7 +282,7 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
     case IndexingOptions::SystemSymbolFilterKind::None:
       return true;
     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
-      if (IsRef)
+      if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
         return true;
       break;
     case IndexingOptions::SystemSymbolFilterKind::All:
diff --git a/clang/test/Index/Core/Inputs/sys/system-head.h b/clang/test/Index/Core/Inputs/sys/system-head.h
new file mode 100644 (file)
index 0000000..df0e39e
--- /dev/null
@@ -0,0 +1,36 @@
+// CHECK: [[@LINE+1]]:12 | class/ObjC | Base | [[Base_USR:.*]] | {{.*}} | Decl | rel: 0
+@interface Base
+@end
+
+// CHECK: [[@LINE+1]]:11 | protocol/ObjC | Prot1 | [[Prot1_USR:.*]] | {{.*}} | Decl | rel: 0
+@protocol Prot1
+@end
+
+// CHECK: [[@LINE+3]]:11 | protocol/ObjC | Prot2 | [[Prot2_USR:.*]] | {{.*}} | Decl | rel: 0
+// CHECK: [[@LINE+2]]:17 | protocol/ObjC | Prot1 | [[Prot1_USR]] | {{.*}} | Ref,RelBase,RelCont | rel: 1
+// CHECK-NEXT: RelBase,RelCont | Prot2 | [[Prot2_USR]]
+@protocol Prot2<Prot1>
+@end
+
+// CHECK: [[@LINE+7]]:12 | class/ObjC | Sub | [[Sub_USR:.*]] | {{.*}} | Decl | rel: 0
+// CHECK: [[@LINE+6]]:18 | class/ObjC | Base | [[Base_USR]] | {{.*}} | Ref,RelBase,RelCont | rel: 1
+// CHECK-NEXT: RelBase,RelCont | Sub | [[Sub_USR]]
+// CHECK: [[@LINE+4]]:23 | protocol/ObjC | Prot2 | [[Prot2_USR]] | {{.*}} | Ref,RelBase,RelCont | rel: 1
+// CHECK-NEXT: RelBase,RelCont | Sub | [[Sub_USR]]
+// CHECK: [[@LINE+2]]:30 | protocol/ObjC | Prot1 | [[Prot1_USR]] | {{.*}} | Ref,RelBase,RelCont | rel: 1
+// CHECK-NEXT: RelBase,RelCont | Sub | [[Sub_USR]]
+@interface Sub : Base<Prot2, Prot1>
+// CHECK-NOT: [[@LINE+1]]:3 | class/ObjC | Sub |
+-(Sub*)getit;
+@end
+
+// CHECK: [[@LINE+1]]:7 | class/C++ | Cls | [[Cls_USR:.*]] | {{.*}} | Def | rel: 0
+class Cls {};
+
+// CHECK: [[@LINE+3]]:7 | class/C++ | SubCls1 | [[SubCls1_USR:.*]] | {{.*}} | Def | rel: 0
+// CHECK: [[@LINE+2]]:24 | class/C++ | Cls | [[Cls_USR]] | {{.*}} | Ref,RelBase,RelCont | rel: 1
+// CHECK-NEXT: RelBase,RelCont | SubCls1 | [[SubCls1_USR]]
+class SubCls1 : public Cls {
+  // CHECK-NOT: [[@LINE+1]]:3 | class/C++ | SubCls1 |
+  SubCls1 *f;
+};
diff --git a/clang/test/Index/Core/index-system.mm b/clang/test/Index/Core/index-system.mm
new file mode 100644 (file)
index 0000000..2ad31fa
--- /dev/null
@@ -0,0 +1,3 @@
+// RUN: c-index-test core -print-source-symbols -- %s -isystem %S/Inputs/sys | FileCheck %S/Inputs/sys/system-head.h
+
+#include "system-head.h"