diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /clang/lib/Tooling/Syntax | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'clang/lib/Tooling/Syntax')
| -rw-r--r-- | clang/lib/Tooling/Syntax/BuildTree.cpp | 38 | ||||
| -rw-r--r-- | clang/lib/Tooling/Syntax/Tokens.cpp | 32 |
2 files changed, 68 insertions, 2 deletions
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 7654e3dfaa01..07888b5c32fa 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -294,11 +294,12 @@ static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, SourceRange Initializer) { SourceLocation Start = GetStartLoc().Visit(T); SourceLocation End = T.getEndLoc(); - assert(End.isValid()); if (Name.isValid()) { if (Start.isInvalid()) Start = Name; - if (SM.isBeforeInTranslationUnit(End, Name)) + // End of TypeLoc could be invalid if the type is invalid, fallback to the + // NameLoc. + if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name)) End = Name; } if (Initializer.isValid()) { @@ -800,6 +801,30 @@ public: return true; } + bool TraverseIfStmt(IfStmt *S) { + bool Result = [&, this]() { + if (S->getInit() && !TraverseStmt(S->getInit())) { + return false; + } + // In cases where the condition is an initialized declaration in a + // statement, we want to preserve the declaration and ignore the + // implicit condition expression in the syntax tree. + if (S->hasVarStorage()) { + if (!TraverseStmt(S->getConditionVariableDeclStmt())) + return false; + } else if (S->getCond() && !TraverseStmt(S->getCond())) + return false; + + if (S->getThen() && !TraverseStmt(S->getThen())) + return false; + if (S->getElse() && !TraverseStmt(S->getElse())) + return false; + return true; + }(); + WalkUpFromIfStmt(S); + return Result; + } + bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) { // We override to traverse range initializer as VarDecl. // RAV traverses it as a statement, we produce invalid node kinds in that @@ -831,6 +856,11 @@ public: return RecursiveASTVisitor::TraverseStmt(S); } + bool TraverseOpaqueValueExpr(OpaqueValueExpr *VE) { + // OpaqueValue doesn't correspond to concrete syntax, ignore it. + return true; + } + // Some expressions are not yet handled by syntax trees. bool WalkUpFromExpr(Expr *E) { assert(!isImplicitExpr(E) && "should be handled by TraverseStmt"); @@ -1426,6 +1456,10 @@ public: bool WalkUpFromIfStmt(IfStmt *S) { Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword); + Stmt *ConditionStatement = S->getCond(); + if (S->hasVarStorage()) + ConditionStatement = S->getConditionVariableDeclStmt(); + Builder.markStmtChild(ConditionStatement, syntax::NodeRole::Condition); Builder.markStmtChild(S->getThen(), syntax::NodeRole::ThenStatement); Builder.markChildToken(S->getElseLoc(), syntax::NodeRole::ElseKeyword); Builder.markStmtChild(S->getElse(), syntax::NodeRole::ElseStatement); diff --git a/clang/lib/Tooling/Syntax/Tokens.cpp b/clang/lib/Tooling/Syntax/Tokens.cpp index 234df9cb7182..8a31e776d030 100644 --- a/clang/lib/Tooling/Syntax/Tokens.cpp +++ b/clang/lib/Tooling/Syntax/Tokens.cpp @@ -183,7 +183,39 @@ llvm::StringRef FileRange::text(const SourceManager &SM) const { return Text.substr(Begin, length()); } +void TokenBuffer::indexExpandedTokens() { + // No-op if the index is already created. + if (!ExpandedTokIndex.empty()) + return; + ExpandedTokIndex.reserve(ExpandedTokens.size()); + // Index ExpandedTokens for faster lookups by SourceLocation. + for (size_t I = 0, E = ExpandedTokens.size(); I != E; ++I) { + SourceLocation Loc = ExpandedTokens[I].location(); + if (Loc.isValid()) + ExpandedTokIndex[Loc] = I; + } +} + llvm::ArrayRef<syntax::Token> TokenBuffer::expandedTokens(SourceRange R) const { + if (R.isInvalid()) + return {}; + if (!ExpandedTokIndex.empty()) { + // Quick lookup if `R` is a token range. + // This is a huge win since majority of the users use ranges provided by an + // AST. Ranges in AST are token ranges from expanded token stream. + const auto B = ExpandedTokIndex.find(R.getBegin()); + const auto E = ExpandedTokIndex.find(R.getEnd()); + if (B != ExpandedTokIndex.end() && E != ExpandedTokIndex.end()) { + const Token *L = ExpandedTokens.data() + B->getSecond(); + // Add 1 to End to make a half-open range. + const Token *R = ExpandedTokens.data() + E->getSecond() + 1; + if (L > R) + return {}; + return {L, R}; + } + } + // Slow case. Use `isBeforeInTranslationUnit` to binary search for the + // required range. return getTokensCovering(expandedTokens(), R, *SourceMgr); } |
