From fbd84caf62a21afa4db5f730e2e2603ead17bb65 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 5 May 2010 00:55:23 +0000 Subject: [PATCH] Rework clang_annotateTokens() to annotate tokens with information that more closely matches clang_getCursor(). Tokens are now annotated with the cursor (for the matching AST element) that most closely encompasses that token. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103064 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Index/annotate-tokens.c | 78 +++++------ test/Index/annotate-tokens.m | 76 +++++------ tools/libclang/CIndex.cpp | 242 +++++++++++++++++++++++++---------- 3 files changed, 248 insertions(+), 148 deletions(-) diff --git a/test/Index/annotate-tokens.c b/test/Index/annotate-tokens.c index 7fbf9cc4fb..41f182d271 100644 --- a/test/Index/annotate-tokens.c +++ b/test/Index/annotate-tokens.c @@ -11,55 +11,55 @@ void f(void *ptr) { // RUN: c-index-test -test-annotate-tokens=%s:4:1:9:32 %s | FileCheck %s // CHECK: Identifier: "T" [4:3 - 4:4] TypeRef=T:1:13 -// CHECK: Punctuation: "*" [4:4 - 4:5] +// CHECK: Punctuation: "*" [4:4 - 4:5] VarDecl=t_ptr:4:6 (Definition) // CHECK: Identifier: "t_ptr" [4:6 - 4:11] VarDecl=t_ptr:4:6 (Definition) -// CHECK: Punctuation: "=" [4:12 - 4:13] -// CHECK: Punctuation: "(" [4:14 - 4:15] +// CHECK: Punctuation: "=" [4:12 - 4:13] VarDecl=t_ptr:4:6 (Definition) +// CHECK: Punctuation: "(" [4:14 - 4:15] UnexposedExpr=ptr:3:14 // CHECK: Identifier: "T" [4:15 - 4:16] TypeRef=T:1:13 -// CHECK: Punctuation: "*" [4:17 - 4:18] -// CHECK: Punctuation: ")" [4:18 - 4:19] +// CHECK: Punctuation: "*" [4:17 - 4:18] UnexposedExpr=ptr:3:14 +// CHECK: Punctuation: ")" [4:18 - 4:19] UnexposedExpr=ptr:3:14 // CHECK: Identifier: "ptr" [4:19 - 4:22] DeclRefExpr=ptr:3:14 -// CHECK: Punctuation: ";" [4:22 - 4:23] -// CHECK: Punctuation: "(" [5:3 - 5:4] -// CHECK: Keyword: "void" [5:4 - 5:8] -// CHECK: Punctuation: ")" [5:8 - 5:9] -// CHECK: Keyword: "sizeof" [5:9 - 5:15] -// CHECK: Punctuation: "(" [5:15 - 5:16] +// CHECK: Punctuation: ";" [4:22 - 4:23] UnexposedStmt= +// CHECK: Punctuation: "(" [5:3 - 5:4] UnexposedExpr= +// CHECK: Keyword: "void" [5:4 - 5:8] UnexposedExpr= +// CHECK: Punctuation: ")" [5:8 - 5:9] UnexposedExpr= +// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnexposedExpr= +// CHECK: Punctuation: "(" [5:15 - 5:16] UnexposedExpr= // CHECK: Identifier: "T" [5:16 - 5:17] TypeRef=T:1:13 -// CHECK: Punctuation: ")" [5:17 - 5:18] -// CHECK: Punctuation: ";" [5:18 - 5:19] -// CHECK: Comment: "/* A comment */" [6:3 - 6:18] -// CHECK: Keyword: "struct" [7:3 - 7:9] +// CHECK: Punctuation: ")" [5:17 - 5:18] UnexposedExpr= +// CHECK: Punctuation: ";" [5:18 - 5:19] UnexposedStmt= +// CHECK: Comment: "/* A comment */" [6:3 - 6:18] UnexposedStmt= +// CHECK: Keyword: "struct" [7:3 - 7:9] UnexposedStmt= // CHECK: Identifier: "X" [7:10 - 7:11] TypeRef=struct X:2:8 // CHECK: Identifier: "x" [7:12 - 7:13] VarDecl=x:7:12 (Definition) -// CHECK: Punctuation: "=" [7:14 - 7:15] -// CHECK: Punctuation: "(" [7:16 - 7:17] -// CHECK: Keyword: "struct" [7:17 - 7:23] +// CHECK: Punctuation: "=" [7:14 - 7:15] VarDecl=x:7:12 (Definition) +// CHECK: Punctuation: "(" [7:16 - 7:17] UnexposedExpr= +// CHECK: Keyword: "struct" [7:17 - 7:23] UnexposedExpr= // CHECK: Identifier: "X" [7:24 - 7:25] TypeRef=struct X:2:8 -// CHECK: Punctuation: ")" [7:25 - 7:26] -// CHECK: Punctuation: "{" [7:26 - 7:27] -// CHECK: Literal: "1" [7:27 - 7:28] -// CHECK: Punctuation: "," [7:28 - 7:29] -// CHECK: Literal: "2" [7:30 - 7:31] -// CHECK: Punctuation: "}" [7:31 - 7:32] -// CHECK: Punctuation: ";" [7:32 - 7:33] -// CHECK: Keyword: "void" [8:3 - 8:7] -// CHECK: Punctuation: "*" [8:8 - 8:9] +// CHECK: Punctuation: ")" [7:25 - 7:26] UnexposedExpr= +// CHECK: Punctuation: "{" [7:26 - 7:27] UnexposedExpr= +// CHECK: Literal: "1" [7:27 - 7:28] UnexposedExpr= +// CHECK: Punctuation: "," [7:28 - 7:29] UnexposedExpr= +// CHECK: Literal: "2" [7:30 - 7:31] UnexposedExpr= +// CHECK: Punctuation: "}" [7:31 - 7:32] UnexposedExpr= +// CHECK: Punctuation: ";" [7:32 - 7:33] UnexposedStmt= +// CHECK: Keyword: "void" [8:3 - 8:7] VarDecl=xx:8:9 (Definition) +// CHECK: Punctuation: "*" [8:8 - 8:9] VarDecl=xx:8:9 (Definition) // CHECK: Identifier: "xx" [8:9 - 8:11] VarDecl=xx:8:9 (Definition) -// CHECK: Punctuation: "=" [8:12 - 8:13] +// CHECK: Punctuation: "=" [8:12 - 8:13] VarDecl=xx:8:9 (Definition) // CHECK: Identifier: "ptr" [8:14 - 8:17] DeclRefExpr=ptr:3:14 -// CHECK: Punctuation: "?" [8:18 - 8:19] -// CHECK: Punctuation: ":" [8:20 - 8:21] -// CHECK: Punctuation: "&" [8:22 - 8:23] +// CHECK: Punctuation: "?" [8:18 - 8:19] UnexposedExpr= +// CHECK: Punctuation: ":" [8:20 - 8:21] UnexposedExpr= +// CHECK: Punctuation: "&" [8:22 - 8:23] UnexposedExpr= // CHECK: Identifier: "x" [8:23 - 8:24] DeclRefExpr=x:7:12 -// CHECK: Punctuation: ";" [8:24 - 8:25] -// CHECK: Keyword: "const" [9:3 - 9:8] -// CHECK: Keyword: "char" [9:9 - 9:13] -// CHECK: Punctuation: "*" [9:14 - 9:15] +// CHECK: Punctuation: ";" [8:24 - 8:25] UnexposedStmt= +// CHECK: Keyword: "const" [9:3 - 9:8] UnexposedStmt= +// CHECK: Keyword: "char" [9:9 - 9:13] VarDecl=hello:9:16 (Definition) +// CHECK: Punctuation: "*" [9:14 - 9:15] VarDecl=hello:9:16 (Definition) // CHECK: Identifier: "hello" [9:16 - 9:21] VarDecl=hello:9:16 (Definition) -// CHECK: Punctuation: "=" [9:22 - 9:23] -// CHECK: Literal: ""Hello"" [9:24 - 9:31] -// CHECK: Punctuation: ";" [9:31 - 9:32] -// CHECK: Punctuation: "}" [10:1 - 10:2] +// CHECK: Punctuation: "=" [9:22 - 9:23] VarDecl=hello:9:16 (Definition) +// CHECK: Literal: ""Hello"" [9:24 - 9:31] UnexposedExpr= +// CHECK: Punctuation: ";" [9:31 - 9:32] UnexposedStmt= +// CHECK: Punctuation: "}" [10:1 - 10:2] UnexposedStmt= // RUN: c-index-test -test-annotate-tokens=%s:4:1:165:32 %s | FileCheck %s // RUN: c-index-test -test-annotate-tokens=%s:4:1:165:38 %s | FileCheck %s diff --git a/test/Index/annotate-tokens.m b/test/Index/annotate-tokens.m index ce399d34c6..8ed1537536 100644 --- a/test/Index/annotate-tokens.m +++ b/test/Index/annotate-tokens.m @@ -10,50 +10,50 @@ @end // RUN: c-index-test -test-annotate-tokens=%s:1:1:10:5 %s | FileCheck %s -// CHECK: Punctuation: "@" [1:1 - 1:2] -// CHECK: Identifier: "interface" [1:2 - 1:11] +// CHECK: Punctuation: "@" [1:1 - 1:2] ObjCInterfaceDecl=Foo:1:12 +// CHECK: Keyword: "interface" [1:2 - 1:11] ObjCInterfaceDecl=Foo:1:12 // CHECK: Identifier: "Foo" [1:12 - 1:15] ObjCInterfaceDecl=Foo:1:12 // CHECK: Punctuation: "-" [2:1 - 2:2] ObjCInstanceMethodDecl=compare::2:1 -// CHECK: Punctuation: "(" [2:3 - 2:4] -// CHECK: Keyword: "int" [2:4 - 2:7] -// CHECK: Punctuation: ")" [2:7 - 2:8] -// CHECK: Identifier: "compare" [2:8 - 2:15] -// CHECK: Punctuation: ":" [2:15 - 2:16] -// CHECK: Punctuation: "(" [2:16 - 2:17] +// CHECK: Punctuation: "(" [2:3 - 2:4] ObjCInstanceMethodDecl=compare::2:1 +// CHECK: Keyword: "int" [2:4 - 2:7] ObjCInstanceMethodDecl=compare::2:1 +// CHECK: Punctuation: ")" [2:7 - 2:8] ObjCInstanceMethodDecl=compare::2:1 +// CHECK: Identifier: "compare" [2:8 - 2:15] ObjCInstanceMethodDecl=compare::2:1 +// CHECK: Punctuation: ":" [2:15 - 2:16] ObjCInstanceMethodDecl=compare::2:1 +// CHECK: Punctuation: "(" [2:16 - 2:17] ObjCInstanceMethodDecl=compare::2:1 // CHECK: Identifier: "Foo" [2:17 - 2:20] ObjCClassRef=Foo:1:12 -// CHECK: Punctuation: "*" [2:20 - 2:21] -// CHECK: Punctuation: ")" [2:21 - 2:22] +// CHECK: Punctuation: "*" [2:20 - 2:21] ParmDecl=other:2:22 (Definition) +// CHECK: Punctuation: ")" [2:21 - 2:22] ParmDecl=other:2:22 (Definition) // CHECK: Identifier: "other" [2:22 - 2:27] ParmDecl=other:2:22 (Definition) -// CHECK: Punctuation: ";" [2:27 - 2:28] -// CHECK: Punctuation: "@" [3:1 - 3:2] -// CHECK: Identifier: "end" [3:2 - 3:5] +// CHECK: Punctuation: ";" [2:27 - 2:28] ObjCInstanceMethodDecl=compare::2:1 +// CHECK: Punctuation: "@" [3:1 - 3:2] ObjCInterfaceDecl=Foo:1:12 +// CHECK: Keyword: "end" [3:2 - 3:5] ObjCInterfaceDecl=Foo:1:12 // CHECK: Punctuation: "@" [5:1 - 5:2] ObjCImplementationDecl=Foo:5:1 (Definition) -// CHECK: Identifier: "implementation" [5:2 - 5:16] -// CHECK: Identifier: "Foo" [5:17 - 5:20] +// CHECK: Keyword: "implementation" [5:2 - 5:16] ObjCImplementationDecl=Foo:5:1 (Definition) +// CHECK: Identifier: "Foo" [5:17 - 5:20] ObjCImplementationDecl=Foo:5:1 (Definition) // CHECK: Punctuation: "-" [6:1 - 6:2] ObjCInstanceMethodDecl=compare::6:1 (Definition) -// CHECK: Punctuation: "(" [6:3 - 6:4] -// CHECK: Keyword: "int" [6:4 - 6:7] -// CHECK: Punctuation: ")" [6:7 - 6:8] -// CHECK: Identifier: "compare" [6:8 - 6:15] -// CHECK: Punctuation: ":" [6:15 - 6:16] -// CHECK: Punctuation: "(" [6:16 - 6:17] +// CHECK: Punctuation: "(" [6:3 - 6:4] ObjCInstanceMethodDecl=compare::6:1 (Definition) +// CHECK: Keyword: "int" [6:4 - 6:7] ObjCInstanceMethodDecl=compare::6:1 (Definition) +// CHECK: Punctuation: ")" [6:7 - 6:8] ObjCInstanceMethodDecl=compare::6:1 (Definition) +// CHECK: Identifier: "compare" [6:8 - 6:15] ObjCInstanceMethodDecl=compare::6:1 (Definition) +// CHECK: Punctuation: ":" [6:15 - 6:16] ObjCInstanceMethodDecl=compare::6:1 (Definition) +// CHECK: Punctuation: "(" [6:16 - 6:17] ObjCInstanceMethodDecl=compare::6:1 (Definition) // CHECK: Identifier: "Foo" [6:17 - 6:20] ObjCClassRef=Foo:1:12 -// CHECK: Punctuation: "*" [6:20 - 6:21] -// CHECK: Punctuation: ")" [6:21 - 6:22] +// CHECK: Punctuation: "*" [6:20 - 6:21] ParmDecl=other:6:22 (Definition) +// CHECK: Punctuation: ")" [6:21 - 6:22] ParmDecl=other:6:22 (Definition) // CHECK: Identifier: "other" [6:22 - 6:27] ParmDecl=other:6:22 (Definition) -// CHECK: Punctuation: "{" [6:28 - 6:29] -// CHECK: Keyword: "return" [7:3 - 7:9] -// CHECK: Literal: "0" [7:10 - 7:11] -// CHECK: Punctuation: ";" [7:11 - 7:12] -// CHECK: Punctuation: "(" [8:3 - 8:4] -// CHECK: Keyword: "void" [8:4 - 8:8] -// CHECK: Punctuation: ")" [8:8 - 8:9] -// CHECK: Punctuation: "@" [8:9 - 8:10] -// CHECK: Identifier: "encode" [8:10 - 8:16] -// CHECK: Punctuation: "(" [8:16 - 8:17] +// CHECK: Punctuation: "{" [6:28 - 6:29] UnexposedStmt= +// CHECK: Keyword: "return" [7:3 - 7:9] UnexposedStmt= +// CHECK: Literal: "0" [7:10 - 7:11] UnexposedExpr= +// CHECK: Punctuation: ";" [7:11 - 7:12] UnexposedStmt= +// CHECK: Punctuation: "(" [8:3 - 8:4] UnexposedExpr= +// CHECK: Keyword: "void" [8:4 - 8:8] UnexposedExpr= +// CHECK: Punctuation: ")" [8:8 - 8:9] UnexposedExpr= +// CHECK: Punctuation: "@" [8:9 - 8:10] UnexposedExpr= +// CHECK: Keyword: "encode" [8:10 - 8:16] UnexposedExpr= +// CHECK: Punctuation: "(" [8:16 - 8:17] UnexposedExpr= // CHECK: Identifier: "Foo" [8:17 - 8:20] ObjCClassRef=Foo:1:12 -// CHECK: Punctuation: ")" [8:20 - 8:21] -// CHECK: Punctuation: ";" [8:21 - 8:22] -// CHECK: Punctuation: "}" [9:1 - 9:2] -// CHECK: Punctuation: "@" [10:1 - 10:2] -// CHECK: Identifier: "end" [10:2 - 10:5] +// CHECK: Punctuation: ")" [8:20 - 8:21] UnexposedExpr= +// CHECK: Punctuation: ";" [8:21 - 8:22] UnexposedStmt= +// CHECK: Punctuation: "}" [9:1 - 9:2] UnexposedStmt= +// CHECK: Punctuation: "@" [10:1 - 10:2] ObjCImplementationDecl=Foo:5:1 (Definition) +// CHECK: Keyword: "end" [10:2 - 10:5] diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 0c0dbbabc2..ef802f574b 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -152,6 +152,23 @@ static RangeComparisonResult RangeCompare(SourceManager &SM, return RangeOverlap; } +/// \brief Determine if a source location falls within, before, or after a +/// a given source range. +static RangeComparisonResult LocationCompare(SourceManager &SM, + SourceLocation L, SourceRange R) { + assert(R.isValid() && "First range is invalid?"); + assert(L.isValid() && "Second range is invalid?"); + if (L == R.getBegin()) + return RangeOverlap; + if (L == R.getEnd()) + return RangeAfter; + if (SM.isBeforeInTranslationUnit(L, R.getBegin())) + return RangeBefore; + if (SM.isBeforeInTranslationUnit(R.getEnd(), L)) + return RangeAfter; + return RangeOverlap; +} + /// \brief Translate a Clang source range into a CIndex source range. /// /// Clang internally represents ranges where the end location points to the @@ -2326,65 +2343,148 @@ void clang_disposeTokens(CXTranslationUnit TU, //===----------------------------------------------------------------------===// typedef llvm::DenseMap AnnotateTokensData; - +static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor, + CXCursor parent, + CXClientData client_data); namespace { class AnnotateTokensWorker { AnnotateTokensData &Annotated; CXToken *Tokens; CXCursor *Cursors; unsigned NumTokens; + unsigned TokIdx; + CursorVisitor AnnotateVis; + SourceManager &SrcMgr; + + bool MoreTokens() const { return TokIdx < NumTokens; } + unsigned NextToken() const { return TokIdx; } + void AdvanceToken() { ++TokIdx; } + SourceLocation GetTokenLoc(unsigned tokI) { + return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]); + } + public: AnnotateTokensWorker(AnnotateTokensData &annotated, - CXToken *tokens, CXCursor *cursors, unsigned numTokens) + CXToken *tokens, CXCursor *cursors, unsigned numTokens, + ASTUnit *CXXUnit, SourceRange RegionOfInterest) : Annotated(annotated), Tokens(tokens), Cursors(cursors), - NumTokens(numTokens) {} - - void CompleteAnnotations(); + NumTokens(numTokens), TokIdx(0), + AnnotateVis(CXXUnit, AnnotateTokensVisitor, this, + Decl::MaxPCHLevel, RegionOfInterest), + SrcMgr(CXXUnit->getSourceManager()) {} + void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); } enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent); + void AnnotateTokens(CXCursor parent); }; } -void AnnotateTokensWorker::CompleteAnnotations() { - for (unsigned I = 0; I != NumTokens; ++I) { - // Determine whether we saw a cursor at this token's location. +void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) { + // Walk the AST within the region of interest, annotating tokens + // along the way. + VisitChildren(parent); + + for (unsigned I = 0 ; I < TokIdx ; ++I) { AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]); - if (Pos == Annotated.end()) - continue; + if (Pos != Annotated.end()) + Cursors[I] = Pos->second; + } + + // Finish up annotating any tokens left. + if (!MoreTokens()) + return; - Cursors[I] = Pos->second; + const CXCursor &C = clang_getNullCursor(); + for (unsigned I = TokIdx ; I < NumTokens ; ++I) { + AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]); + Cursors[I] = (Pos == Annotated.end()) ? C : Pos->second; } } enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { - // We only annotate the locations of declarations, simple - // references, and expressions which directly reference something. - CXCursorKind Kind = clang_getCursorKind(cursor); - if (clang_isDeclaration(Kind) || clang_isReference(Kind)) { - // Okay: We can annotate the location of this declaration with the - // declaration or reference - } else if (clang_isExpression(cursor.kind)) { - if (Kind != CXCursor_DeclRefExpr && - Kind != CXCursor_MemberRefExpr && - Kind != CXCursor_ObjCMessageExpr) - return CXChildVisit_Recurse; - - CXCursor Referenced = clang_getCursorReferenced(cursor); - if (Referenced == cursor || Referenced == clang_getNullCursor()) - 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 + CXSourceLocation Loc = clang_getCursorLocation(cursor); + // We can always annotate a preprocessing directive/macro instantiation. + if (clang_isPreprocessing(cursor.kind)) { + Annotated[Loc.int_data] = cursor; return CXChildVisit_Recurse; } + + CXSourceRange cursorExtent = clang_getCursorExtent(cursor); + SourceRange cursorRange = cxloc::translateCXSourceRange(cursorExtent); + + if (cursorRange.isInvalid()) + return CXChildVisit_Continue; + + SourceLocation L = SourceLocation::getFromRawEncoding(Loc.int_data); + + const enum CXCursorKind K = clang_getCursorKind(parent); + const CXCursor updateC = + (clang_isInvalid(K) || K == CXCursor_TranslationUnit || + L.isMacroID()) + ? clang_getNullCursor() : parent; + + while (MoreTokens()) { + const unsigned I = NextToken(); + SourceLocation TokLoc = GetTokenLoc(I); + switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) { + case RangeBefore: + Cursors[I] = updateC; + AdvanceToken(); + continue; + case RangeAfter: + return CXChildVisit_Continue; + case RangeOverlap: + break; + } + break; + } + + // Visit children to get their cursor information. + const unsigned BeforeChildren = NextToken(); + VisitChildren(cursor); + const unsigned AfterChildren = NextToken(); + + // Adjust 'Last' to the last token within the extent of the cursor. + 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] = updateC; + AdvanceToken(); + continue; + } + break; + } + const unsigned Last = NextToken(); - CXSourceLocation Loc = clang_getCursorLocation(cursor); - Annotated[Loc.int_data] = cursor; - return CXChildVisit_Recurse; + // Scan the tokens that are at the beginning of the cursor, but are not + // capture by the child cursors. + + // For AST elements within macros, rely on a post-annotate pass to + // to correctly annotate the tokens with cursors. Otherwise we can + // get confusing results of having tokens that map to cursors that really + // are expanded by an instantiation. + if (L.isMacroID()) + cursor = clang_getNullCursor(); + + 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 + // but the child cursors. + for (unsigned I = AfterChildren; I != Last; ++I) + Cursors[I] = cursor; + + TokIdx = Last; + return CXChildVisit_Continue; } static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor, @@ -2398,40 +2498,43 @@ extern "C" { void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens, unsigned NumTokens, CXCursor *Cursors) { - if (NumTokens == 0) + + if (NumTokens == 0 || !Tokens || !Cursors) return; - - // Any token we don't specifically annotate will have a NULL cursor. - for (unsigned I = 0; I != NumTokens; ++I) - Cursors[I] = clang_getNullCursor(); - + ASTUnit *CXXUnit = static_cast(TU); - if (!CXXUnit || !Tokens) + 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; return; - + } + ASTUnit::ConcurrencyCheck Check(*CXXUnit); - + // Determine the region of interest, which contains all of the tokens. SourceRange RegionOfInterest; - RegionOfInterest.setBegin( - cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0]))); + 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; - - // Relex the tokens within the source range to look for preprocessing + + // 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()); - + llvm::StringRef Buffer; bool Invalid = false; if (BeginLocInfo.first == EndLocInfo.first && @@ -2439,16 +2542,16 @@ void clang_annotateTokens(CXTranslationUnit TU, !Invalid) { Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), CXXUnit->getASTContext().getLangOptions(), - Buffer.begin(), Buffer.data() + BeginLocInfo.second, + Buffer.begin(), Buffer.data() + BeginLocInfo.second, Buffer.end()); Lex.SetCommentRetentionState(true); - - // Lex tokens in raw mode until we hit the end of the range, to avoid + + // Lex tokens in raw mode until we hit the end of the range, to avoid // entering #includes or expanding macros. while (true) { Token Tok; Lex.LexFromRawLexer(Tok); - + reprocess: if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { // We have found a preprocessing directive. Gobble it up so that we @@ -2461,37 +2564,34 @@ void clang_annotateTokens(CXTranslationUnit TU, std::vector Locations; do { Locations.push_back(Tok.getLocation()); - Lex.LexFromRawLexer(Tok); + Lex.LexFromRawLexer(Tok); } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof)); - + using namespace cxcursor; CXCursor Cursor - = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(), - Locations.back()), + = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(), + Locations.back()), CXXUnit); for (unsigned I = 0, N = Locations.size(); I != N; ++I) { Annotated[Locations[I].getRawEncoding()] = Cursor; } - + if (Tok.isAtStartOfLine()) goto reprocess; - + continue; } - + if (Tok.is(tok::eof)) break; } } - + // Annotate all of the source locations in the region of interest that map to - // a specific cursor. - CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit); - AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens); - CursorVisitor AnnotateVis(CXXUnit, AnnotateTokensVisitor, &W, - Decl::MaxPCHLevel, RegionOfInterest); - AnnotateVis.VisitChildren(Parent); - W.CompleteAnnotations(); + // a specific cursor. + AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens, + CXXUnit, RegionOfInterest); + W.AnnotateTokens(clang_getTranslationUnitCursor(CXXUnit)); } } // end: extern "C" -- 2.40.0