libclang/libIndex: USR generation: mangle source location into USRs for macros,

unless the macro comes from a system header

llvm-svn: 205064
This commit is contained in:
Dmitri Gribenko 2014-03-28 22:21:26 +00:00
parent 57ba0b228d
commit 237769ede5
5 changed files with 101 additions and 32 deletions

View File

@ -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<char> &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<char> &Buf);
} // namespace index
} // namespace clang

View File

@ -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<FileID, unsigned> &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<USRGenerator> {
SmallVectorImpl<char> &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<FileID, unsigned> &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<char> &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;
}

View File

@ -0,0 +1 @@
#define MACRO_FROM_SYSTEM_HEADER_1 meow

View File

@ -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 <usrs-system.h>
#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]

View File

@ -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);
}