[cfe-commits] r141277 - in /cfe/trunk: include/clang-c/Index.h test/Index/file-refs.c test/Index/file-refs.cpp test/Index/file-refs.m tools/c-index-test/c-index-test.c tools/libclang/CIndex.cpp tools/libclang/CIndexHigh.cpp tools/libclang/CMakeLists.txt tools/libclang/CXCursor.cpp tools/libclang/CXCursor.h tools/libclang/Index_Internal.h tools/libclang/libclang.exports

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Oct 6 00:00:54 PDT 2011


Author: akirtzidis
Date: Thu Oct  6 02:00:54 2011
New Revision: 141277

URL: http://llvm.org/viewvc/llvm-project?rev=141277&view=rev
Log:
[libclang] Introduce clang_findReferencesInFile which accepts a cursor, a file,
and a callback and finds all identifier references of the cursor in the file.

rdar://7948304

Added:
    cfe/trunk/test/Index/file-refs.c
    cfe/trunk/test/Index/file-refs.cpp
    cfe/trunk/test/Index/file-refs.m
    cfe/trunk/tools/libclang/CIndexHigh.cpp
    cfe/trunk/tools/libclang/Index_Internal.h
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CMakeLists.txt
    cfe/trunk/tools/libclang/CXCursor.cpp
    cfe/trunk/tools/libclang/CXCursor.h
    cfe/trunk/tools/libclang/libclang.exports

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=141277&r1=141276&r2=141277&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Oct  6 02:00:54 2011
@@ -1857,6 +1857,7 @@
  */
 typedef struct {
   enum CXCursorKind kind;
+  int xdata;
   void *data[3];
 } CXCursor;
 
@@ -3779,6 +3780,53 @@
  * @}
  */
 
+/** \defgroup CINDEX_HIGH Higher level API functions
+ *
+ * @{
+ */
+
+enum CXVisitorResult {
+  CXVisit_Break,
+  CXVisit_Continue
+};
+
+typedef struct {
+  void *context;
+  enum CXVisitorResult (*visit)(void *context, CXCursor, CXSourceRange);
+} CXCursorAndRangeVisitor;
+
+/**
+ * \brief Find references of a declaration in a specific file.
+ * 
+ * \param cursor pointing to a declaration or a reference of one.
+ *
+ * \param file to search for references.
+ *
+ * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for
+ * each reference found.
+ * The CXSourceRange will point inside the file; if the reference is inside
+ * a macro (and not a macro argument) the CXSourceRange will be invalid.
+ */
+CINDEX_LINKAGE void clang_findReferencesInFile(CXCursor cursor, CXFile file,
+                                               CXCursorAndRangeVisitor visitor);
+
+#ifdef __has_feature
+#  if __has_feature(blocks)
+
+typedef enum CXVisitorResult
+    (^CXCursorAndRangeVisitorBlock)(CXCursor, CXSourceRange);
+
+CINDEX_LINKAGE
+void clang_findReferencesInFileWithBlock(CXCursor, CXFile,
+                                         CXCursorAndRangeVisitorBlock);
+
+#  endif
+#endif
+
+/**
+ * @}
+ */
+
 /**
  * @}
  */

Added: cfe/trunk/test/Index/file-refs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/file-refs.c?rev=141277&view=auto
==============================================================================
--- cfe/trunk/test/Index/file-refs.c (added)
+++ cfe/trunk/test/Index/file-refs.c Thu Oct  6 02:00:54 2011
@@ -0,0 +1,57 @@
+enum {
+  VALUE = 3
+};
+
+extern int glob_x;
+
+int f(int x) {
+  return x+glob_x+VALUE; 
+}
+
+typedef struct {
+  int x;
+  int y;
+} Vector;
+
+int vector_get_x(Vector v) {
+  int x = v.x;
+  return x;
+}
+
+int f(int);
+int f(int);
+
+// RUN: c-index-test \
+
+// RUN:  -file-refs-at=%s:2:5 \
+// CHECK:      EnumConstantDecl=VALUE:2:3 (Definition)
+// CHECK-NEXT: EnumConstantDecl=VALUE:2:3 (Definition) =[2:3 - 2:8]
+// CHECK-NEXT: DeclRefExpr=VALUE:2:3 =[8:19 - 8:24]
+
+// RUN:  -file-refs-at=%s:8:15 \
+// CHECK-NEXT: DeclRefExpr=glob_x:5:12
+// CHECK-NEXT: VarDecl=glob_x:5:12 =[5:12 - 5:18]
+// CHECK-NEXT: DeclRefExpr=glob_x:5:12 =[8:12 - 8:18]
+
+// RUN:  -file-refs-at=%s:8:10 \
+// CHECK-NEXT: DeclRefExpr=x:7:11
+// CHECK-NEXT: ParmDecl=x:7:11 (Definition) =[7:11 - 7:12]
+// CHECK-NEXT: DeclRefExpr=x:7:11 =[8:10 - 8:11]
+
+// RUN:  -file-refs-at=%s:12:7 \
+// CHECK-NEXT: FieldDecl=x:12:7 (Definition)
+// CHECK-NEXT: FieldDecl=x:12:7 (Definition) =[12:7 - 12:8]
+// CHECK-NEXT: MemberRefExpr=x:12:7 {{.*}} =[17:13 - 17:14]
+
+// RUN:  -file-refs-at=%s:16:21 \
+// CHECK-NEXT: TypeRef=Vector:14:3
+// CHECK-NEXT: TypedefDecl=Vector:14:3 (Definition) =[14:3 - 14:9]
+// CHECK-NEXT: TypeRef=Vector:14:3 =[16:18 - 16:24]
+
+// RUN:  -file-refs-at=%s:21:5 \
+// CHECK-NEXT: FunctionDecl=f:21:5
+// CHECK-NEXT: FunctionDecl=f:7:5 (Definition) =[7:5 - 7:6]
+// CHECK-NEXT: FunctionDecl=f:21:5 =[21:5 - 21:6]
+// CHECK-NEXT: FunctionDecl=f:22:5 =[22:5 - 22:6]
+
+// RUN:   %s | FileCheck %s

Added: cfe/trunk/test/Index/file-refs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/file-refs.cpp?rev=141277&view=auto
==============================================================================
--- cfe/trunk/test/Index/file-refs.cpp (added)
+++ cfe/trunk/test/Index/file-refs.cpp Thu Oct  6 02:00:54 2011
@@ -0,0 +1,104 @@
+namespace NS {
+  class C {
+  public:
+    C() { }
+    void m();
+  };
+}
+
+void NS::C::m() {
+  C c;
+  c.m();
+}
+
+void f() {
+  NS::C c1();
+  NS::C c2 = NS::C();
+}
+
+void over(int);
+void over(float);
+
+void test_over() {
+  over(0);
+  over(0.0f);
+}
+
+template <typename T>
+T tf(T t) {
+  return t;
+}
+
+namespace Test2 {
+
+struct S {
+  S(int x, int y);
+  S();
+};
+
+typedef S Cake;
+
+void f() {
+  Cake p;
+  p = Test2::S(0,2);
+  p = Test2::Cake(0,2);
+}
+
+}
+
+// RUN: c-index-test \
+
+// RUN:  -file-refs-at=%s:9:7 \
+// CHECK:      NamespaceRef=NS:1:11
+// CHECK-NEXT: Namespace=NS:1:11 (Definition) =[1:11 - 1:13]
+// CHECK-NEXT: NamespaceRef=NS:1:11 =[9:6 - 9:8]
+// CHECK-NEXT: NamespaceRef=NS:1:11 =[15:3 - 15:5]
+// CHECK-NEXT: NamespaceRef=NS:1:11 =[16:3 - 16:5]
+// CHECK-NEXT: NamespaceRef=NS:1:11 =[16:14 - 16:16]
+
+// RUN:  -file-refs-at=%s:2:9 \
+// CHECK-NEXT: ClassDecl=C:2:9 (Definition)
+// CHECK-NEXT: ClassDecl=C:2:9 (Definition) =[2:9 - 2:10]
+// CHECK-NEXT: CXXConstructor=C:4:5 (Definition) =[4:5 - 4:6]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[9:10 - 9:11]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[10:3 - 10:4]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[15:7 - 15:8]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[16:7 - 16:8]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[16:18 - 16:19]
+
+// RUN:  -file-refs-at=%s:16:18 \
+// CHECK-NEXT: CallExpr=C:4:5
+// CHECK-NEXT: ClassDecl=C:2:9 (Definition) =[2:9 - 2:10]
+// CHECK-NEXT: CXXConstructor=C:4:5 (Definition) =[4:5 - 4:6]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[9:10 - 9:11]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[10:3 - 10:4]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[15:7 - 15:8]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[16:7 - 16:8]
+// CHECK-NEXT: TypeRef=class NS::C:2:9 =[16:18 - 16:19]
+
+// RUN:  -file-refs-at=%s:20:8 \
+// CHECK-NEXT: FunctionDecl=over:20:6
+// CHECK-NEXT: FunctionDecl=over:20:6 =[20:6 - 20:10]
+// CHECK-NEXT: DeclRefExpr=over:20:6 =[24:3 - 24:7]
+
+// RUN:  -file-refs-at=%s:28:1 \
+// CHECK-NEXT: TypeRef=T:27:20
+// FIXME: Missing TemplateTypeParameter=T:27:20 (Definition)
+// CHECK-NEXT: TypeRef=T:27:20 =[28:1 - 28:2]
+// CHECK-NEXT: TypeRef=T:27:20 =[28:6 - 28:7]
+
+// RUN:  -file-refs-at=%s:43:14 \
+// CHECK-NEXT: CallExpr=S:35:3
+// CHECK-NEXT: StructDecl=S:34:8 (Definition) =[34:8 - 34:9]
+// CHECK-NEXT: CXXConstructor=S:35:3 =[35:3 - 35:4]
+// CHECK-NEXT: CXXConstructor=S:36:3 =[36:3 - 36:4]
+// CHECK-NEXT: TypeRef=struct Test2::S:34:8 =[39:9 - 39:10]
+// CHECK-NEXT: TypeRef=struct Test2::S:34:8 =[43:14 - 43:15]
+
+// RUN:  -file-refs-at=%s:44:16 \
+// CHECK-NEXT: CallExpr=S:35:3
+// CHECK-NEXT: TypedefDecl=Cake:39:11 (Definition) =[39:11 - 39:15]
+// CHECK-NEXT: TypeRef=Cake:39:11 =[42:3 - 42:7]
+// CHECK-NEXT: TypeRef=Cake:39:11 =[44:14 - 44:18]
+
+// RUN:   %s | FileCheck %s

Added: cfe/trunk/test/Index/file-refs.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/file-refs.m?rev=141277&view=auto
==============================================================================
--- cfe/trunk/test/Index/file-refs.m (added)
+++ cfe/trunk/test/Index/file-refs.m Thu Oct  6 02:00:54 2011
@@ -0,0 +1,87 @@
+ at class Foo;
+
+ at interface Foo
+-(id)setWithInt:(int)i andFloat:(float)f;
+ at end
+
+ at implementation Foo
+-(id)setWithInt:(int)i andFloat:(float)f {
+  return self;
+}
+ at end
+
+void test(Foo *foo) {
+  [foo setWithInt:0 andFloat:0];
+  [foo setWithInt: 2 andFloat: 3];
+}
+
+ at protocol Prot1
+-(void)protMeth;
+ at end
+
+ at protocol Prot2<Prot1>
+ at end
+
+ at interface Base<Prot2>
+ at end
+
+ at interface Sub : Base
+-(void)protMeth;
+ at end
+
+ at implementation Sub
+-(void)protMeth {}
+ at end
+
+void test2(Sub *s, id<Prot1> p) {
+  [s protMeth];
+  [p protMeth];
+}
+
+
+// RUN: c-index-test \
+
+// RUN:  -file-refs-at=%s:7:18 \
+// CHECK:      ObjCImplementationDecl=Foo:7:17 (Definition)
+// CHECK-NEXT: ObjCClassRef=Foo:3:12 =[1:8 - 1:11]
+// CHECK-NEXT: ObjCInterfaceDecl=Foo:3:12 =[3:12 - 3:15]
+// CHECK-NEXT: ObjCImplementationDecl=Foo:7:17 (Definition) =[7:17 - 7:20]
+// CHECK-NEXT: ObjCClassRef=Foo:3:12 =[13:11 - 13:14]
+
+// RUN:  -file-refs-at=%s:4:10 \
+// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::4:1
+// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::4:1 =[4:6 - 4:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::8:1 (Definition) [Overrides @4:1] =[8:6 - 8:16]
+// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[14:8 - 14:18]
+// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[15:8 - 15:18]
+
+// RUN:  -file-refs-at=%s:15:27 \
+// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1
+// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::4:1 =[4:24 - 4:32]
+// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::8:1 (Definition) [Overrides @4:1] =[8:24 - 8:32]
+// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[14:21 - 14:29]
+// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[15:22 - 15:30]
+
+// RUN:  -file-refs-at=%s:18:13 \
+// CHECK-NEXT: ObjCProtocolDecl=Prot1:18:11 (Definition)
+// CHECK-NEXT: ObjCProtocolDecl=Prot1:18:11 (Definition) =[18:11 - 18:16]
+// CHECK-NEXT: ObjCProtocolRef=Prot1:18:11 =[22:17 - 22:22]
+// CHECK-NEXT: ObjCProtocolRef=Prot1:18:11 =[36:23 - 36:28]
+
+// RUN:  -file-refs-at=%s:38:10 \
+// CHECK-NEXT: ObjCMessageExpr=protMeth:19:1
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:19:1 =[19:8 - 19:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:29:1 [Overrides @19:1] =[29:8 - 29:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @29:1] =[33:8 - 33:16]
+// CHECK-NEXT: ObjCMessageExpr=protMeth:29:1 =[37:6 - 37:14]
+// CHECK-NEXT: ObjCMessageExpr=protMeth:19:1 =[38:6 - 38:14]
+
+// RUN:  -file-refs-at=%s:33:12 \
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @29:1]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:19:1 =[19:8 - 19:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:29:1 [Overrides @19:1] =[29:8 - 29:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @29:1] =[33:8 - 33:16]
+// CHECK-NEXT: ObjCMessageExpr=protMeth:29:1 =[37:6 - 37:14]
+// CHECK-NEXT: ObjCMessageExpr=protMeth:19:1 =[38:6 - 38:14]
+
+// RUN:   %s | FileCheck %s

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=141277&r1=141276&r2=141277&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Thu Oct  6 02:00:54 2011
@@ -175,7 +175,8 @@
 
 int want_display_name = 0;
 
-static void PrintCursor(CXTranslationUnit TU, CXCursor Cursor) {
+static void PrintCursor(CXCursor Cursor) {
+  CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
   if (clang_isInvalid(Cursor.kind)) {
     CXString ks = clang_getCursorKindSpelling(Cursor.kind);
     printf("Invalid Cursor => %s", clang_getCString(ks));
@@ -463,7 +464,7 @@
     clang_getSpellingLocation(Loc, 0, &line, &column, 0);
     printf("// %s: %s:%d:%d: ", FileCheckPrefix,
            GetCursorSource(Cursor), line, column);
-    PrintCursor(Data->TU, Cursor);
+    PrintCursor(Cursor);
     PrintCursorExtent(Cursor);
     printf("\n");
     return CXChildVisit_Recurse;
@@ -516,7 +517,7 @@
       } else if (Ref.kind != CXCursor_FunctionDecl) {
         printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
                curLine, curColumn);
-        PrintCursor(Data->TU, Ref);
+        PrintCursor(Ref);
         printf("\n");
       }
     }
@@ -605,7 +606,7 @@
   }
 
   if (linkage) {
-    PrintCursor(Data->TU, cursor);
+    PrintCursor(cursor);
     printf("linkage=%s\n", linkage);
   }
 
@@ -623,7 +624,7 @@
   if (!clang_isInvalid(clang_getCursorKind(cursor))) {
     CXType T = clang_getCursorType(cursor);
     CXString S = clang_getTypeKindSpelling(T.kind);
-    PrintCursor(Data->TU, cursor);
+    PrintCursor(cursor);
     printf(" typekind=%s", clang_getCString(S));
     if (clang_isConstQualifiedType(T))
       printf(" const");
@@ -836,7 +837,7 @@
     printf("-%s", prefix);
   PrintExtent(stdout, start_line, start_col, end_line, end_col);
   printf(" ");
-  PrintCursor(TU, cursor);
+  PrintCursor(cursor);
   printf("\n");
 }
 
@@ -1275,7 +1276,7 @@
   unsigned column;
 } CursorSourceLocation;
 
-int inspect_cursor_at(int argc, const char **argv) {
+static int inspect_cursor_at(int argc, const char **argv) {
   CXIndex CIdx;
   int errorCode;
   struct CXUnsavedFile *unsaved_files = 0;
@@ -1344,7 +1345,7 @@
       if (I + 1 == Repeats) {
         CXCompletionString completionString = clang_getCursorCompletionString(
                                                                         Cursor);
-        PrintCursor(TU, Cursor);
+        PrintCursor(Cursor);
         if (completionString != NULL) {
           printf("\nCompletion string: ");
           print_completion_string(completionString, stdout);
@@ -1363,6 +1364,101 @@
   return 0;
 }
 
+static enum CXVisitorResult findFileRefsVisit(void *context,
+                                         CXCursor cursor, CXSourceRange range) {
+  if (clang_Range_isNull(range))
+    return CXVisit_Continue;
+
+  PrintCursor(cursor);
+  PrintRange(range, "");
+  printf("\n");
+  return CXVisit_Continue;
+}
+
+static int find_file_refs_at(int argc, const char **argv) {
+  CXIndex CIdx;
+  int errorCode;
+  struct CXUnsavedFile *unsaved_files = 0;
+  int num_unsaved_files = 0;
+  CXTranslationUnit TU;
+  CXCursor Cursor;
+  CursorSourceLocation *Locations = 0;
+  unsigned NumLocations = 0, Loc;
+  unsigned Repeats = 1;
+  unsigned I;
+  
+  /* Count the number of locations. */
+  while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1])
+    ++NumLocations;
+
+  /* Parse the locations. */
+  assert(NumLocations > 0 && "Unable to count locations?");
+  Locations = (CursorSourceLocation *)malloc(
+                                  NumLocations * sizeof(CursorSourceLocation));
+  for (Loc = 0; Loc < NumLocations; ++Loc) {
+    const char *input = argv[Loc + 1] + strlen("-file-refs-at=");
+    if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
+                                            &Locations[Loc].line,
+                                            &Locations[Loc].column, 0, 0)))
+      return errorCode;
+  }
+
+  if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
+                           &num_unsaved_files))
+    return -1;
+
+  if (getenv("CINDEXTEST_EDITING"))
+    Repeats = 5;
+
+  /* Parse the translation unit. When we're testing clang_getCursor() after
+     reparsing, don't remap unsaved files until the second parse. */
+  CIdx = clang_createIndex(1, 1);
+  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
+                                  argv + num_unsaved_files + 1 + NumLocations,
+                                  argc - num_unsaved_files - 2 - NumLocations,
+                                  unsaved_files,
+                                  Repeats > 1? 0 : num_unsaved_files,
+                                  getDefaultParsingOptions());
+                                                 
+  if (!TU) {
+    fprintf(stderr, "unable to parse input\n");
+    return -1;
+  }
+
+  for (I = 0; I != Repeats; ++I) {
+    if (Repeats > 1 &&
+        clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, 
+                                     clang_defaultReparseOptions(TU))) {
+      clang_disposeTranslationUnit(TU);
+      return 1;
+    }
+    
+    for (Loc = 0; Loc < NumLocations; ++Loc) {
+      CXFile file = clang_getFile(TU, Locations[Loc].filename);
+      if (!file)
+        continue;
+
+      Cursor = clang_getCursor(TU,
+                               clang_getLocation(TU, file, Locations[Loc].line,
+                                                 Locations[Loc].column));
+      if (I + 1 == Repeats) {
+        PrintCursor(Cursor);
+        printf("\n");
+        CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit };
+        clang_findReferencesInFile(Cursor, file, visitor);
+        free(Locations[Loc].filename);
+      }
+    }
+  }
+  
+  PrintDiagnostics(TU);
+  clang_disposeTranslationUnit(TU);
+  clang_disposeIndex(CIdx);
+  free(Locations);
+  free_remapped_files(unsaved_files, num_unsaved_files);
+  return 0;
+}
+
 int perform_token_annotation(int argc, const char **argv) {
   const char *input = argv[1];
   char *filename = 0;
@@ -1464,7 +1560,7 @@
     PrintExtent(stdout, start_line, start_column, end_line, end_column);
     if (!clang_isInvalid(cursors[i].kind)) {
       printf(" ");
-      PrintCursor(TU, cursors[i]);
+      PrintCursor(cursors[i]);
     }
     printf("\n");
   }
@@ -1730,6 +1826,7 @@
     "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
     "       c-index-test -code-completion-timing=<site> <compiler arguments>\n"
     "       c-index-test -cursor-at=<site> <compiler arguments>\n"
+    "       c-index-test -file-refs-at=<site> <compiler arguments>\n"
     "       c-index-test -test-file-scan <AST file> <source file> "
           "[FileCheck prefix]\n"
     "       c-index-test -test-load-tu <AST file> <symbol filter> "
@@ -1776,6 +1873,8 @@
     return perform_code_completion(argc, argv, 1);
   if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])
     return inspect_cursor_at(argc, argv);
+  if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1])
+    return find_file_refs_at(argc, argv);
   else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
     CXCursorVisitor I = GetVisitor(argv[1] + 13);
     if (I)

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=141277&r1=141276&r2=141277&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Thu Oct  6 02:00:54 2011
@@ -491,7 +491,7 @@
           for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
                                         TLEnd = CXXUnit->top_level_end();
                TL != TLEnd; ++TL) {
-            if (Visit(MakeCXCursor(*TL, tu), true))
+            if (Visit(MakeCXCursor(*TL, tu, RegionOfInterest), true))
               return true;
           }
         } else if (VisitDeclContext(
@@ -534,7 +534,7 @@
         return true;
 
   if (Stmt *Body = B->getBody())
-    return Visit(MakeCXCursor(Body, StmtParent, TU));
+    return Visit(MakeCXCursor(Body, StmtParent, TU, RegionOfInterest));
 
   return false;
 }
@@ -574,7 +574,7 @@
     Decl *D = *I;
     if (D->getLexicalDeclContext() != DC)
       continue;
-    CXCursor Cursor = MakeCXCursor(D, TU);
+    CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest);
     const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
     if (!V.hasValue())
       continue;
@@ -672,7 +672,7 @@
 
 bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
   if (Expr *Init = D->getInitExpr())
-    return Visit(MakeCXCursor(Init, StmtParent, TU));
+    return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
   return false;
 }
 
@@ -767,12 +767,12 @@
         
         // Visit the initializer value.
         if (Expr *Initializer = Init->getInit())
-          if (Visit(MakeCXCursor(Initializer, ND, TU)))
+          if (Visit(MakeCXCursor(Initializer, ND, TU, RegionOfInterest)))
             return true;
       } 
     }
     
-    if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+    if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))
       return true;
   }
 
@@ -784,7 +784,7 @@
     return true;
 
   if (Expr *BitWidth = D->getBitWidth())
-    return Visit(MakeCXCursor(BitWidth, StmtParent, TU));
+    return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest));
 
   return false;
 }
@@ -794,7 +794,7 @@
     return true;
 
   if (Expr *Init = D->getInit())
-    return Visit(MakeCXCursor(Init, StmtParent, TU));
+    return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
 
   return false;
 }
@@ -805,7 +805,7 @@
   
   if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
     if (Expr *DefArg = D->getDefaultArgument())
-      return Visit(MakeCXCursor(DefArg, StmtParent, TU));
+      return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest));
   
   return false;  
 }
@@ -847,12 +847,12 @@
   for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
        PEnd = ND->param_end();
        P != PEnd; ++P) {
-    if (Visit(MakeCXCursor(*P, TU)))
+    if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))
       return true;
   }
 
   if (ND->isThisDeclarationADefinition() &&
-      Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+      Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))
     return true;
 
   return false;
@@ -926,7 +926,7 @@
   // Now visit the decls.
   for (SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(),
          E = DeclsInContainer.end(); I != E; ++I) {
-    CXCursor Cursor = MakeCXCursor(*I, TU);
+    CXCursor Cursor = MakeCXCursor(*I, TU, RegionOfInterest);
     const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
     if (!V.hasValue())
       continue;
@@ -988,12 +988,12 @@
   // the @interface.
   if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())
     if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl)
-      if (Visit(MakeCXCursor(MD, TU)))
+      if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
         return true;
 
   if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())
     if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl)
-      if (Visit(MakeCXCursor(MD, TU)))
+      if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
         return true;
 
   return false;
@@ -1246,7 +1246,7 @@
   for (TemplateParameterList::const_iterator P = Params->begin(),
                                           PEnd = Params->end();
        P != PEnd; ++P) {
-    if (Visit(MakeCXCursor(*P, TU)))
+    if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))
       return true;
   }
   
@@ -1303,12 +1303,12 @@
       
   case TemplateArgument::Declaration:
     if (Expr *E = TAL.getSourceDeclExpression())
-      return Visit(MakeCXCursor(E, StmtParent, TU));
+      return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
     return false;
       
   case TemplateArgument::Expression:
     if (Expr *E = TAL.getSourceExpression())
-      return Visit(MakeCXCursor(E, StmtParent, TU));
+      return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
     return false;
   
   case TemplateArgument::Template:
@@ -1400,7 +1400,7 @@
 
 bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
   if (TL.isDefinition())
-    return Visit(MakeCXCursor(TL.getDecl(), TU));
+    return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest));
 
   return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
 }
@@ -1468,7 +1468,7 @@
 
   for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
     if (Decl *D = TL.getArg(I))
-      if (Visit(MakeCXCursor(D, TU)))
+      if (Visit(MakeCXCursor(D, TU, RegionOfInterest)))
         return true;
 
   return false;
@@ -1479,7 +1479,7 @@
     return true;
 
   if (Expr *Size = TL.getSizeExpr())
-    return Visit(MakeCXCursor(Size, StmtParent, TU));
+    return Visit(MakeCXCursor(Size, StmtParent, TU, RegionOfInterest));
 
   return false;
 }
@@ -2070,7 +2070,7 @@
 }
 
 void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) {
-  EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU)).Visit(S);
+  EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
 }
 
 bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {
@@ -2098,7 +2098,8 @@
           continue;
 
         // For now, perform default visitation for Decls.
-        if (Visit(MakeCXCursor(D, TU, cast<DeclVisit>(&LI)->isFirst())))
+        if (Visit(MakeCXCursor(D, TU, RegionOfInterest,
+                               cast<DeclVisit>(&LI)->isFirst())))
             return true;
 
         continue;
@@ -2156,7 +2157,7 @@
           continue;
 
         // Update the current cursor.
-        CXCursor Cursor = MakeCXCursor(S, StmtParent, TU);
+        CXCursor Cursor = MakeCXCursor(S, StmtParent, TU, RegionOfInterest);
         if (!IsInRegionOfInterest(Cursor))
           continue;
         switch (Visitor(Cursor, Parent, ClientData)) {
@@ -2674,7 +2675,7 @@
 }
 
 CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
-  CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } };
+  CXCursor Result = { CXCursor_TranslationUnit, 0, { 0, 0, TU } };
   return Result;
 }
 
@@ -3616,8 +3617,12 @@
   // clang_getCursor() to point at the constructor.
   if (clang_isExpression(BestCursor->kind) &&
       isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) &&
-      cursor.kind == CXCursor_TypeRef)
+      cursor.kind == CXCursor_TypeRef) {
+    // Keep the cursor pointing at CXXTemporaryObjectExpr but also mark it
+    // as having the actual point on the type reference.
+    *BestCursor = getTypeRefedCallExprCursor(*BestCursor);
     return CXChildVisit_Recurse;
+  }
   
   *BestCursor = cursor;
   return CXChildVisit_Recurse;
@@ -4055,8 +4060,12 @@
   if (clang_isExpression(C.kind)) {
     Expr *E = getCursorExpr(C);
     Decl *D = getDeclFromExpr(E);
-    if (D)
-      return MakeCXCursor(D, tu);
+    if (D) {
+      CXCursor declCursor = MakeCXCursor(D, tu);
+      declCursor = getSelectorIdentifierCursor(getSelectorIdentifierIndex(C),
+                                               declCursor);
+      return declCursor;
+    }
     
     if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E))
       return MakeCursorOverloadedDeclRef(Ovl, tu);

Added: cfe/trunk/tools/libclang/CIndexHigh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexHigh.cpp?rev=141277&view=auto
==============================================================================
--- cfe/trunk/tools/libclang/CIndexHigh.cpp (added)
+++ cfe/trunk/tools/libclang/CIndexHigh.cpp Thu Oct  6 02:00:54 2011
@@ -0,0 +1,315 @@
+//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Index_Internal.h"
+#include "CXCursor.h"
+#include "CXSourceLocation.h"
+#include "CXTranslationUnit.h"
+
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/AST/DeclObjC.h"
+
+using namespace clang;
+
+static void getTopOverriddenMethods(CXTranslationUnit TU,
+                                    Decl *D,
+                                    SmallVectorImpl<Decl *> &Methods) {
+  if (!isa<ObjCMethodDecl>(D) && !isa<CXXMethodDecl>(D))
+    return;
+
+  SmallVector<CXCursor, 8> Overridden;
+  cxcursor::getOverriddenCursors(cxcursor::MakeCXCursor(D, TU), Overridden);
+  
+  if (Overridden.empty()) {
+    Methods.push_back(D->getCanonicalDecl());
+    return;
+  }
+
+  for (SmallVector<CXCursor, 8>::iterator
+         I = Overridden.begin(), E = Overridden.end(); I != E; ++I)
+    getTopOverriddenMethods(TU, cxcursor::getCursorDecl(*I), Methods);
+}
+
+namespace {
+
+struct FindFileIdRefVisitData {
+  CXTranslationUnit TU;
+  FileID FID;
+  Decl *Dcl;
+  int SelectorIdIdx;
+  CXCursorAndRangeVisitor visitor;
+
+  typedef SmallVector<Decl *, 8> TopMethodsTy;
+  TopMethodsTy TopMethods;
+
+  FindFileIdRefVisitData(CXTranslationUnit TU, FileID FID,
+                         Decl *D, int selectorIdIdx,
+                         CXCursorAndRangeVisitor visitor)
+    : TU(TU), FID(FID), SelectorIdIdx(selectorIdIdx), visitor(visitor) {
+    Dcl = getCanonical(D);
+    getTopOverriddenMethods(TU, Dcl, TopMethods);
+  }
+
+  ASTContext &getASTContext() const {
+    return static_cast<ASTUnit *>(TU->TUData)->getASTContext();
+  }
+
+  /// \brief We are looking to find all semantically relevant identifiers,
+  /// so the definition of "canonical" here is different than in the AST, e.g.
+  ///
+  /// \code
+  ///   class C {
+  ///     C() {}
+  ///   };
+  /// \endcode
+  ///
+  /// we consider the canonical decl of the constructor decl to be the class
+  /// itself, so both 'C' can be highlighted.
+  Decl *getCanonical(Decl *D) const {
+    D = D->getCanonicalDecl();
+
+    if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
+      return getCanonical(ImplD->getClassInterface());
+    if (CXXConstructorDecl *CXXCtorD = dyn_cast<CXXConstructorDecl>(D))
+      return getCanonical(CXXCtorD->getParent());
+    
+    return D;
+  }
+
+  bool isHit(Decl *D) const {
+    D = getCanonical(D);
+    if (D == Dcl)
+      return true;
+
+    if (isa<ObjCMethodDecl>(D) || isa<CXXMethodDecl>(D))
+      return isOverriddingMethod(D);
+
+    return false;
+  }
+
+private:
+  bool isOverriddingMethod(Decl *D) const {
+    if (std::find(TopMethods.begin(), TopMethods.end(), D) !=
+          TopMethods.end())
+      return true;
+
+    TopMethodsTy methods;
+    getTopOverriddenMethods(TU, D, methods);
+    for (TopMethodsTy::iterator
+           I = methods.begin(), E = methods.end(); I != E; ++I) {
+      if (std::find(TopMethods.begin(), TopMethods.end(), *I) !=
+            TopMethods.end())
+        return true;
+    }
+
+    return false;
+  }
+};
+
+} // end anonymous namespace.
+
+/// \brief For a macro \arg Loc, returns the file spelling location and sets
+/// to \arg isMacroArg whether the spelling resides inside a macro definition or
+/// a macro argument.
+static SourceLocation getFileSpellingLoc(SourceManager &SM,
+                                         SourceLocation Loc,
+                                         bool &isMacroArg) {
+  assert(Loc.isMacroID());
+  SourceLocation SpellLoc = SM.getImmediateSpellingLoc(Loc);
+  if (SpellLoc.isMacroID())
+    return getFileSpellingLoc(SM, SpellLoc, isMacroArg);
+  
+  isMacroArg = SM.isMacroArgExpansion(Loc);
+  return SpellLoc;
+}
+
+static enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor,
+                                                  CXCursor parent,
+                                                  CXClientData client_data) {
+  CXCursor declCursor = clang_getCursorReferenced(cursor);
+  if (!clang_isDeclaration(declCursor.kind))
+    return CXChildVisit_Recurse;
+
+  Decl *D = cxcursor::getCursorDecl(declCursor);
+  FindFileIdRefVisitData *data = (FindFileIdRefVisitData *)client_data;
+  if (data->isHit(D)) {
+    cursor = cxcursor::getSelectorIdentifierCursor(data->SelectorIdIdx, cursor);
+
+    // We are looking for identifiers to highlight so for objc methods (and
+    // not a parameter) we can only highlight the selector identifiers.
+    if ((cursor.kind == CXCursor_ObjCClassMethodDecl ||
+         cursor.kind == CXCursor_ObjCInstanceMethodDecl) &&
+         cxcursor::getSelectorIdentifierIndex(cursor) == -1)
+      return CXChildVisit_Recurse;
+
+    if (clang_isExpression(cursor.kind)) {
+      if (cursor.kind == CXCursor_DeclRefExpr ||
+          cursor.kind == CXCursor_MemberRefExpr) {
+        // continue..
+
+      } else if (cursor.kind == CXCursor_ObjCMessageExpr &&
+                 cxcursor::getSelectorIdentifierIndex(cursor) != -1) {
+        // continue..
+                
+      } else
+        return CXChildVisit_Recurse;
+    }
+
+    SourceLocation
+      Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
+    SourceLocation SelIdLoc = cxcursor::getSelectorIdentifierLoc(cursor);
+    if (SelIdLoc.isValid())
+      Loc = SelIdLoc;
+
+    SourceManager &SM = data->getASTContext().getSourceManager();
+    bool isInMacroDef = false;
+    if (Loc.isMacroID()) {
+      bool isMacroArg;
+      Loc = getFileSpellingLoc(SM, Loc, isMacroArg);
+      isInMacroDef = !isMacroArg;
+    }
+
+    // We are looking for identifiers in a specific file.
+    std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+    if (LocInfo.first != data->FID)
+      return CXChildVisit_Recurse;
+
+    if (isInMacroDef) {
+      // FIXME: For a macro definition make sure that all expansions
+      // of it expand to the same reference before allowing to point to it.
+      Loc = SourceLocation();
+    }
+
+    data->visitor.visit(data->visitor.context, cursor,
+                        cxloc::translateSourceRange(D->getASTContext(), Loc));
+  }
+  return CXChildVisit_Recurse;
+}
+
+static void findIdRefsInFile(CXTranslationUnit TU, CXCursor declCursor,
+                           const FileEntry *File,
+                           CXCursorAndRangeVisitor Visitor) {
+  assert(clang_isDeclaration(declCursor.kind));
+  ASTUnit *Unit = static_cast<ASTUnit*>(TU->TUData);
+  ASTContext &Ctx = Unit->getASTContext();
+  SourceManager &SM = Unit->getSourceManager();
+
+  FileID FID = SM.translateFile(File);
+  Decl *Dcl = cxcursor::getCursorDecl(declCursor);
+  FindFileIdRefVisitData data(TU, FID, Dcl,
+                              cxcursor::getSelectorIdentifierIndex(declCursor),
+                              Visitor);
+
+  if (DeclContext *DC = Dcl->getParentFunctionOrMethod()) {
+    clang_visitChildren(cxcursor::MakeCXCursor(cast<Decl>(DC), TU),
+                        findFileIdRefVisit, &data);
+    return;
+  }
+  
+  if (FID == SM.getMainFileID() && !Unit->isMainFileAST()) {
+    SourceLocation FileLoc = SM.getLocForStartOfFile(FID);
+    TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl();
+    CXCursor TUCursor = clang_getTranslationUnitCursor(TU);
+    for (DeclContext::decl_iterator
+           I = TUD->noload_decls_begin(), E = TUD->noload_decls_end();
+         I != E; ++I) {
+      Decl *D = *I;
+
+      SourceRange R = D->getSourceRange();
+      if (R.isInvalid())
+        continue;
+      if (SM.isBeforeInTranslationUnit(R.getEnd(), FileLoc))
+        continue;
+
+      if (TagDecl *TD = dyn_cast<TagDecl>(D))
+        if (!TD->isFreeStanding())
+          continue;
+
+      CXCursor CurCursor = cxcursor::MakeCXCursor(D, TU);
+      findFileIdRefVisit(CurCursor, TUCursor, &data);
+      clang_visitChildren(CurCursor, findFileIdRefVisit, &data);
+    }
+    return;
+  }
+
+  clang_visitChildren(clang_getTranslationUnitCursor(TU),
+                      findFileIdRefVisit, &data);
+}
+
+
+//===----------------------------------------------------------------------===//
+// libclang public APIs.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+
+void clang_findReferencesInFile(CXCursor cursor, CXFile file,
+                                CXCursorAndRangeVisitor visitor) {
+  bool Logging = ::getenv("LIBCLANG_LOGGING");
+
+  if (clang_Cursor_isNull(cursor)) {
+    if (Logging)
+      llvm::errs() << "clang_findReferencesInFile: Null cursor\n";
+    return;
+  }
+  if (!file) {
+    if (Logging)
+      llvm::errs() << "clang_findReferencesInFile: Null file\n";
+    return;
+  }
+  if (!visitor.visit) {
+    if (Logging)
+      llvm::errs() << "clang_findReferencesInFile: Null visitor\n";
+    return;
+  }
+
+  // We are interested in semantics of identifiers so for C++ constructor exprs
+  // prefer type references, e.g.:
+  //
+  //  return MyStruct();
+  //
+  // for 'MyStruct' we'll have a cursor pointing at the constructor decl but
+  // we are actually interested in the type declaration.
+  cursor = cxcursor::getTypeRefCursor(cursor);
+
+  CXCursor refCursor = clang_getCursorReferenced(cursor);
+
+  if (!clang_isDeclaration(refCursor.kind)) {
+    if (Logging)
+      llvm::errs() << "clang_findReferencesInFile: cursor is not referencing a "
+                      "declaration\n";
+    return;
+  }
+
+  ASTUnit *CXXUnit = cxcursor::getCursorASTUnit(cursor);
+  ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+  findIdRefsInFile(cxcursor::getCursorTU(cursor),
+                   refCursor,
+                   static_cast<const FileEntry *>(file),
+                   visitor);
+}
+
+static enum CXVisitorResult _visitCursorAndRange(void *context,
+                                                 CXCursor cursor,
+                                                 CXSourceRange range) {
+  CXCursorAndRangeVisitorBlock block = (CXCursorAndRangeVisitorBlock)context;
+  return INVOKE_BLOCK2(block, cursor, range);
+}
+
+void clang_findReferencesInFileWithBlock(CXCursor cursor,
+                                         CXFile file,
+                                         CXCursorAndRangeVisitorBlock block) {
+  CXCursorAndRangeVisitor visitor = { block,
+                                      block ? _visitCursorAndRange : 0 };
+  return clang_findReferencesInFile(cursor, file, visitor);
+}
+
+} // end: extern "C"
+

Modified: cfe/trunk/tools/libclang/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CMakeLists.txt?rev=141277&r1=141276&r2=141277&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CMakeLists.txt (original)
+++ cfe/trunk/tools/libclang/CMakeLists.txt Thu Oct  6 02:00:54 2011
@@ -21,6 +21,7 @@
   CIndexCXX.cpp
   CIndexCodeCompletion.cpp
   CIndexDiagnostic.cpp
+  CIndexHigh.cpp
   CIndexInclusionStack.cpp
   CIndexUSRs.cpp
   CIndexer.cpp

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=141277&r1=141276&r2=141277&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Thu Oct  6 02:00:54 2011
@@ -20,8 +20,10 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang-c/Index.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -30,7 +32,7 @@
 
 CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) {
   assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid);
-  CXCursor C = { K, { 0, 0, 0 } };
+  CXCursor C = { K, 0, { 0, 0, 0 } };
   return C;
 }
 
@@ -51,21 +53,41 @@
 CXCursor cxcursor::MakeCXCursor(const Attr *A, Decl *Parent,
                                 CXTranslationUnit TU) {
   assert(A && Parent && TU && "Invalid arguments!");
-  CXCursor C = { GetCursorKind(A), { Parent, (void*)A, TU } };
+  CXCursor C = { GetCursorKind(A), 0, { Parent, (void*)A, TU } };
   return C;
 }
 
 CXCursor cxcursor::MakeCXCursor(Decl *D, CXTranslationUnit TU,
+                                SourceRange RegionOfInterest,
                                 bool FirstInDeclGroup) {
   assert(D && TU && "Invalid arguments!");
-  CXCursor C = { getCursorKindForDecl(D),
-                 { D, (void*)(intptr_t) (FirstInDeclGroup ? 1 : 0), TU }
-               };
+
+  CXCursorKind K = getCursorKindForDecl(D);
+
+  if (K == CXCursor_ObjCClassMethodDecl ||
+      K == CXCursor_ObjCInstanceMethodDecl) {
+    int SelectorIdIndex = -1;
+    // Check if cursor points to a selector id.
+    if (RegionOfInterest.isValid() &&
+        RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) {
+      SmallVector<SourceLocation, 16> SelLocs;
+      cast<ObjCMethodDecl>(D)->getSelectorLocs(SelLocs);
+      SmallVector<SourceLocation, 16>::iterator
+        I=std::find(SelLocs.begin(), SelLocs.end(),RegionOfInterest.getBegin());
+      if (I != SelLocs.end())
+        SelectorIdIndex = I - SelLocs.begin();
+    }
+    CXCursor C = { K, SelectorIdIndex,
+                   { D, (void*)(intptr_t) (FirstInDeclGroup ? 1 : 0), TU }};
+    return C;
+  }
+  
+  CXCursor C = { K, 0, { D, (void*)(intptr_t) (FirstInDeclGroup ? 1 : 0), TU }};
   return C;
 }
 
-CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
-                                CXTranslationUnit TU) {
+CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
+                                SourceRange RegionOfInterest) {
   assert(S && TU && "Invalid arguments!");
   CXCursorKind K = CXCursor_NotImplemented;
   
@@ -408,10 +430,22 @@
       
   case Stmt::ObjCMessageExprClass:      
     K = CXCursor_ObjCMessageExpr;
-    break;
+    int SelectorIdIndex = -1;
+    // Check if cursor points to a selector id.
+    if (RegionOfInterest.isValid() &&
+        RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) {
+      SmallVector<SourceLocation, 16> SelLocs;
+      cast<ObjCMessageExpr>(S)->getSelectorLocs(SelLocs);
+      SmallVector<SourceLocation, 16>::iterator
+        I=std::find(SelLocs.begin(), SelLocs.end(),RegionOfInterest.getBegin());
+      if (I != SelLocs.end())
+        SelectorIdIndex = I - SelLocs.begin();
+    }
+    CXCursor C = { K, 0, { Parent, S, TU } };
+    return getSelectorIdentifierCursor(SelectorIdIndex, C);
   }
   
-  CXCursor C = { K, { Parent, S, TU } };
+  CXCursor C = { K, 0, { Parent, S, TU } };
   return C;
 }
 
@@ -420,7 +454,7 @@
                                                CXTranslationUnit TU) {
   assert(Super && TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_ObjCSuperClassRef, { Super, RawLoc, TU } };
+  CXCursor C = { CXCursor_ObjCSuperClassRef, 0, { Super, RawLoc, TU } };
   return C;    
 }
 
@@ -437,7 +471,7 @@
                                              CXTranslationUnit TU) {
   assert(Super && TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_ObjCProtocolRef, { Super, RawLoc, TU } };
+  CXCursor C = { CXCursor_ObjCProtocolRef, 0, { Super, RawLoc, TU } };
   return C;    
 }
 
@@ -457,7 +491,7 @@
     return MakeCXCursorInvalid(CXCursor_InvalidCode);
   assert(TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, TU } };
+  CXCursor C = { CXCursor_ObjCClassRef, 0, { Class, RawLoc, TU } };
   return C;    
 }
 
@@ -473,7 +507,7 @@
                                      CXTranslationUnit TU) {
   assert(Type && TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_TypeRef, { Type, RawLoc, TU } };
+  CXCursor C = { CXCursor_TypeRef, 0, { Type, RawLoc, TU } };
   return C;    
 }
 
@@ -490,7 +524,7 @@
                                          CXTranslationUnit TU) {
   assert(Template && TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_TemplateRef, { Template, RawLoc, TU } };
+  CXCursor C = { CXCursor_TemplateRef, 0, { Template, RawLoc, TU } };
   return C;    
 }
 
@@ -508,7 +542,7 @@
   assert(NS && (isa<NamespaceDecl>(NS) || isa<NamespaceAliasDecl>(NS)) && TU &&
          "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_NamespaceRef, { NS, RawLoc, TU } };
+  CXCursor C = { CXCursor_NamespaceRef, 0, { NS, RawLoc, TU } };
   return C;    
 }
 
@@ -525,7 +559,7 @@
   
   assert(Field && TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_MemberRef, { Field, RawLoc, TU } };
+  CXCursor C = { CXCursor_MemberRef, 0, { Field, RawLoc, TU } };
   return C;    
 }
 
@@ -539,7 +573,7 @@
 
 CXCursor cxcursor::MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B,
                                               CXTranslationUnit TU){
-  CXCursor C = { CXCursor_CXXBaseSpecifier, { B, 0, TU } };
+  CXCursor C = { CXCursor_CXXBaseSpecifier, 0, { B, 0, TU } };
   return C;  
 }
 
@@ -550,7 +584,7 @@
 
 CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range, 
                                                     CXTranslationUnit TU) {
-  CXCursor C = { CXCursor_PreprocessingDirective, 
+  CXCursor C = { CXCursor_PreprocessingDirective, 0,
                  { reinterpret_cast<void *>(Range.getBegin().getRawEncoding()),
                    reinterpret_cast<void *>(Range.getEnd().getRawEncoding()),
                    TU }
@@ -570,7 +604,7 @@
 
 CXCursor cxcursor::MakeMacroDefinitionCursor(MacroDefinition *MI,
                                              CXTranslationUnit TU) {
-  CXCursor C = { CXCursor_MacroDefinition, { MI, 0, TU } };
+  CXCursor C = { CXCursor_MacroDefinition, 0, { MI, 0, TU } };
   return C;
 }
 
@@ -581,7 +615,7 @@
 
 CXCursor cxcursor::MakeMacroExpansionCursor(MacroExpansion *MI, 
                                             CXTranslationUnit TU) {
-  CXCursor C = { CXCursor_MacroExpansion, { MI, 0, TU } };
+  CXCursor C = { CXCursor_MacroExpansion, 0, { MI, 0, TU } };
   return C;
 }
 
@@ -592,7 +626,7 @@
 
 CXCursor cxcursor::MakeInclusionDirectiveCursor(InclusionDirective *ID, 
                                                 CXTranslationUnit TU) {
-  CXCursor C = { CXCursor_InclusionDirective, { ID, 0, TU } };
+  CXCursor C = { CXCursor_InclusionDirective, 0, { ID, 0, TU } };
   return C;
 }
 
@@ -606,7 +640,7 @@
   
   assert(Label && TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
-  CXCursor C = { CXCursor_LabelRef, { Label, RawLoc, TU } };
+  CXCursor C = { CXCursor_LabelRef, 0, { Label, RawLoc, TU } };
   return C;    
 }
 
@@ -624,7 +658,7 @@
   OverloadedDeclRefStorage Storage(E);
   void *RawLoc = reinterpret_cast<void *>(E->getNameLoc().getRawEncoding());
   CXCursor C = { 
-                 CXCursor_OverloadedDeclRef, 
+                 CXCursor_OverloadedDeclRef, 0,
                  { Storage.getOpaqueValue(), RawLoc, TU } 
                };
   return C;    
@@ -637,7 +671,7 @@
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
   OverloadedDeclRefStorage Storage(D);
   CXCursor C = { 
-    CXCursor_OverloadedDeclRef, 
+    CXCursor_OverloadedDeclRef, 0,
     { Storage.getOpaqueValue(), RawLoc, TU }
   };
   return C;    
@@ -650,7 +684,7 @@
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
   OverloadedDeclRefStorage Storage(Name.getAsOverloadedTemplate());
   CXCursor C = { 
-    CXCursor_OverloadedDeclRef, 
+    CXCursor_OverloadedDeclRef, 0,
     { Storage.getOpaqueValue(), RawLoc, TU } 
   };
   return C;    
@@ -788,6 +822,87 @@
   CollectOverriddenMethods(TU, Method->getDeclContext(), Method, overridden);
 }
 
+std::pair<int, SourceLocation>
+cxcursor::getSelectorIdentifierIndexAndLoc(CXCursor cursor) {
+  if (cursor.kind == CXCursor_ObjCMessageExpr) {
+    if (cursor.xdata != -1)
+      return std::make_pair(cursor.xdata,
+                            cast<ObjCMessageExpr>(getCursorExpr(cursor))
+                                                ->getSelectorLoc(cursor.xdata));
+  } else if (cursor.kind == CXCursor_ObjCClassMethodDecl ||
+             cursor.kind == CXCursor_ObjCInstanceMethodDecl) {
+    if (cursor.xdata != -1)
+      return std::make_pair(cursor.xdata,
+                            cast<ObjCMethodDecl>(getCursorDecl(cursor))
+                                                ->getSelectorLoc(cursor.xdata));
+  }
+
+  return std::make_pair(-1, SourceLocation());
+}
+
+CXCursor cxcursor::getSelectorIdentifierCursor(int SelIdx, CXCursor cursor) {
+  CXCursor newCursor = cursor;
+
+  if (cursor.kind == CXCursor_ObjCMessageExpr) {
+    if (SelIdx == -1 ||
+        unsigned(SelIdx) >= cast<ObjCMessageExpr>(getCursorExpr(cursor))
+                                                         ->getNumSelectorLocs())
+      newCursor.xdata = -1;
+    else
+      newCursor.xdata = SelIdx;
+  } else if (cursor.kind == CXCursor_ObjCClassMethodDecl ||
+             cursor.kind == CXCursor_ObjCInstanceMethodDecl) {
+    if (SelIdx == -1 ||
+        unsigned(SelIdx) >= cast<ObjCMethodDecl>(getCursorDecl(cursor))
+                                                         ->getNumSelectorLocs())
+      newCursor.xdata = -1;
+    else
+      newCursor.xdata = SelIdx;
+  }
+
+  return newCursor;
+}
+
+CXCursor cxcursor::getTypeRefCursor(CXCursor cursor) {
+  if (cursor.kind != CXCursor_CallExpr)
+    return cursor;
+
+  if (cursor.xdata == 0)
+    return cursor;
+
+  Expr *E = getCursorExpr(cursor);
+  TypeSourceInfo *Type = 0;
+  if (CXXUnresolvedConstructExpr *
+        UnCtor = dyn_cast<CXXUnresolvedConstructExpr>(E)) {
+    Type = UnCtor->getTypeSourceInfo();
+  } else if (CXXTemporaryObjectExpr *Tmp = dyn_cast<CXXTemporaryObjectExpr>(E)){
+    Type = Tmp->getTypeSourceInfo();
+  }
+
+  if (!Type)
+    return cursor;
+
+  CXTranslationUnit TU = getCursorTU(cursor);
+  QualType Ty = Type->getType();
+  TypeLoc TL = Type->getTypeLoc();
+  SourceLocation Loc = TL.getBeginLoc();
+
+  if (const ElaboratedType *ElabT = Ty->getAs<ElaboratedType>()) {
+    Ty = ElabT->getNamedType();
+    ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(TL);
+    Loc = ElabTL.getNamedTypeLoc().getBeginLoc();
+  }
+
+  if (const TypedefType *Typedef = Ty->getAs<TypedefType>())
+    return MakeCursorTypeRef(Typedef->getDecl(), Loc, TU);
+  if (const TagType *Tag = Ty->getAs<TagType>())
+    return MakeCursorTypeRef(Tag->getDecl(), Loc, TU);
+  if (const TemplateTypeParmType *TemplP = Ty->getAs<TemplateTypeParmType>())
+    return MakeCursorTypeRef(TemplP->getDecl(), Loc, TU);
+
+  return cursor;
+}
+
 bool cxcursor::operator==(CXCursor X, CXCursor Y) {
   return X.kind == Y.kind && X.data[0] == Y.data[0] && X.data[1] == Y.data[1] &&
          X.data[2] == Y.data[2];

Modified: cfe/trunk/tools/libclang/CXCursor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.h?rev=141277&r1=141276&r2=141277&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.h (original)
+++ cfe/trunk/tools/libclang/CXCursor.h Thu Oct  6 02:00:54 2011
@@ -49,9 +49,11 @@
 CXCursor MakeCXCursor(const clang::Attr *A, clang::Decl *Parent,
                       CXTranslationUnit TU);
 CXCursor MakeCXCursor(clang::Decl *D, CXTranslationUnit TU,
+                      SourceRange RegionOfInterest = SourceRange(),
                       bool FirstInDeclGroup = true);
 CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent,
-                      CXTranslationUnit TU);
+                      CXTranslationUnit TU,
+                      SourceRange RegionOfInterest = SourceRange());
 CXCursor MakeCXCursorInvalid(CXCursorKind K);
 
 /// \brief Create an Objective-C superclass reference at the given location.
@@ -195,6 +197,27 @@
 void getOverriddenCursors(CXCursor cursor,
                           SmallVectorImpl<CXCursor> &overridden); 
 
+/// \brief Returns a index/location pair for a selector identifier if the cursor
+/// points to one.
+std::pair<int, SourceLocation> getSelectorIdentifierIndexAndLoc(CXCursor);
+static inline int getSelectorIdentifierIndex(CXCursor cursor) {
+  return getSelectorIdentifierIndexAndLoc(cursor).first;
+}
+static inline SourceLocation getSelectorIdentifierLoc(CXCursor cursor) {
+  return getSelectorIdentifierIndexAndLoc(cursor).second;
+}
+
+CXCursor getSelectorIdentifierCursor(int SelIdx, CXCursor cursor);
+
+static inline CXCursor getTypeRefedCallExprCursor(CXCursor cursor) {
+  CXCursor newCursor = cursor;
+  if (cursor.kind == CXCursor_CallExpr)
+    newCursor.xdata = 1;
+  return newCursor;
+}
+
+CXCursor getTypeRefCursor(CXCursor cursor);
+
 bool operator==(CXCursor X, CXCursor Y);
   
 inline bool operator!=(CXCursor X, CXCursor Y) {

Added: cfe/trunk/tools/libclang/Index_Internal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Index_Internal.h?rev=141277&view=auto
==============================================================================
--- cfe/trunk/tools/libclang/Index_Internal.h (added)
+++ cfe/trunk/tools/libclang/Index_Internal.h Thu Oct  6 02:00:54 2011
@@ -0,0 +1,43 @@
+//===- CXString.h - Routines for manipulating CXStrings -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXStrings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBCLANG_INDEX_INTERNAL_H
+#define LLVM_LIBCLANG_INDEX_INTERNAL_H
+
+#include "clang-c/Index.h"
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+#if __has_feature(blocks)
+
+#define INVOKE_BLOCK2(block, arg1, arg2) block(arg1, arg2)
+
+#else
+// If we are compiled with a compiler that doesn't have native blocks support,
+// define and call the block manually. 
+
+#define INVOKE_BLOCK2(block, arg1, arg2) block->invoke(block, arg1, arg2)
+
+typedef struct _CXCursorAndRangeVisitorBlock {
+  void *isa;
+  int flags;
+  int reserved;
+  enum CXVisitorResult (*invoke)(_CXCursorAndRangeVisitorBlock *,
+                                 CXCursor, CXSourceRange);
+} *CXCursorAndRangeVisitorBlock;
+
+#endif // !__has_feature(blocks)
+
+#endif

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=141277&r1=141276&r2=141277&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Thu Oct  6 02:00:54 2011
@@ -42,6 +42,8 @@
 clang_equalRanges
 clang_equalTypes
 clang_executeOnThread
+clang_findReferencesInFile
+clang_findReferencesInFileWithBlock
 clang_formatDiagnostic
 clang_getArrayElementType
 clang_getArraySize





More information about the cfe-commits mailing list