From 20004ee7d21b1f7a0e1666b312483093d780cf9e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 19 Mar 2010 00:18:31 +0000 Subject: [PATCH] Visit preprocessing elements (macro instantiations and macro definitions) as part of the translation unit, so that normal visitation, token-annotation, and cursor-at retrieval all see preprocessing elements. llvm-svn: 98907 --- clang/test/Index/c-index-getCursor-pp.c | 18 +++ clang/tools/CIndex/CIndex.cpp | 153 +++++++----------------- 2 files changed, 64 insertions(+), 107 deletions(-) create mode 100644 clang/test/Index/c-index-getCursor-pp.c diff --git a/clang/test/Index/c-index-getCursor-pp.c b/clang/test/Index/c-index-getCursor-pp.c new file mode 100644 index 000000000000..67fcfef2e4be --- /dev/null +++ b/clang/test/Index/c-index-getCursor-pp.c @@ -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 diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index 4cf49613e3d2..526d1b4bf3f2 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -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(*E)) { + if (Visit(MakeMacroInstantiationCursor(MI, CXXUnit))) + return true; + continue; + } + + if (MacroDefinition *MD = dyn_cast(*E)) { + if (Visit(MakeMacroDefinitionCursor(MD, CXXUnit))) + return true; + + continue; + } + } + } return false; } @@ -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 @@ -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; @@ -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)); - - 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. + // A mapping from the source locations found when re-lexing or traversing the + // region of interest to the corresponding cursors. + AnnotateTokensData Annotated; + + // Relex the tokens within the source range to look for preprocessing + // directives. SourceManager &SourceMgr = CXXUnit->getSourceManager(); std::pair BeginLocInfo = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin()); std::pair 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, @@ -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 TokenStream; while (true) { Token Tok; Lex.LexFromRawLexer(Tok); @@ -2407,35 +2368,13 @@ void clang_annotateTokens(CXTranslationUnit TU, break; } } - - if (CXXUnit->hasPreprocessingRecord()) { - PreprocessingRecord &PPRec = CXXUnit->getPreprocessingRecord(); - std::pair - 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(Entity)) { - SourceLocation Loc = MI->getSourceRange().getBegin(); - if (Loc.isFileID()) { - Annotated[Loc.getRawEncoding()] - = MakeMacroInstantiationCursor(MI, CXXUnit); - } - - continue; - } - - if (MacroDefinition *MD = dyn_cast(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.