From: Ted Kremenek Date: Thu, 15 Apr 2010 21:51:13 +0000 (+0000) Subject: Better support USRs for anonymous enums, structs, by including the location where X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f153956158a2780c46872a8e987a8dc66b5f76a;p=clang Better support USRs for anonymous enums, structs, by including the location where the tag was declared. WIP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101403 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp index 2c38047fef..3196fd7463 100644 --- a/tools/CIndex/CIndexUSRs.cpp +++ b/tools/CIndex/CIndexUSRs.cpp @@ -14,9 +14,11 @@ #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(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 &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(ND)) + if (isa(ND) || isa(ND) || + isa(ND)) break; // Fall-through. case InternalLinkage: