summaryrefslogtreecommitdiffstats
path: root/clang/tools/libclang/CIndex.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-10-21 06:10:04 +0000
committerDouglas Gregor <dgregor@apple.com>2010-10-21 06:10:04 +0000
commitadfdccf1f3d4d9c377c721b5c1067dcc02e58c23 (patch)
treed0a2d6653938286df2bfed0bb7806ce865871379 /clang/tools/libclang/CIndex.cpp
parentcac9df3bf6bd1ffd1251aac73805a37c041a2fdc (diff)
downloadbcm5719-llvm-adfdccf1f3d4d9c377c721b5c1067dcc02e58c23.tar.gz
bcm5719-llvm-adfdccf1f3d4d9c377c721b5c1067dcc02e58c23.zip
Improve the implementation of libclang's token-annotation logic for
entities in the preprocessing record. Previously, we would only end up getting the first token of a preprocessing record annotated correctly. For example, given #include "foo.h" we would only get the '#' annotated as an inclusion directive; the 'include' and '"foo.h"' tokens would be given the general 'processing directive' annotation. Now, we get proper annotations for entities in the preprocessing record. llvm-svn: 117001
Diffstat (limited to 'clang/tools/libclang/CIndex.cpp')
-rw-r--r--clang/tools/libclang/CIndex.cpp84
1 files changed, 69 insertions, 15 deletions
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index c944883fa4d..b9147fa1a1f 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -3657,6 +3657,7 @@ class AnnotateTokensWorker {
CXCursor *Cursors;
unsigned NumTokens;
unsigned TokIdx;
+ unsigned PreprocessingTokIdx;
CursorVisitor AnnotateVis;
SourceManager &SrcMgr;
@@ -3672,7 +3673,7 @@ public:
CXToken *tokens, CXCursor *cursors, unsigned numTokens,
ASTUnit *CXXUnit, SourceRange RegionOfInterest)
: Annotated(annotated), Tokens(tokens), Cursors(cursors),
- NumTokens(numTokens), TokIdx(0),
+ NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0),
AnnotateVis(CXXUnit, AnnotateTokensVisitor, this,
Decl::MaxPCHLevel, RegionOfInterest),
SrcMgr(CXXUnit->getSourceManager()) {}
@@ -3690,7 +3691,9 @@ void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) {
for (unsigned I = 0 ; I < TokIdx ; ++I) {
AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
- if (Pos != Annotated.end())
+ if (Pos != Annotated.end() &&
+ (clang_isInvalid(Cursors[I].kind) ||
+ Pos->second.kind != CXCursor_PreprocessingDirective))
Cursors[I] = Pos->second;
}
@@ -3706,16 +3709,66 @@ void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) {
}
enum CXChildVisitResult
-AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
+AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
CXSourceLocation Loc = clang_getCursorLocation(cursor);
- // We can always annotate a preprocessing directive/macro instantiation.
- if (clang_isPreprocessing(cursor.kind)) {
- Annotated[Loc.int_data] = cursor;
+ SourceRange cursorRange = getRawCursorExtent(cursor);
+
+ if (clang_isPreprocessing(cursor.kind)) {
+ // For macro instantiations, just note where the beginning of the macro
+ // instantiation occurs.
+ if (cursor.kind == CXCursor_MacroInstantiation) {
+ Annotated[Loc.int_data] = cursor;
+ return CXChildVisit_Recurse;
+ }
+
+ if (cursorRange.isInvalid())
+ return CXChildVisit_Continue;
+
+ // Items in the preprocessing record are kept separate from items in
+ // declarations, so we keep a separate token index.
+ unsigned SavedTokIdx = TokIdx;
+ TokIdx = PreprocessingTokIdx;
+
+ // Skip tokens up until we catch up to the beginning of the preprocessing
+ // entry.
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ SourceLocation TokLoc = GetTokenLoc(I);
+ switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
+ case RangeBefore:
+ AdvanceToken();
+ continue;
+ case RangeAfter:
+ case RangeOverlap:
+ break;
+ }
+ break;
+ }
+
+ // Look at all of the tokens within this range.
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ SourceLocation TokLoc = GetTokenLoc(I);
+ switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
+ case RangeBefore:
+ assert(0 && "Infeasible");
+ case RangeAfter:
+ break;
+ case RangeOverlap:
+ Cursors[I] = cursor;
+ AdvanceToken();
+ continue;
+ }
+ break;
+ }
+
+ // Save the preprocessing token index; restore the non-preprocessing
+ // token index.
+ PreprocessingTokIdx = TokIdx;
+ TokIdx = SavedTokIdx;
return CXChildVisit_Recurse;
}
- SourceRange cursorRange = getRawCursorExtent(cursor);
-
if (cursorRange.isInvalid())
return CXChildVisit_Continue;
@@ -3753,7 +3806,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
// directive. Here we assume that the default construction of CXCursor
// results in CXCursor.kind being an initialized value (i.e., 0). If
// this isn't the case, we can fix by doing lookup + insertion.
-
+
CXCursor &oldC = Annotated[rawEncoding];
if (!clang_isPreprocessing(oldC.kind))
oldC = cursor;
@@ -3815,6 +3868,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
for (unsigned I = BeforeChildren; I != AfterChildren; ++I) {
if (!clang_isInvalid(clang_getCursorKind(Cursors[I])))
break;
+
Cursors[I] = cursor;
}
// Scan the tokens that are at the end of the cursor, but are not captured
@@ -3841,14 +3895,14 @@ void clang_annotateTokens(CXTranslationUnit TU,
if (NumTokens == 0 || !Tokens || !Cursors)
return;
+ // Any token we don't specifically annotate will have a NULL cursor.
+ CXCursor C = clang_getNullCursor();
+ for (unsigned I = 0; I != NumTokens; ++I)
+ Cursors[I] = C;
+
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
- if (!CXXUnit) {
- // Any token we don't specifically annotate will have a NULL cursor.
- const CXCursor &C = clang_getNullCursor();
- for (unsigned I = 0; I != NumTokens; ++I)
- Cursors[I] = C;
+ if (!CXXUnit)
return;
- }
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
OpenPOWER on IntegriCloud