diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -856,6 +856,11 @@ 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"); diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -512,6 +512,25 @@ )txt")); } +TEST_P(BuildSyntaxTreeTest, ConditionalOperator) { + // FIXME: conditional expression is not modeled yet. + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +void test() { + [[1?:2]]; +} +)cpp", + {R"txt( +UnknownExpression Expression +|-IntegerLiteralExpression +| `-'1' LiteralToken +|-'?' +|-':' +`-IntegerLiteralExpression + `-'2' LiteralToken +)txt"})); +} + TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Identifier) { EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp(