aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Tooling/Syntax/BuildTree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Tooling/Syntax/BuildTree.cpp')
-rw-r--r--clang/lib/Tooling/Syntax/BuildTree.cpp38
1 files changed, 36 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);