[clang-format] Link the braces of a block in UnwrappedLineParser
authorOwen Pan <owenpiano@gmail.com>
Sat, 3 Dec 2022 15:16:32 +0000 (07:16 -0800)
committerOwen Pan <owenpiano@gmail.com>
Sun, 4 Dec 2022 20:01:26 +0000 (12:01 -0800)
This includes TT_MacroBlockBegin and TT_MacroBlockEnd as well.

We can no longer use MatchingParen of FormatToken as an indicator
to mark optional braces. Instead, we directly set Optional of an
l_brace first and reset it later if it turns out that the braces
are not optional.

Also added a test case for deeply nested loops.

Differential Revision: https://reviews.llvm.org/D139257

clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/BracesRemoverTest.cpp

index e6bb9c4..d665a4b 100644 (file)
@@ -934,6 +934,9 @@ FormatToken *UnwrappedLineParser::parseBlock(
     return IfLBrace;
   }
 
+  Tok->MatchingParen = FormatTok;
+  FormatTok->MatchingParen = Tok;
+
   const bool IsFunctionRBrace =
       FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
 
@@ -967,10 +970,7 @@ FormatToken *UnwrappedLineParser::parseBlock(
     }
     return mightFitOnOneLine((*CurrentLines)[Index], Tok);
   };
-  if (RemoveBraces()) {
-    Tok->MatchingParen = FormatTok;
-    FormatTok->MatchingParen = Tok;
-  }
+  Tok->Optional = RemoveBraces();
 
   size_t PPEndHash = computePPHash();
 
@@ -2707,10 +2707,20 @@ static void markOptionalBraces(FormatToken *LeftBrace) {
 
   assert(RightBrace->is(tok::r_brace));
   assert(RightBrace->MatchingParen == LeftBrace);
-  assert(LeftBrace->Optional == RightBrace->Optional);
 
-  LeftBrace->Optional = true;
-  RightBrace->Optional = true;
+  RightBrace->Optional = LeftBrace->Optional;
+}
+
+static void resetOptional(FormatToken *LeftBrace) {
+  if (!LeftBrace)
+    return;
+
+  const auto *RightBrace = LeftBrace->MatchingParen;
+  const bool IsOptionalRightBrace = RightBrace && RightBrace->Optional;
+  assert(LeftBrace->Optional || !IsOptionalRightBrace);
+
+  if (!IsOptionalRightBrace)
+    LeftBrace->Optional = false;
 }
 
 void UnwrappedLineParser::handleAttributes() {
@@ -2770,8 +2780,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
 
   if (Style.RemoveBracesLLVM) {
     assert(!NestedTooDeep.empty());
-    KeepIfBraces = KeepIfBraces ||
-                   (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
+    KeepIfBraces = KeepIfBraces || (IfLeftBrace && !IfLeftBrace->Optional) ||
                    NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
                    IfBlockKind == IfStmtKind::IfElseIf;
   }
@@ -2802,8 +2811,9 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
                          ElseBlockKind == IfStmtKind::IfElseIf;
       } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
         KeepElseBraces = true;
+        assert(ElseLeftBrace->Optional);
         assert(ElseLeftBrace->MatchingParen);
-        markOptionalBraces(ElseLeftBrace);
+        ElseLeftBrace->MatchingParen->Optional = true;
       }
       addUnwrappedLine();
     } else if (FormatTok->is(tok::kw_if)) {
@@ -2838,7 +2848,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
 
   assert(!NestedTooDeep.empty());
   KeepElseBraces = KeepElseBraces ||
-                   (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
+                   (ElseLeftBrace && !ElseLeftBrace->Optional) ||
                    NestedTooDeep.back();
 
   NestedTooDeep.pop_back();
@@ -2846,17 +2856,11 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
   if (!KeepIfBraces && !KeepElseBraces) {
     markOptionalBraces(IfLeftBrace);
     markOptionalBraces(ElseLeftBrace);
-  } else if (IfLeftBrace) {
-    FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
-    if (IfRightBrace) {
-      assert(IfRightBrace->MatchingParen == IfLeftBrace);
-      assert(!IfLeftBrace->Optional);
-      assert(!IfRightBrace->Optional);
-      IfLeftBrace->MatchingParen = nullptr;
-      IfRightBrace->MatchingParen = nullptr;
-    }
   }
 
+  resetOptional(IfLeftBrace);
+  resetOptional(ElseLeftBrace);
+
   if (IfKind)
     *IfKind = Kind;
 
@@ -3071,6 +3075,7 @@ void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {
       if (!NestedTooDeep.back())
         markOptionalBraces(LeftBrace);
     }
+    resetOptional(LeftBrace);
     if (WrapRightBrace)
       addUnwrappedLine();
   } else {
index 9c33a70..dea551c 100644 (file)
@@ -204,6 +204,20 @@ TEST_F(BracesRemoverTest, RemoveBraces) {
                "while (j < 0) { ++j; }",
                Style);
 
+  verifyFormat("for (;;) {\n"
+               "  for (;;)\n"
+               "    for (;;)\n"
+               "      a;\n"
+               "}",
+               "for (;;) {\n"
+               "  for (;;) {\n"
+               "    for (;;) {\n"
+               "      a;\n"
+               "    }\n"
+               "  }\n"
+               "}",
+               Style);
+
   verifyFormat("if (a)\n"
                "  b; // comment\n"
                "else if (c)\n"