]> granicus.if.org Git - clang/commitdiff
Rework USR generation for symbols with no linkage. Many of the USRs are now shortened,
authorTed Kremenek <kremenek@apple.com>
Fri, 16 Apr 2010 21:31:52 +0000 (21:31 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 16 Apr 2010 21:31:52 +0000 (21:31 +0000)
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
tools/CIndex/CIndexUSRs.cpp
tools/c-index-test/c-index-test.c

index 9cd64f786e6cbcdea691d0094ec27dc3a91b5dcc..898778b11e7d1ce8a7edb86f9db14015a1a7e49c 100644 (file)
@@ -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
index 3196fd74633a606612096b76cf1779044bca6764..b35ca0bcaf62d04740620970c3b910bec4170a22 100644 (file)
@@ -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<NamedDecl>(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<FileID, unsigned> &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<NamedDecl>(D))
+  if (const NamedDecl *ND = dyn_cast<NamedDecl>(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<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
-            isa<EnumConstantDecl>(ND))
+            isa<EnumConstantDecl>(ND) || isa<FieldDecl>(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);
 }
index d7f3483ffbfd27cd1d3dd5559ca65931ddb7308f..c15b69cb1c064075fd08a1de93a2d4aa3b6dbf48 100644 (file)
@@ -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));