From e74ef1289d5fff0a6ea573198bf354fa8cd84d51 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 16 Apr 2010 21:31:52 +0000 Subject: [PATCH] Rework USR generation for symbols with no linkage. Many of the USRs are now shortened, and we now include the file name that declares the symbol with no linkage in the USR. USRs for such symbols are generated only in restructed cases, e.g., anonymous enum declarations, typedefs, etc. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101542 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Index/print-usrs.c | 4 +- tools/CIndex/CIndexUSRs.cpp | 92 +++++++++++++++++++++---------- tools/c-index-test/c-index-test.c | 2 +- 3 files changed, 67 insertions(+), 31 deletions(-) diff --git a/test/Index/print-usrs.c b/test/Index/print-usrs.c index 9cd64f786e..898778b11e 100644 --- a/test/Index/print-usrs.c +++ b/test/Index/print-usrs.c @@ -8,8 +8,8 @@ ObjCMethod baz:with 1 c:objc(cs)NSObject ObjCProperty gimme c:objc(cs)NSObject ObjCProtocol blah // CHECK: c:objc(cs)NSObject -// CHECK: c:objc(cy)NSObject^foo -// CHECK: c:objc(cs)NSObject@^x +// CHECK: c:objc(cy)NSObject@foo +// CHECK: c:objc(cs)NSObject@x // CHECK: c:objc(cs)NSObject(cm)foo: // CHECK: c:objc(cs)NSObject(im)baz:with // CHECK: c:objc(cs)NSObject(py)gimme diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp index 3196fd7463..b35ca0bcaf 100644 --- a/tools/CIndex/CIndexUSRs.cpp +++ b/tools/CIndex/CIndexUSRs.cpp @@ -44,8 +44,10 @@ public: void VisitFunctionDecl(FunctionDecl *D); void VisitNamedDecl(NamedDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); + void VisitObjCClassDecl(ObjCClassDecl *CD); void VisitObjCContainerDecl(ObjCContainerDecl *CD); void VisitObjCMethodDecl(ObjCMethodDecl *MD); + void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P); void VisitObjCPropertyDecl(ObjCPropertyDecl *D); void VisitTagDecl(TagDecl *D); void VisitTypedefDecl(TypedefDecl *D); @@ -114,7 +116,7 @@ public: void USRGenerator::VisitBlockDecl(BlockDecl *D) { VisitDeclContext(D->getDeclContext()); // FIXME: Better support for anonymous blocks. - Out << "@B^anon"; + Out << "@B@anon"; } void USRGenerator::VisitDeclContext(DeclContext *DC) { @@ -130,24 +132,30 @@ void USRGenerator::VisitFieldDecl(FieldDecl *D) { return; } VisitDeclContext(D->getDeclContext()); - Out << "@^FI^" << s; + Out << "@FI@" << s; } void USRGenerator::VisitFunctionDecl(FunctionDecl *D) { VisitDeclContext(D->getDeclContext()); - Out << "@F^" << D->getNameAsString(); + Out << "@F@" << D->getNameAsString(); } void USRGenerator::VisitNamedDecl(NamedDecl *D) { VisitDeclContext(D->getDeclContext()); const std::string &s = D->getNameAsString(); - // assert(!s.empty()); - GenNamedDecl(s); + // 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->getNameAsString(); + Out << "@N@" << D->getNameAsString(); } void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) { @@ -156,6 +164,18 @@ void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) { D->isInstanceMethod()); } +void USRGenerator::VisitObjCClassDecl(ObjCClassDecl *D) { + // FIXME: @class declarations can refer to multiple classes. We need + // to be able to traverse these. + IgnoreResults = true; +} + +void USRGenerator::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { + // FIXME: @protocol declarations can refer to multiple protocols. We need + // to be able to traverse these. + IgnoreResults = true; +} + void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { switch (D->getKind()) { default: @@ -207,37 +227,47 @@ void USRGenerator::VisitTagDecl(TagDecl *D) { D = D->getCanonicalDecl(); VisitDeclContext(D->getDeclContext()); switch (D->getTagKind()) { - case TagDecl::TK_struct: Out << "@S^"; break; - case TagDecl::TK_class: Out << "@C^"; break; - case TagDecl::TK_union: Out << "@U^"; break; - case TagDecl::TK_enum: Out << "@E^"; break; + case TagDecl::TK_struct: Out << "@S"; break; + case TagDecl::TK_class: Out << "@C"; break; + case TagDecl::TK_union: Out << "@U"; break; + case TagDecl::TK_enum: Out << "@E"; break; + } + + const std::string &s = D->getNameAsString(); + const TypedefDecl *TD = 0; + if (s.empty()) { + TD = D->getTypedefForAnonDecl(); + Out << (TD ? 'A' : 'a'); } // Add the location of the tag decl to handle resolution across // translation units. if (D->getLinkage() == NoLinkage) { + Out << '@'; GenLoc(D); if (IgnoreResults) return; } - const std::string &s = D->getNameAsString(); if (s.empty()) { - if (TypedefDecl *TD = D->getTypedefForAnonDecl()) - Out << "^anontd^" << TD->getNameAsString(); - else - Out << "^anon"; + if (TD) + Out << '@' << TD->getNameAsString(); } else - Out << s; + Out << '@' << s; } void USRGenerator::VisitTypedefDecl(TypedefDecl *D) { DeclContext *DC = D->getDeclContext(); if (NamedDecl *DCN = dyn_cast(DC)) Visit(DCN); - Out << "typedef@"; - GenLoc(D); + Out << "@T@"; + if (D->getLinkage() == NoLinkage) { + GenLoc(D); + if (IgnoreResults) + return; + Out << '@'; + } Out << D->getName(); } @@ -251,16 +281,18 @@ void USRGenerator::GenLoc(const Decl *D) { L = SM.getInstantiationLoc(L); const std::pair &Decomposed = SM.getDecomposedLoc(L); const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); - if (FE) - Out << FE->getName(); + if (FE) { + llvm::sys::Path P(FE->getName()); + Out << P.getLast(); + } else { // This case really isn't interesting. IgnoreResults = true; return; } - Out << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':' - << SM.getColumnNumber(Decomposed.first, Decomposed.second) - << '^'; + Out << '@' + << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':' + << SM.getColumnNumber(Decomposed.first, Decomposed.second); } //===----------------------------------------------------------------------===// @@ -268,7 +300,7 @@ void USRGenerator::GenLoc(const Decl *D) { //===----------------------------------------------------------------------===// void USRGenerator::GenNamedDecl(llvm::StringRef name) { - Out << "@^" << name; + Out << "@" << name; } void USRGenerator::GenObjCClass(llvm::StringRef cls) { @@ -276,7 +308,7 @@ void USRGenerator::GenObjCClass(llvm::StringRef cls) { } void USRGenerator::GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat) { - Out << "objc(cy)" << cls << '^' << cat; + Out << "objc(cy)" << cls << '@' << cat; } void USRGenerator::GenObjCIvar(llvm::StringRef ivar) { @@ -305,11 +337,13 @@ static inline llvm::StringRef extractUSRSuffix(llvm::StringRef s) { static CXString getDeclCursorUSR(const CXCursor &C) { Decl *D = cxcursor::getCursorDecl(C); - if (!D) + + // Don't generate USRs for things with invalid locations. + if (!D || D->getLocStart().isInvalid()) return createCXString(NULL); // Check if the cursor has 'NoLinkage'. - if (const NamedDecl *ND = dyn_cast_or_null(D)) + if (const NamedDecl *ND = dyn_cast(D)) switch (ND->getLinkage()) { case ExternalLinkage: // Generate USRs for all entities with external linkage. @@ -321,7 +355,7 @@ static CXString getDeclCursorUSR(const CXCursor &C) { // enums/anonymous structs/etc. defined in a common header file // are referred to across multiple translation units. if (isa(ND) || isa(ND) || - isa(ND)) + isa(ND) || isa(ND)) break; // Fall-through. case InternalLinkage: @@ -335,6 +369,8 @@ static CXString getDeclCursorUSR(const CXCursor &C) { if (SUG->ignoreResults()) return createCXString(""); + assert(SUG.str().size() > 3); + // 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 d7f3483ffb..c15b69cb1c 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -374,7 +374,7 @@ enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent, CXString USR = clang_getCursorUSR(C); if (!clang_getCString(USR)) { clang_disposeString(USR); - return CXChildVisit_Continue; + return CXChildVisit_Recurse; } printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), clang_getCString(USR)); -- 2.40.0