From 7ac8837d4ab171d6bee0b9d0109d48f44830848d Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Fri, 28 Mar 2014 22:21:26 +0000 Subject: [PATCH] libclang/libIndex: USR generation: mangle source location into USRs for macros, unless the macro comes from a system header git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205064 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Index/USRGeneration.h | 12 ++++- lib/Index/USRGeneration.cpp | 77 ++++++++++++++++++++--------- test/Index/Inputs/usrs-system.h | 1 + test/Index/usrs.m | 27 +++++++++- tools/libclang/CIndexUSRs.cpp | 16 ++++-- 5 files changed, 101 insertions(+), 32 deletions(-) create mode 100644 test/Index/Inputs/usrs-system.h diff --git a/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h index 7b0fd5063a..3195dee750 100644 --- a/include/clang/Index/USRGeneration.h +++ b/include/clang/Index/USRGeneration.h @@ -14,7 +14,9 @@ #include "llvm/ADT/StringRef.h" namespace clang { - class Decl; +class Decl; +class MacroDefinition; +class SourceManager; namespace index { @@ -22,7 +24,7 @@ static inline StringRef getUSRSpacePrefix() { return "c:"; } -/// \brief Generate a USR for a Decl, including the prefix. +/// \brief Generate a USR for a Decl, including the USR prefix. /// \returns true if the results should be ignored, false otherwise. bool generateUSRForDecl(const Decl *D, SmallVectorImpl &Buf); @@ -47,6 +49,12 @@ void generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS); /// \brief Generate a USR fragment for an Objective-C protocol. void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS); +/// \brief Generate a USR for a macro, including the USR prefix. +/// +/// \returns true on error, false on success. +bool generateUSRForMacro(const MacroDefinition *MD, const SourceManager &SM, + SmallVectorImpl &Buf); + } // namespace index } // namespace clang diff --git a/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp index b3ab9de4d3..15aa87555e 100644 --- a/lib/Index/USRGeneration.cpp +++ b/lib/Index/USRGeneration.cpp @@ -11,6 +11,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" +#include "clang/Lex/PreprocessingRecord.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -22,6 +23,30 @@ using namespace clang::index; // USR generation. //===----------------------------------------------------------------------===// +/// \returns true on error. +static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, + const SourceManager &SM, bool IncludeOffset) { + if (Loc.isInvalid()) { + return true; + } + Loc = SM.getExpansionLoc(Loc); + const std::pair &Decomposed = SM.getDecomposedLoc(Loc); + const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); + if (FE) { + OS << llvm::sys::path::filename(FE->getName()); + } else { + // This case really isn't interesting. + return true; + } + if (IncludeOffset) { + // Use the offest into the FileID to represent the location. Using + // a line/column can cause us to look back at the original source file, + // which is expensive. + OS << '@' << Decomposed.second; + } + return false; +} + namespace { class USRGenerator : public ConstDeclVisitor { SmallVectorImpl &Buf; @@ -465,7 +490,7 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { if (generatedLoc) return IgnoreResults; generatedLoc = true; - + // Guard against null declarations in invalid code. if (!D) { IgnoreResults = true; @@ -475,29 +500,10 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { // Use the location of canonical decl. D = D->getCanonicalDecl(); - const SourceManager &SM = Context->getSourceManager(); - SourceLocation L = D->getLocStart(); - if (L.isInvalid()) { - IgnoreResults = true; - return true; - } - L = SM.getExpansionLoc(L); - const std::pair &Decomposed = SM.getDecomposedLoc(L); - const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); - if (FE) { - Out << llvm::sys::path::filename(FE->getName()); - } - else { - // This case really isn't interesting. - IgnoreResults = true; - return true; - } - if (IncludeOffset) { - // Use the offest into the FileID to represent the location. Using - // a line/column can cause us to look back at the original source file, - // which is expensive. - Out << '@' << Decomposed.second; - } + IgnoreResults = + IgnoreResults || printLoc(Out, D->getLocStart(), + Context->getSourceManager(), IncludeOffset); + return IgnoreResults; } @@ -799,3 +805,26 @@ bool clang::index::generateUSRForDecl(const Decl *D, UG.Visit(D); return UG.ignoreResults(); } + +bool clang::index::generateUSRForMacro(const MacroDefinition *MD, + const SourceManager &SM, + SmallVectorImpl &Buf) { + // Don't generate USRs for things with invalid locations. + if (!MD || MD->getLocation().isInvalid()) + return true; + + llvm::raw_svector_ostream Out(Buf); + + // Assume that system headers are sane. Don't put source location + // information into the USR if the macro comes from a system header. + SourceLocation Loc = MD->getLocation(); + bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc); + + Out << getUSRSpacePrefix(); + if (ShouldGenerateLocation) + printLoc(Out, Loc, SM, /*IncludeOffset=*/true); + Out << "@macro@"; + Out << MD->getName()->getNameStart(); + return false; +} + diff --git a/test/Index/Inputs/usrs-system.h b/test/Index/Inputs/usrs-system.h new file mode 100644 index 0000000000..dee4d83257 --- /dev/null +++ b/test/Index/Inputs/usrs-system.h @@ -0,0 +1 @@ +#define MACRO_FROM_SYSTEM_HEADER_1 meow diff --git a/test/Index/usrs.m b/test/Index/usrs.m index c321e85196..fc3fbc9105 100644 --- a/test/Index/usrs.m +++ b/test/Index/usrs.m @@ -89,7 +89,24 @@ int test_multi_declaration(void) { -(int)methodWithFn:(void (*)(int *p))fn; @end -// RUN: c-index-test -test-load-source-usrs all -target x86_64-apple-macosx10.7 %s | FileCheck %s +#include + +#define MACRO1 123 + +#define MACRO2 123 +#undef MACRO2 +#define MACRO2 789 + +#define MACRO3(X) 123, X +#define MACRO3(X) 789, X + +// RUN: c-index-test -test-load-source-usrs all -target x86_64-apple-macosx10.7 %s -isystem %S/Inputs | FileCheck %s +// CHECK: usrs-system.h c:@macro@MACRO_FROM_SYSTEM_HEADER_1 Extent=[1:9 - 1:40] +// CHECK: usrs.m c:usrs.m@1265@macro@MACRO1 Extent=[94:9 - 94:19] +// CHECK: usrs.m c:usrs.m@1285@macro@MACRO2 Extent=[96:9 - 96:19] +// CHECK: usrs.m c:usrs.m@1318@macro@MACRO2 Extent=[98:9 - 98:19] +// CHECK: usrs.m c:usrs.m@1338@macro@MACRO3 Extent=[100:9 - 100:25] +// CHECK: usrs.m c:usrs.m@1363@macro@MACRO3 Extent=[101:9 - 101:25] // CHECK: usrs.m c:usrs.m@F@my_helper Extent=[3:1 - 3:60] // CHECK: usrs.m c:usrs.m@95@F@my_helper@x Extent=[3:29 - 3:34] // CHECK: usrs.m c:usrs.m@102@F@my_helper@y Extent=[3:36 - 3:41] @@ -153,7 +170,13 @@ int test_multi_declaration(void) { // CHECK: usrs.m c:objc(cs)CWithExt2(im)pro_ext Extent=[88:23 - 88:30] // CHECK: usrs.m c:objc(cs)CWithExt2(im)setPro_ext: Extent=[88:23 - 88:30] -// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-source %s +// RUN: c-index-test -test-load-source all %s -isystem %S/Inputs | FileCheck -check-prefix=CHECK-source %s +// CHECK-source: usrs-system.h:1:9: macro definition=MACRO_FROM_SYSTEM_HEADER_1 Extent=[1:9 - 1:40] +// CHECK-source: usrs.m:94:9: macro definition=MACRO1 Extent=[94:9 - 94:19] +// CHECK-source: usrs.m:96:9: macro definition=MACRO2 Extent=[96:9 - 96:19] +// CHECK-source: usrs.m:98:9: macro definition=MACRO2 Extent=[98:9 - 98:19] +// CHECK-source: usrs.m:100:9: macro definition=MACRO3 Extent=[100:9 - 100:25] +// CHECK-source: usrs.m:101:9: macro definition=MACRO3 Extent=[101:9 - 101:25] // CHECK-source: usrs.m:3:19: FunctionDecl=my_helper:3:19 (Definition) Extent=[3:1 - 3:60] // CHECK-source: usrs.m:3:33: ParmDecl=x:3:33 (Definition) Extent=[3:29 - 3:34] // CHECK-source: usrs.m:3:40: ParmDecl=y:3:40 (Definition) Extent=[3:36 - 3:41] diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index 2b43c5b375..25881c3ef0 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -14,8 +14,10 @@ #include "CIndexer.h" #include "CXCursor.h" #include "CXString.h" +#include "CXTranslationUnit.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/PreprocessingRecord.h" +#include "clang/Frontend/ASTUnit.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" @@ -73,10 +75,16 @@ CXString clang_getCursorUSR(CXCursor C) { if (!buf) return cxstring::createEmpty(); - buf->Data += getUSRSpacePrefix(); - buf->Data += "macro@"; - buf->Data += - cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart(); + bool Ignore = generateUSRForMacro(cxcursor::getCursorMacroDefinition(C), + cxtu::getASTUnit(TU)->getSourceManager(), + buf->Data); + if (Ignore) { + buf->dispose(); + return cxstring::createEmpty(); + } + + // Return the C-string, but don't make a copy since it is already in + // the string buffer. buf->Data.push_back('\0'); return createCXString(buf); } -- 2.40.0