mirror of https://github.com/microsoft/clang.git
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141277 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b11be041e4
commit
aed123ec3c
|
@ -1857,6 +1857,7 @@ enum CXCursorKind {
|
|||
*/
|
||||
typedef struct {
|
||||
enum CXCursorKind kind;
|
||||
int xdata;
|
||||
void *data[3];
|
||||
} CXCursor;
|
||||
|
||||
|
@ -3775,6 +3776,53 @@ CINDEX_LINKAGE void clang_remap_getFilenames(CXRemapping, unsigned index,
|
|||
*/
|
||||
CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** \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
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,87 @@
|
|||
@class Foo;
|
||||
|
||||
@interface Foo
|
||||
-(id)setWithInt:(int)i andFloat:(float)f;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
-(id)setWithInt:(int)i andFloat:(float)f {
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
void test(Foo *foo) {
|
||||
[foo setWithInt:0 andFloat:0];
|
||||
[foo setWithInt: 2 andFloat: 3];
|
||||
}
|
||||
|
||||
@protocol Prot1
|
||||
-(void)protMeth;
|
||||
@end
|
||||
|
||||
@protocol Prot2<Prot1>
|
||||
@end
|
||||
|
||||
@interface Base<Prot2>
|
||||
@end
|
||||
|
||||
@interface Sub : Base
|
||||
-(void)protMeth;
|
||||
@end
|
||||
|
||||
@implementation Sub
|
||||
-(void)protMeth {}
|
||||
@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
|
|
@ -175,7 +175,8 @@ static void PrintRange(CXSourceRange R, const char *str) {
|
|||
|
||||
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 @@ enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
|
|||
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 @@ static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor,
|
|||
} 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 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p,
|
|||
}
|
||||
|
||||
if (linkage) {
|
||||
PrintCursor(Data->TU, cursor);
|
||||
PrintCursor(cursor);
|
||||
printf("linkage=%s\n", linkage);
|
||||
}
|
||||
|
||||
|
@ -623,7 +624,7 @@ static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p,
|
|||
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 @@ static void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor,
|
|||
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 @@ typedef struct {
|
|||
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 @@ int inspect_cursor_at(int argc, const char **argv) {
|
|||
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 @@ int inspect_cursor_at(int argc, const char **argv) {
|
|||
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 @@ int perform_token_annotation(int argc, const char **argv) {
|
|||
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 @@ static void print_usage(void) {
|
|||
"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 @@ int cindextest_main(int argc, const char **argv) {
|
|||
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)
|
||||
|
|
|
@ -491,7 +491,7 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
|
|||
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 @@ bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
|
|||
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 @@ bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
|
|||
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::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
|
|||
|
||||
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 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
|
|||
|
||||
// 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 @@ bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
|
|||
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 @@ bool CursorVisitor::VisitVarDecl(VarDecl *D) {
|
|||
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 @@ bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
|||
|
||||
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 @@ bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
|
|||
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 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
|
|||
// 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 @@ bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {
|
|||
// 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 @@ bool CursorVisitor::VisitTemplateParameters(
|
|||
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 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
|
|||
|
||||
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::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
|
|||
|
||||
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 @@ bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
|
|||
|
||||
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 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
|
|||
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 EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
|
|||
}
|
||||
|
||||
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 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
|
|||
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 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
|
|||
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 @@ CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
|
|||
}
|
||||
|
||||
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 @@ static enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
|
|||
// 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 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
|
|||
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);
|
||||
|
|
|
@ -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"
|
||||
|
|
@ -21,6 +21,7 @@ set(SOURCES
|
|||
CIndexCXX.cpp
|
||||
CIndexCodeCompletion.cpp
|
||||
CIndexDiagnostic.cpp
|
||||
CIndexHigh.cpp
|
||||
CIndexInclusionStack.cpp
|
||||
CIndexUSRs.cpp
|
||||
CIndexer.cpp
|
||||
|
|
|
@ -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 @@ using namespace cxcursor;
|
|||
|
||||
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 @@ static CXCursorKind GetCursorKind(const Attr *A) {
|
|||
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 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
|
|||
|
||||
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 @@ CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
|
|||
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 @@ CXCursor cxcursor::MakeCursorObjCProtocolRef(ObjCProtocolDecl *Super,
|
|||
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 @@ CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class,
|
|||
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 @@ CXCursor cxcursor::MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc,
|
|||
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 @@ CXCursor cxcursor::MakeCursorTemplateRef(TemplateDecl *Template,
|
|||
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 @@ CXCursor cxcursor::MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc,
|
|||
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 @@ CXCursor cxcursor::MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc,
|
|||
|
||||
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::getCursorMemberRef(CXCursor C) {
|
|||
|
||||
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 @@ CXXBaseSpecifier *cxcursor::getCursorCXXBaseSpecifier(CXCursor C) {
|
|||
|
||||
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 @@ SourceRange cxcursor::getCursorPreprocessingDirective(CXCursor C) {
|
|||
|
||||
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 @@ MacroDefinition *cxcursor::getCursorMacroDefinition(CXCursor C) {
|
|||
|
||||
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 @@ MacroExpansion *cxcursor::getCursorMacroExpansion(CXCursor C) {
|
|||
|
||||
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 @@ CXCursor cxcursor::MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc,
|
|||
|
||||
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 @@ CXCursor cxcursor::MakeCursorOverloadedDeclRef(OverloadExpr *E,
|
|||
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 @@ CXCursor cxcursor::MakeCursorOverloadedDeclRef(Decl *D,
|
|||
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 @@ CXCursor cxcursor::MakeCursorOverloadedDeclRef(TemplateName Name,
|
|||
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 @@ void cxcursor::getOverriddenCursors(CXCursor cursor,
|
|||
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];
|
||||
|
|
|
@ -49,9 +49,11 @@ CXCursor getCursor(CXTranslationUnit, SourceLocation);
|
|||
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 @@ CXTranslationUnit getCursorTU(CXCursor Cursor);
|
|||
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) {
|
||||
|
|
|
@ -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
|
|
@ -42,6 +42,8 @@ clang_equalLocations
|
|||
clang_equalRanges
|
||||
clang_equalTypes
|
||||
clang_executeOnThread
|
||||
clang_findReferencesInFile
|
||||
clang_findReferencesInFileWithBlock
|
||||
clang_formatDiagnostic
|
||||
clang_getArrayElementType
|
||||
clang_getArraySize
|
||||
|
|
Loading…
Reference in New Issue