[Syntax] Support condition for IfStmt.
authorHaojian Wu <hokein.wu@gmail.com>
Mon, 1 Feb 2021 12:45:42 +0000 (13:45 +0100)
committerHaojian Wu <hokein.wu@gmail.com>
Thu, 4 Feb 2021 08:15:30 +0000 (09:15 +0100)
Differential Revision: https://reviews.llvm.org/D95782

clang/lib/Tooling/Syntax/BuildTree.cpp
clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
clang/unittests/Tooling/Syntax/SynthesisTest.cpp

index 7654e3d..62573b6 100644 (file)
@@ -800,6 +800,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
@@ -1426,6 +1450,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);
index 17e1bbe..1f950b0 100644 (file)
@@ -204,8 +204,9 @@ void test() {
 IfStatement Statement
 |-'if' IntroducerKeyword
 |-'('
-|-IntegerLiteralExpression
-| `-'1' LiteralToken
+|-ExpressionStatement Condition
+| `-IntegerLiteralExpression Expression
+|   `-'1' LiteralToken
 |-')'
 `-CompoundStatement ThenStatement
   |-'{' OpenParen
@@ -215,8 +216,9 @@ IfStatement Statement
 IfStatement Statement
 |-'if' IntroducerKeyword
 |-'('
-|-IntegerLiteralExpression
-| `-'1' LiteralToken
+|-ExpressionStatement Condition
+| `-IntegerLiteralExpression Expression
+|   `-'1' LiteralToken
 |-')'
 |-CompoundStatement ThenStatement
 | |-'{' OpenParen
@@ -225,8 +227,9 @@ IfStatement Statement
 `-IfStatement ElseStatement
   |-'if' IntroducerKeyword
   |-'('
-  |-IntegerLiteralExpression
-  | `-'0' LiteralToken
+  |-ExpressionStatement Condition
+  | `-IntegerLiteralExpression Expression
+  |   `-'0' LiteralToken
   |-')'
   `-CompoundStatement ThenStatement
     |-'{' OpenParen
@@ -234,6 +237,61 @@ IfStatement Statement
 )txt"}));
 }
 
+TEST_P(BuildSyntaxTreeTest, IfDecl) {
+  if (!GetParam().isCXX17OrLater()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqualOnAnnotations(
+      R"cpp(
+void test() {
+  [[if (int a = 5) {}]]
+  [[if (int a; a == 5) {}]]
+}
+)cpp",
+      {R"txt(
+IfStatement Statement
+|-'if' IntroducerKeyword
+|-'('
+|-DeclarationStatement Condition
+| `-SimpleDeclaration
+|   |-'int'
+|   `-DeclaratorList Declarators
+|     `-SimpleDeclarator ListElement
+|       |-'a'
+|       |-'='
+|       `-IntegerLiteralExpression
+|         `-'5' LiteralToken
+|-')'
+`-CompoundStatement ThenStatement
+  |-'{' OpenParen
+  `-'}' CloseParen
+      )txt",
+       R"txt(
+IfStatement Statement
+|-'if' IntroducerKeyword
+|-'('
+|-DeclarationStatement
+| |-SimpleDeclaration
+| | |-'int'
+| | `-DeclaratorList Declarators
+| |   `-SimpleDeclarator ListElement
+| |     `-'a'
+| `-';'
+|-ExpressionStatement Condition
+| `-BinaryOperatorExpression Expression
+|   |-IdExpression LeftHandSide
+|   | `-UnqualifiedId UnqualifiedId
+|   |   `-'a'
+|   |-'==' OperatorToken
+|   `-IntegerLiteralExpression RightHandSide
+|     `-'5' LiteralToken
+|-')'
+`-CompoundStatement ThenStatement
+  |-'{' OpenParen
+  `-'}' CloseParen
+)txt"}));
+}
+
 TEST_P(BuildSyntaxTreeTest, For) {
   EXPECT_TRUE(treeDumpEqualOnAnnotations(
       R"cpp(
@@ -420,8 +478,9 @@ TranslationUnit Detached
     |-IfStatement Statement
     | |-'if' IntroducerKeyword
     | |-'('
-    | |-IntegerLiteralExpression
-    | | `-'1' LiteralToken
+    | |-ExpressionStatement Condition
+    | | `-IntegerLiteralExpression Expression
+    | |   `-'1' LiteralToken
     | |-')'
     | |-ExpressionStatement ThenStatement
     | | |-CallExpression Expression
@@ -3992,12 +4051,13 @@ TranslationUnit Detached
     |-IfStatement Statement
     | |-'if' IntroducerKeyword unmodifiable
     | |-'(' unmodifiable
-    | |-BinaryOperatorExpression unmodifiable
-    | | |-IntegerLiteralExpression LeftHandSide unmodifiable
-    | | | `-'1' LiteralToken unmodifiable
-    | | |-'+' OperatorToken unmodifiable
-    | | `-IntegerLiteralExpression RightHandSide unmodifiable
-    | |   `-'1' LiteralToken unmodifiable
+    | |-ExpressionStatement Condition unmodifiable
+    | | `-BinaryOperatorExpression Expression unmodifiable
+    | |   |-IntegerLiteralExpression LeftHandSide unmodifiable
+    | |   | `-'1' LiteralToken unmodifiable
+    | |   |-'+' OperatorToken unmodifiable
+    | |   `-IntegerLiteralExpression RightHandSide unmodifiable
+    | |     `-'1' LiteralToken unmodifiable
     | |-')' unmodifiable
     | |-CompoundStatement ThenStatement unmodifiable
     | | |-'{' OpenParen unmodifiable
@@ -4076,12 +4136,13 @@ TranslationUnit Detached
     |-IfStatement Statement
     | |-'if' IntroducerKeyword unmodifiable
     | |-'(' unmodifiable
-    | |-BinaryOperatorExpression unmodifiable
-    | | |-IntegerLiteralExpression LeftHandSide
-    | | | `-'1' LiteralToken
-    | | |-'&&' OperatorToken unmodifiable
-    | | `-IntegerLiteralExpression RightHandSide
-    | |   `-'0' LiteralToken
+    | |-ExpressionStatement Condition unmodifiable
+    | | `-BinaryOperatorExpression Expression unmodifiable
+    | |   |-IntegerLiteralExpression LeftHandSide
+    | |   | `-'1' LiteralToken
+    | |   |-'&&' OperatorToken unmodifiable
+    | |   `-IntegerLiteralExpression RightHandSide
+    | |     `-'0' LiteralToken
     | |-')' unmodifiable
     | |-CompoundStatement ThenStatement unmodifiable
     | | |-'{' OpenParen unmodifiable
index b8c2334..a815989 100644 (file)
@@ -238,12 +238,13 @@ TranslationUnit Detached synthesized
     |-IfStatement Statement synthesized
     | |-'if' IntroducerKeyword synthesized
     | |-'(' synthesized
-    | |-BinaryOperatorExpression synthesized
-    | | |-IntegerLiteralExpression LeftHandSide synthesized
-    | | | `-'1' LiteralToken synthesized
-    | | |-'+' OperatorToken synthesized
-    | | `-IntegerLiteralExpression RightHandSide synthesized
-    | |   `-'1' LiteralToken synthesized
+    | |-ExpressionStatement Condition synthesized
+    | | `-BinaryOperatorExpression Expression synthesized
+    | |   |-IntegerLiteralExpression LeftHandSide synthesized
+    | |   | `-'1' LiteralToken synthesized
+    | |   |-'+' OperatorToken synthesized
+    | |   `-IntegerLiteralExpression RightHandSide synthesized
+    | |     `-'1' LiteralToken synthesized
     | |-')' synthesized
     | |-CompoundStatement ThenStatement synthesized
     | | |-'{' OpenParen synthesized