Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
Visit preprocessing elements (macro instantiations and macro
Browse files Browse the repository at this point in the history
definitions) as part of the translation unit, so that normal
visitation, token-annotation, and cursor-at retrieval all see
preprocessing elements.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98935 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
DougGregor committed Mar 19, 2010
1 parent 3178cb6 commit 0396f46
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 106 deletions.
18 changes: 18 additions & 0 deletions test/Index/c-index-getCursor-pp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#define OBSCURE(X) X
#define DECORATION

typedef int T;
void OBSCURE(func)(int x) {
OBSCURE(T) DECORATION value;
}

// RUN: c-index-test -cursor-at=%s:1:11 %s | FileCheck -check-prefix=CHECK-1 %s
// CHECK-1: macro definition=OBSCURE
// RUN: c-index-test -cursor-at=%s:2:14 %s | FileCheck -check-prefix=CHECK-2 %s
// CHECK-2: macro definition=DECORATION
// RUN: c-index-test -cursor-at=%s:5:7 %s | FileCheck -check-prefix=CHECK-3 %s
// CHECK-3: macro instantiation=OBSCURE:1:9
// RUN: c-index-test -cursor-at=%s:6:6 %s | FileCheck -check-prefix=CHECK-4 %s
// CHECK-4: macro instantiation=OBSCURE:1:9
// RUN: c-index-test -cursor-at=%s:6:19 %s | FileCheck -check-prefix=CHECK-5 %s
// CHECK-5: macro instantiation=DECORATION:2:9
154 changes: 48 additions & 106 deletions tools/CIndex/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,31 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
if (Visit(MakeCXCursor(*it, CXXUnit), true))
return true;
}
} else {
return VisitDeclContext(
CXXUnit->getASTContext().getTranslationUnitDecl());
}
} else if (VisitDeclContext(
CXXUnit->getASTContext().getTranslationUnitDecl()))
return true;

// Walk the preprocessing record.
if (CXXUnit->hasPreprocessingRecord()) {
// FIXME: Once we have the ability to deserialize a preprocessing record,
// do so.
PreprocessingRecord &PPRec = CXXUnit->getPreprocessingRecord();
for (PreprocessingRecord::iterator E = PPRec.begin(), EEnd = PPRec.end();
E != EEnd; ++E) {
if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
if (Visit(MakeMacroInstantiationCursor(MI, CXXUnit)))
return true;
continue;
}

if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
if (Visit(MakeMacroDefinitionCursor(MD, CXXUnit)))
return true;

continue;
}
}
}
return false;
}

Expand Down Expand Up @@ -2059,51 +2079,6 @@ void clang_enableStackTraces(void) {
// Token-based Operations.
//===----------------------------------------------------------------------===//

namespace {
class ComparePreprocessedEntityLocation {
SourceManager &SM;

public:
explicit ComparePreprocessedEntityLocation(SourceManager &SM) : SM(SM) { }

bool operator()(const PreprocessedEntity *Entity, SourceLocation Loc) const{
return SM.isBeforeInTranslationUnit(Entity->getSourceRange().getEnd(),
Loc);
}

bool operator()(SourceLocation Loc, const PreprocessedEntity *Entity) const{
return SM.isBeforeInTranslationUnit(Loc,
Entity->getSourceRange().getBegin());
}

bool operator()(const PreprocessedEntity *Entity, SourceRange R) const {
return SM.isBeforeInTranslationUnit(Entity->getSourceRange().getEnd(),
R.getBegin());
}

bool operator()(SourceRange R, const PreprocessedEntity *Entity) const {
return SM.isBeforeInTranslationUnit(R.getEnd(),
Entity->getSourceRange().getBegin());
}

bool operator()(const PreprocessedEntity *Entity1,
const PreprocessedEntity *Entity2) const {
return SM.isBeforeInTranslationUnit(Entity1->getSourceRange().getEnd(),
Entity2->getSourceRange().getBegin());
}

bool operator()(SourceRange R1, SourceRange R2) const {
return SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin());
}

bool operator()(SourceLocation Loc1, SourceLocation Loc2) const {
return SM.isBeforeInTranslationUnit(Loc1, Loc2);
}
};
}



/* CXToken layout:
* int_data[0]: a CXTokenKind
* int_data[1]: starting token location
Expand Down Expand Up @@ -2293,6 +2268,8 @@ enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
return CXChildVisit_Recurse;

// Okay: we can annotate the location of this expression
} else if (clang_isPreprocessing(cursor.kind)) {
// We can always annotate a preprocessing directive/macro instantiation.
} else {
// Nothing to annotate
return CXChildVisit_Recurse;
Expand All @@ -2319,47 +2296,32 @@ void clang_annotateTokens(CXTranslationUnit TU,

ASTUnit::ConcurrencyCheck Check(*CXXUnit);

// Annotate all of the source locations in the region of interest that map to
// a specific cursor.
// Determine the region of interest, which contains all of the tokens.
SourceRange RegionOfInterest;
RegionOfInterest.setBegin(
cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
SourceLocation End
= cxloc::translateSourceLocation(clang_getTokenLocation(TU,
Tokens[NumTokens - 1]));
= cxloc::translateSourceLocation(clang_getTokenLocation(TU,
Tokens[NumTokens - 1]));
RegionOfInterest.setEnd(CXXUnit->getPreprocessor().getLocForEndOfToken(End));


// A mapping from the source locations found when re-lexing or traversing the
// region of interest to the corresponding cursors.
AnnotateTokensData Annotated;
CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
CursorVisitor AnnotateVis(CXXUnit, AnnotateTokensVisitor, &Annotated,
Decl::MaxPCHLevel, RegionOfInterest);
AnnotateVis.VisitChildren(Parent);

// Look for macro instantiations and preprocessing directives in the
// source range containing the annotated tokens. We do this by re-lexing the
// tokens in the source range.
// Relex the tokens within the source range to look for preprocessing
// directives.
SourceManager &SourceMgr = CXXUnit->getSourceManager();
std::pair<FileID, unsigned> BeginLocInfo
= SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin());
std::pair<FileID, unsigned> EndLocInfo
= SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd());

bool RelexOkay = true;

// Cannot re-tokenize across files.
if (BeginLocInfo.first != EndLocInfo.first)
RelexOkay = false;

llvm::StringRef Buffer;
if (RelexOkay) {
// Create a lexer
bool Invalid = false;
Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
if (Invalid)
RelexOkay = false;
}

if (RelexOkay) {
bool Invalid = false;
if (BeginLocInfo.first == EndLocInfo.first &&
((Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid)),true) &&
!Invalid) {
Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
CXXUnit->getASTContext().getLangOptions(),
Buffer.begin(), Buffer.data() + BeginLocInfo.second,
Expand All @@ -2368,7 +2330,6 @@ void clang_annotateTokens(CXTranslationUnit TU,

// Lex tokens in raw mode until we hit the end of the range, to avoid
// entering #includes or expanding macros.
std::vector<Token> TokenStream;
while (true) {
Token Tok;
Lex.LexFromRawLexer(Tok);
Expand Down Expand Up @@ -2407,35 +2368,13 @@ void clang_annotateTokens(CXTranslationUnit TU,
break;
}
}

if (CXXUnit->hasPreprocessingRecord()) {
PreprocessingRecord &PPRec = CXXUnit->getPreprocessingRecord();
std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
Entities = std::equal_range(PPRec.begin(), PPRec.end(), RegionOfInterest,
ComparePreprocessedEntityLocation(SourceMgr));
for (; Entities.first != Entities.second; ++Entities.first) {
PreprocessedEntity *Entity = *Entities.first;
if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(Entity)) {
SourceLocation Loc = MI->getSourceRange().getBegin();
if (Loc.isFileID()) {
Annotated[Loc.getRawEncoding()]
= MakeMacroInstantiationCursor(MI, CXXUnit);
}

continue;
}

if (MacroDefinition *MD = dyn_cast<MacroDefinition>(Entity)) {
SourceLocation Loc = MD->getLocation();
if (Loc.isFileID()) {
Annotated[Loc.getRawEncoding()]
= MakeMacroDefinitionCursor(MD, CXXUnit);
}

continue;
}
}
}

// Annotate all of the source locations in the region of interest that map to
// a specific cursor.
CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
CursorVisitor AnnotateVis(CXXUnit, AnnotateTokensVisitor, &Annotated,
Decl::MaxPCHLevel, RegionOfInterest);
AnnotateVis.VisitChildren(Parent);

for (unsigned I = 0; I != NumTokens; ++I) {
// Determine whether we saw a cursor at this token's location.
Expand All @@ -2460,6 +2399,9 @@ void clang_disposeTokens(CXTranslationUnit TU,

extern "C" {
CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
if (!clang_isDeclaration(cursor.kind))
return CXLinkage_Invalid;

Decl *D = cxcursor::getCursorDecl(cursor);
if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
switch (ND->getLinkage()) {
Expand Down

0 comments on commit 0396f46

Please sign in to comment.