diff options
-rw-r--r-- | test/Index/usrs.m | 74 | ||||
-rw-r--r-- | tools/CIndex/CIndexUSRs.cpp | 36 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 7 |
3 files changed, 112 insertions, 5 deletions
diff --git a/test/Index/usrs.m b/test/Index/usrs.m new file mode 100644 index 0000000000..28771aebc1 --- /dev/null +++ b/test/Index/usrs.m @@ -0,0 +1,74 @@ +// RUN: c-index-test -test-load-source-usrs all %s | FileCheck %s + +enum { + ABA, + CADABA +}; + +enum { + FOO, + BAR +}; + +typedef struct { + int wa; + int moo; +} MyStruct; + +enum Pizza { + CHEESE, + MUSHROOMS +}; + +@interface Foo { + id x; + id y; +} +- (id) godzilla; ++ (id) kingkong; +@property int d1; +@end + +@implementation Foo +- (id) godzilla { + static int a = 0; + extern int z; + return 0; +} ++ (id) kingkong { + return 0; +} +@synthesize d1; +@end + +int z; + +// CHECK: usrs.m c:@Ea@usrs.m@3:1 Extent=[3:1 - 6:2] +// CHECK: usrs.m c:@Ea@usrs.m@3:1@ABA Extent=[4:3 - 4:6] +// CHECK: usrs.m c:@Ea@usrs.m@3:1@CADABA Extent=[5:3 - 5:9] +// CHECK: usrs.m c:@Ea@usrs.m@8:1 Extent=[8:1 - 11:2] +// CHECK: usrs.m c:@Ea@usrs.m@8:1@FOO Extent=[9:3 - 9:6] +// CHECK: usrs.m c:@Ea@usrs.m@8:1@BAR Extent=[10:3 - 10:6] +// CHECK: usrs.m c:@SA@MyStruct Extent=[13:9 - 16:2] +// CHECK: usrs.m c:@SA@MyStruct@FI@wa Extent=[14:7 - 14:9] +// CHECK: usrs.m c:@SA@MyStruct@FI@moo Extent=[15:7 - 15:10] +// CHECK: usrs.m c:@T@usrs.m@16:3@MyStruct Extent=[16:3 - 16:11] +// CHECK: usrs.m c:@E@Pizza Extent=[18:1 - 21:2] +// CHECK: usrs.m c:@E@Pizza@CHEESE Extent=[19:3 - 19:9] +// CHECK: usrs.m c:@E@Pizza@MUSHROOMS Extent=[20:3 - 20:12] +// CHECK: usrs.m c:objc(cs)Foo Extent=[23:1 - 30:5] +// CHECK: usrs.m c:objc(cs)Foo@x Extent=[24:6 - 24:7] +// CHECK: usrs.m c:objc(cs)Foo@y Extent=[25:6 - 25:7] +// CHECK: usrs.m c:objc(cs)Foo(py)d1 Extent=[29:15 - 29:17] +// CHECK: usrs.m c:objc(cs)Foo(im)godzilla Extent=[27:1 - 27:17] +// CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[28:1 - 28:17] +// CHECK: usrs.m c:objc(cs)Foo(im)d1 Extent=[29:15 - 29:17] +// CHECK: usrs.m c:objc(cs)Foo(im)setD1: Extent=[29:15 - 29:17] +// CHECK: usrs.m c:objc(cs)Foo Extent=[32:1 - 42:2] +// CHECK: usrs.m c:objc(cs)Foo(im)godzilla Extent=[33:1 - 37:2] +// CHECK: usrs.m c:@z Extent=[35:10 - 35:15] +// CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[38:1 - 40:2] +// CHECK: usrs.m c:objc(cs)Foo@d1 Extent=[41:13 - 41:15] +// CHECK: usrs.m c:objc(cs)Foo(py)d1 Extent=[41:1 - 41:15] +// CHECK: usrs.m c:@z Extent=[44:1 - 44:6] + diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp index d67f97a5a6..58870b930b 100644 --- a/tools/CIndex/CIndexUSRs.cpp +++ b/tools/CIndex/CIndexUSRs.cpp @@ -46,11 +46,13 @@ public: void VisitNamespaceDecl(NamespaceDecl *D); void VisitObjCClassDecl(ObjCClassDecl *CD); void VisitObjCContainerDecl(ObjCContainerDecl *CD); - void VisitObjCMethodDecl(ObjCMethodDecl *MD); void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P); + void VisitObjCMethodDecl(ObjCMethodDecl *MD); void VisitObjCPropertyDecl(ObjCPropertyDecl *D); + void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); void VisitTagDecl(TagDecl *D); void VisitTypedefDecl(TypedefDecl *D); + void VisitVarDecl(VarDecl *D); /// Generate the string component containing the location of the /// declaration. @@ -132,7 +134,7 @@ void USRGenerator::VisitFieldDecl(FieldDecl *D) { return; } VisitDeclContext(D->getDeclContext()); - Out << "@FI@" << s; + Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@") << s; } void USRGenerator::VisitFunctionDecl(FunctionDecl *D) { @@ -153,6 +155,24 @@ void USRGenerator::VisitNamedDecl(NamedDecl *D) { GenNamedDecl(s); } +void USRGenerator::VisitVarDecl(VarDecl *D) { + // VarDecls can be declared 'extern' within a function or method body, + // but their enclosing DeclContext is the function, not the TU. We need + // to check the storage class to correctly generate the USR. + if (!D->hasExternalStorage()) + VisitDeclContext(D->getDeclContext()); + + const std::string &s = D->getNameAsString(); + // The string can be empty if the declaration has no name; e.g., it is + // the ParmDecl with no name for declaration of a function pointer type, e.g.: + // void (*f)(void *); + // In this case, don't generate a USR. + if (s.empty()) + IgnoreResults = true; + else + GenNamedDecl(s); +} + void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) { VisitDeclContext(D->getDeclContext()); Out << "@N@" << D; @@ -223,6 +243,15 @@ void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { GenObjCProperty(D->getName()); } +void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { + if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { + VisitObjCPropertyDecl(PD); + return; + } + + IgnoreResults = true; +} + void USRGenerator::VisitTagDecl(TagDecl *D) { D = D->getCanonicalDecl(); VisitDeclContext(D->getDeclContext()); @@ -369,6 +398,9 @@ static CXString getDeclCursorUSR(const CXCursor &C) { if (SUG->ignoreResults()) return createCXString(""); + // For development testing. + // assert(SUG.str().size() > 2); + // Return a copy of the string that must be disposed by the caller. return createCXString(SUG.str(), true); } diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index c15b69cb1c..494181675c 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -372,12 +372,13 @@ enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent, VisitorData *Data = (VisitorData *)ClientData; if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) { CXString USR = clang_getCursorUSR(C); - if (!clang_getCString(USR)) { + const char *cstr = clang_getCString(USR); + if (!cstr || cstr[0] == '\0') { clang_disposeString(USR); return CXChildVisit_Recurse; } - printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), - clang_getCString(USR)); + printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), cstr); + PrintCursorExtent(C); printf("\n"); clang_disposeString(USR); |