]> granicus.if.org Git - clang/commitdiff
Better support USRs for anonymous enums, structs, by including the location where
authorTed Kremenek <kremenek@apple.com>
Thu, 15 Apr 2010 21:51:13 +0000 (21:51 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 15 Apr 2010 21:51:13 +0000 (21:51 +0000)
the tag was declared.  WIP.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101403 91177308-0d34-0410-b5e6-96231b3b80d8

tools/CIndex/CIndexUSRs.cpp

index 2c38047fef313dadf74675e6a6f6b05926e82007..3196fd74633a606612096b76cf1779044bca6764 100644 (file)
 #include "CIndexer.h"
 #include "CXCursor.h"
 #include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
+
 using namespace clang;
 using namespace clang::cxstring;
 
@@ -48,6 +50,10 @@ public:
   void VisitTagDecl(TagDecl *D);
   void VisitTypedefDecl(TypedefDecl *D);
 
+  /// Generate the string component containing the location of the
+  ///  declaration.
+  void GenLoc(const Decl *D);
+
   /// String generation methods used both by the visitation methods
   /// and from other clients that want to directly generate USRs.  These
   /// methods do not construct complete USRs (which incorporate the parents
@@ -198,6 +204,7 @@ void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
 }
 
 void USRGenerator::VisitTagDecl(TagDecl *D) {
+  D = D->getCanonicalDecl();
   VisitDeclContext(D->getDeclContext());
   switch (D->getTagKind()) {
     case TagDecl::TK_struct: Out << "@S^"; break;
@@ -206,7 +213,14 @@ void USRGenerator::VisitTagDecl(TagDecl *D) {
     case TagDecl::TK_enum:   Out << "@E^"; break;
   }
 
-  // FIXME: Better support for anonymous structures and enums.
+  // Add the location of the tag decl to handle resolution across
+  // translation units.
+  if (D->getLinkage() == NoLinkage) {
+    GenLoc(D);
+    if (IgnoreResults)
+      return;
+  }
+
   const std::string &s = D->getNameAsString();
   if (s.empty()) {
     if (TypedefDecl *TD = D->getTypedefForAnonDecl())
@@ -222,7 +236,31 @@ void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
   DeclContext *DC = D->getDeclContext();
   if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
     Visit(DCN);
-  Out << "typedef@" << D->getName();
+  Out << "typedef@";
+  GenLoc(D);
+  Out << D->getName();
+}
+
+void USRGenerator::GenLoc(const Decl *D) {
+  const SourceManager &SM = AU->getSourceManager();
+  SourceLocation L = D->getLocStart();
+  if (L.isInvalid()) {
+    IgnoreResults = true;
+    return;
+  }
+  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();
+  else {
+    // This case really isn't interesting.
+    IgnoreResults = true;
+    return;
+  }
+  Out << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':'
+      << SM.getColumnNumber(Decomposed.first, Decomposed.second)
+      << '^';
 }
 
 //===----------------------------------------------------------------------===//
@@ -282,7 +320,8 @@ static CXString getDeclCursorUSR(const CXCursor &C) {
         // (e.g., the header).  This is a little gross, but in principal
         // enums/anonymous structs/etc. defined in a common header file
         // are referred to across multiple translation units.
-        if (isa<TagDecl>(ND))
+        if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
+            isa<EnumConstantDecl>(ND))
           break;
         // Fall-through.
       case InternalLinkage: