From: Argyrios Kyrtzidis Date: Wed, 16 Nov 2011 08:58:57 +0000 (+0000) Subject: [libclang] Make clang_annotateTokens use "file-targeted" deserialization and avoid X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03ee2dd9fc5d5fc62b5eb0fb88ee56e553f8cda7;p=clang [libclang] Make clang_annotateTokens use "file-targeted" deserialization and avoid unnecessary deserializations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144792 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Index/targeted-annotation.c b/test/Index/targeted-annotation.c new file mode 100644 index 0000000000..cfa1046cc8 --- /dev/null +++ b/test/Index/targeted-annotation.c @@ -0,0 +1,99 @@ + +#include "targeted-top.h" +#include "targeted-preamble.h" + +int LocalVar1; +int LocalVar2; + +// RUN: c-index-test -write-pch %t.h.pch %S/targeted-top.h +// RUN: env CINDEXTEST_FAILONERROR=1 c-index-test -test-annotate-tokens=%s:1:1:7:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=NestedVar1 \ +// RUN: -Xclang -error-on-deserialized-decl=TopVar \ +// RUN: | FileCheck %s -check-prefix=LOCAL + +// RUN: env CINDEXTEST_FAILONERROR=1 CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_NO_CACHING=1 \ +// RUN: c-index-test -test-annotate-tokens=%s:1:1:7:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=PreambleVar \ +// RUN: -Xclang -error-on-deserialized-decl=NestedVar1 \ +// RUN: -Xclang -error-on-deserialized-decl=TopVar \ +// RUN: | FileCheck %s -check-prefix=LOCAL + +// LOCAL: Punctuation: "#" [2:1 - 2:2] inclusion directive=targeted-top.h +// LOCAL: Identifier: "include" [2:2 - 2:9] inclusion directive=targeted-top.h +// LOCAL: Literal: ""targeted-top.h"" [2:10 - 2:26] inclusion directive=targeted-top.h +// LOCAL: Punctuation: "#" [3:1 - 3:2] inclusion directive=targeted-preamble.h +// LOCAL: Identifier: "include" [3:2 - 3:9] inclusion directive=targeted-preamble.h +// LOCAL: Literal: ""targeted-preamble.h"" [3:10 - 3:31] inclusion directive=targeted-preamble.h +// LOCAL: Keyword: "int" [5:1 - 5:4] VarDecl=LocalVar1:5:5 +// LOCAL: Identifier: "LocalVar1" [5:5 - 5:14] VarDecl=LocalVar1:5:5 +// LOCAL: Punctuation: ";" [5:14 - 5:15] +// LOCAL: Keyword: "int" [6:1 - 6:4] VarDecl=LocalVar2:6:5 +// LOCAL: Identifier: "LocalVar2" [6:5 - 6:14] VarDecl=LocalVar2:6:5 +// LOCAL: Punctuation: ";" [6:14 - 6:15] + +// RUN: env CINDEXTEST_FAILONERROR=1 c-index-test -test-annotate-tokens=%S/targeted-fields.h:1:1:4:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=NestedVar1 \ +// RUN: -Xclang -error-on-deserialized-decl=TopVar \ +// RUN: | FileCheck %s -check-prefix=FIELD + +// RUN: env CINDEXTEST_FAILONERROR=1 CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_NO_CACHING=1 \ +// RUN: c-index-test -test-annotate-tokens=%S/targeted-fields.h:1:1:4:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=PreambleVar \ +// RUN: -Xclang -error-on-deserialized-decl=NestedVar1 \ +// RUN: -Xclang -error-on-deserialized-decl=TopVar \ +// RUN: | FileCheck %s -check-prefix=FIELD + +// FIELD: Keyword: "int" [2:3 - 2:6] FieldDecl=z:2:7 (Definition) +// FIELD: Identifier: "z" [2:7 - 2:8] FieldDecl=z:2:7 (Definition) +// FIELD: Punctuation: ";" [2:8 - 2:9] StructDecl=:13:9 (Definition) +// FIELD: Keyword: "int" [3:3 - 3:6] FieldDecl=w:3:7 (Definition) +// FIELD: Identifier: "w" [3:7 - 3:8] FieldDecl=w:3:7 (Definition) +// FIELD: Punctuation: ";" [3:8 - 3:9] StructDecl=:13:9 (Definition) + +// RUN: env CINDEXTEST_FAILONERROR=1 c-index-test -test-annotate-tokens=%S/targeted-nested1.h:1:1:3:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=TopVar \ +// RUN: | FileCheck %s -check-prefix=NESTED + +// RUN: env CINDEXTEST_FAILONERROR=1 CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_NO_CACHING=1 \ +// RUN: c-index-test -test-annotate-tokens=%S/targeted-nested1.h:1:1:3:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=PreambleVar \ +// RUN: -Xclang -error-on-deserialized-decl=TopVar \ +// RUN: | FileCheck %s -check-prefix=NESTED + +// NESTED: Keyword: "extern" [2:1 - 2:7] +// NESTED: Keyword: "int" [2:8 - 2:11] VarDecl=NestedVar1:2:12 +// NESTED: Identifier: "NestedVar1" [2:12 - 2:22] VarDecl=NestedVar1:2:12 +// NESTED: Punctuation: ";" [2:22 - 2:23] + +// RUN: env CINDEXTEST_FAILONERROR=1 c-index-test -test-annotate-tokens=%S/targeted-top.h:1:1:12:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=NestedVar1 \ +// RUN: -Xclang -error-on-deserialized-decl=vector_get_x \ +// RUN: | FileCheck %s -check-prefix=TOP + +// RUN: env CINDEXTEST_FAILONERROR=1 CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_NO_CACHING=1 \ +// RUN: c-index-test -test-annotate-tokens=%S/targeted-top.h:1:1:12:1 %s -include %t.h \ +// RUN: -Xclang -error-on-deserialized-decl=PreambleVar \ +// RUN: -Xclang -error-on-deserialized-decl=NestedVar1 \ +// RUN: -Xclang -error-on-deserialized-decl=vector_get_x \ +// RUN: | FileCheck %s -check-prefix=TOP + +// TOP: Punctuation: "#" [2:1 - 2:2] preprocessing directive= +// TOP: Identifier: "ifndef" [2:2 - 2:8] preprocessing directive= +// TOP: Identifier: "TARGETED_TOP_H" [2:9 - 2:23] preprocessing directive= +// TOP: Punctuation: "#" [3:1 - 3:2] preprocessing directive= +// TOP: Identifier: "define" [3:2 - 3:8] preprocessing directive= +// TOP: Identifier: "TARGETED_TOP_H" [3:9 - 3:23] preprocessing directive= +// TOP: Punctuation: "#" [5:1 - 5:2] preprocessing directive= +// TOP: Identifier: "include" [5:2 - 5:9] preprocessing directive= +// TOP: Literal: ""targeted-nested1.h"" [5:10 - 5:30] preprocessing directive= +// TOP: Keyword: "enum" [7:1 - 7:5] EnumDecl=:7:1 (Definition) +// TOP: Punctuation: "{" [7:6 - 7:7] EnumDecl=:7:1 (Definition) +// TOP: Identifier: "VALUE" [8:3 - 8:8] EnumConstantDecl=VALUE:8:3 (Definition) +// TOP: Punctuation: "=" [8:9 - 8:10] EnumConstantDecl=VALUE:8:3 (Definition) +// TOP: Literal: "3" [8:11 - 8:12] IntegerLiteral= +// TOP: Punctuation: "}" [9:1 - 9:2] EnumDecl=:7:1 (Definition) +// TOP: Punctuation: ";" [9:2 - 9:3] +// TOP: Keyword: "extern" [11:1 - 11:7] +// TOP: Keyword: "int" [11:8 - 11:11] VarDecl=TopVar:11:12 +// TOP: Identifier: "TopVar" [11:12 - 11:18] VarDecl=TopVar:11:12 +// TOP: Punctuation: ";" [11:18 - 11:19] diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 25d0c5b6da..42adfa1cbc 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -315,6 +315,14 @@ void CursorVisitor::visitDeclsFromFileRegion(FileID File, assert(CompRes == RangeOverlap); VisitedAtLeastOnce = true; + + if (isa(D)) { + FileDI_current = &DIt; + FileDE_current = DE; + } else { + FileDI_current = 0; + } + if (Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true)) break; } @@ -838,6 +846,27 @@ bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) { return false; } +template +static void addRangedDeclsInContainer(DeclIt *DI_current, DeclIt DE_current, + SourceManager &SM, SourceLocation EndLoc, + SmallVectorImpl &Decls) { + DeclIt next = *DI_current; + while (++next != DE_current) { + Decl *D_next = *next; + if (!D_next) + break; + SourceLocation L = D_next->getLocStart(); + if (!L.isValid()) + break; + if (SM.isBeforeInTranslationUnit(L, EndLoc)) { + *DI_current = next; + Decls.push_back(D_next); + continue; + } + break; + } +} + namespace { struct ContainerDeclsSort { SourceManager &SM; @@ -856,7 +885,7 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) { // an @implementation can lexically contain Decls that are not properly // nested in the AST. When we identify such cases, we need to retrofit // this nesting here. - if (!DI_current) + if (!DI_current && !FileDI_current) return VisitDeclContext(D); // Scan the Decls that immediately come after the container @@ -867,20 +896,12 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) { SourceLocation EndLoc = D->getSourceRange().getEnd(); SourceManager &SM = AU->getSourceManager(); if (EndLoc.isValid()) { - DeclContext::decl_iterator next = *DI_current; - while (++next != DE_current) { - Decl *D_next = *next; - if (!D_next) - break; - SourceLocation L = D_next->getLocStart(); - if (!L.isValid()) - break; - if (SM.isBeforeInTranslationUnit(L, EndLoc)) { - *DI_current = next; - DeclsInContainer.push_back(D_next); - continue; - } - break; + if (DI_current) { + addRangedDeclsInContainer(DI_current, DE_current, SM, EndLoc, + DeclsInContainer); + } else { + addRangedDeclsInContainer(FileDI_current, FileDE_current, SM, EndLoc, + DeclsInContainer); } } @@ -4517,10 +4538,7 @@ public: void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); } enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent); - void AnnotateTokens(CXCursor parent); - void AnnotateTokens() { - AnnotateTokens(clang_getTranslationUnitCursor(AnnotateVis.getTU())); - } + void AnnotateTokens(); /// \brief Determine whether the annotator saw any cursors that have /// context-sensitive keywords. @@ -4530,10 +4548,10 @@ public: }; } -void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) { +void AnnotateTokensWorker::AnnotateTokens() { // Walk the AST within the region of interest, annotating tokens // along the way. - VisitChildren(parent); + AnnotateVis.visitFileRegion(); for (unsigned I = 0 ; I < TokIdx ; ++I) { AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]); @@ -4549,6 +4567,9 @@ void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) { const CXCursor &C = clang_getNullCursor(); for (unsigned I = TokIdx ; I < NumTokens ; ++I) { + if (I < PreprocessingTokIdx && clang_isPreprocessing(Cursors[I].kind)) + continue; + AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]); Cursors[I] = (Pos == Annotated.end()) ? C : Pos->second; } diff --git a/tools/libclang/CursorVisitor.h b/tools/libclang/CursorVisitor.h index eaefd83716..d3fa70d8a2 100644 --- a/tools/libclang/CursorVisitor.h +++ b/tools/libclang/CursorVisitor.h @@ -87,6 +87,8 @@ class CursorVisitor : public DeclVisitor, // iteration over all Decls contained lexically within an ObjC container. DeclContext::decl_iterator *DI_current; DeclContext::decl_iterator DE_current; + SmallVectorImpl::iterator *FileDI_current; + SmallVectorImpl::iterator FileDE_current; // Cache of pre-allocated worklists for data-recursion walk of Stmts. SmallVector WorkListFreeList; @@ -134,7 +136,7 @@ public: Visitor(Visitor), ClientData(ClientData), VisitPreprocessorLast(VisitPreprocessorLast), VisitIncludedEntities(VisitIncludedPreprocessingEntries), - RegionOfInterest(RegionOfInterest), DI_current(0) + RegionOfInterest(RegionOfInterest), DI_current(0), FileDI_current(0) { Parent.kind = CXCursor_NoDeclFound; Parent.data[0] = 0;