Index: clang/lib/Format/UnwrappedLineParser.h =================================================================== --- clang/lib/Format/UnwrappedLineParser.h +++ clang/lib/Format/UnwrappedLineParser.h @@ -110,7 +110,8 @@ const FormatToken *OpeningBrace = nullptr) const; FormatToken *parseBlock(bool MustBeDeclaration = false, unsigned AddLevels = 1u, bool MunchSemi = true, - bool KeepBraces = true, IfStmtKind *IfKind = nullptr, + bool *KeepBraces = nullptr, + IfStmtKind *IfKind = nullptr, bool UnindentWhitesmithsBraces = false, bool CanContainBracedList = true, TokenType NextLBracesType = TT_Unknown); Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -533,7 +533,7 @@ continue; } parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, - /*MunchSemi=*/true, /*KeepBraces=*/true, /*IfKind=*/nullptr, + /*MunchSemi=*/true, /*KeepBraces=*/nullptr, /*IfKind=*/nullptr, /*UnindentWhitesmithsBraces=*/false, CanContainBracedList, NextLBracesType); ++StatementCount; @@ -836,9 +836,23 @@ return Line.Level * Style.IndentWidth + Length <= ColumnLimit; } +/// \brief Parses a Block. +/// \param[in] MustBeDeclaration If the block is for a declaration. +/// \param[in] AddLevels How many levels should be added to the lines. +/// \param[in] MunchSemi If a trailing semi should be munched. +/// \param[in,out] KeepBraces If not provided it's the same as if it is provided +/// and set to \c true. If provided it will be set to \c true, if the braces of +/// this block have to be kept (and thus also the braces of the outer scopes). +/// \param[in] IfKind +/// \param[in] UnindentWhitesmithsBraces If the brace has to be unindented, +/// because of Whitesmith brace indenting. +/// \param[in] CanContainBracedList If the block can contain braced init lists. +/// \param[in] NextLBracesType The type for the next found left braces, when +/// it's set to something different than TT_Unknown. +/// \return FormatToken *UnwrappedLineParser::parseBlock( - bool MustBeDeclaration, unsigned AddLevels, bool MunchSemi, bool KeepBraces, - IfStmtKind *IfKind, bool UnindentWhitesmithsBraces, + bool MustBeDeclaration, unsigned AddLevels, bool MunchSemi, + bool *KeepBraces, IfStmtKind *IfKind, bool UnindentWhitesmithsBraces, bool CanContainBracedList, TokenType NextLBracesType) { auto HandleVerilogBlockLabel = [this]() { // ":" name @@ -932,7 +946,7 @@ if (WrappedOpeningBrace && FollowedByComment) return false; const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional; - if (KeepBraces && !HasRequiredIfBraces) + if ((!KeepBraces || *KeepBraces) && !HasRequiredIfBraces) return false; if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) { const FormatToken *Previous = Tokens->getPreviousToken(); @@ -953,10 +967,13 @@ } return mightFitOnOneLine((*CurrentLines)[Index], Tok); }; - if (RemoveBraces()) { - Tok->MatchingParen = FormatTok; - FormatTok->MatchingParen = Tok; - } + if (RemoveBraces()) + Tok->Optional = FormatTok->Optional = true; + else if (KeepBraces) + *KeepBraces = true; + + Tok->MatchingParen = FormatTok; + FormatTok->MatchingParen = Tok; size_t PPEndHash = computePPHash(); @@ -2676,10 +2693,8 @@ --Line->Level; } -static void markOptionalBraces(FormatToken *LeftBrace) { - if (!LeftBrace) - return; - +static void markOptionalBraces(FormatToken *LeftBrace, bool Optional) { + assert(LeftBrace); assert(LeftBrace->is(tok::l_brace)); FormatToken *RightBrace = LeftBrace->MatchingParen; @@ -2692,8 +2707,8 @@ assert(RightBrace->MatchingParen == LeftBrace); assert(LeftBrace->Optional == RightBrace->Optional); - LeftBrace->Optional = true; - RightBrace->Optional = true; + LeftBrace->Optional = Optional; + RightBrace->Optional = Optional; } void UnwrappedLineParser::handleAttributes() { @@ -2742,7 +2757,7 @@ IfLeftBrace = FormatTok; CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, - /*MunchSemi=*/true, KeepIfBraces, &IfBlockKind); + /*MunchSemi=*/true, &KeepIfBraces, &IfBlockKind); if (Style.BraceWrapping.BeforeElse) addUnwrappedLine(); else @@ -2753,13 +2768,13 @@ if (Style.RemoveBracesLLVM) { assert(!NestedTooDeep.empty()); - KeepIfBraces = KeepIfBraces || - (IfLeftBrace && !IfLeftBrace->MatchingParen) || - NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly || + KeepIfBraces = KeepIfBraces || NestedTooDeep.back() || + IfBlockKind == IfStmtKind::IfOnly || IfBlockKind == IfStmtKind::IfElseIf; } bool KeepElseBraces = KeepIfBraces; + bool MergeElseIf = false; FormatToken *ElseLeftBrace = nullptr; IfStmtKind Kind = IfStmtKind::IfOnly; @@ -2778,15 +2793,15 @@ IfStmtKind ElseBlockKind = IfStmtKind::NotIf; FormatToken *IfLBrace = parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, - /*MunchSemi=*/true, KeepElseBraces, &ElseBlockKind); + /*MunchSemi=*/true, &KeepElseBraces, &ElseBlockKind); if (FormatTok->is(tok::kw_else)) { KeepElseBraces = KeepElseBraces || ElseBlockKind == IfStmtKind::IfOnly || ElseBlockKind == IfStmtKind::IfElseIf; } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) { KeepElseBraces = true; + MergeElseIf = true; assert(ElseLeftBrace->MatchingParen); - markOptionalBraces(ElseLeftBrace); } addUnwrappedLine(); } else if (FormatTok->is(tok::kw_if)) { @@ -2810,6 +2825,8 @@ } else { parseUnbracedBody(/*CheckEOF=*/true); } + KeepElseBraces = + KeepElseBraces || (ElseLeftBrace && !ElseLeftBrace->Optional); } else { KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse; if (NeedsUnwrappedLine) @@ -2820,25 +2837,15 @@ return nullptr; assert(!NestedTooDeep.empty()); - KeepElseBraces = KeepElseBraces || - (ElseLeftBrace && !ElseLeftBrace->MatchingParen) || - NestedTooDeep.back(); + KeepElseBraces = KeepElseBraces || NestedTooDeep.back(); NestedTooDeep.pop_back(); - 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; - } - } + bool DropBraces = !KeepIfBraces && !KeepElseBraces; + if (IfLeftBrace) + markOptionalBraces(IfLeftBrace, DropBraces); + if (ElseLeftBrace) + markOptionalBraces(ElseLeftBrace, DropBraces || MergeElseIf); if (IfKind) *IfKind = Kind; @@ -2980,7 +2987,7 @@ ++Line->Level; parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true, - /*KeepBraces=*/true, /*IfKind=*/nullptr, + /*KeepBraces=*/nullptr, /*IfKind=*/nullptr, ManageWhitesmithsBraces); // Munch the semicolon after a namespace. This is more common than one would @@ -3048,11 +3055,11 @@ FormatToken *LeftBrace = FormatTok; CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, - /*MunchSemi=*/true, KeepBraces); + /*MunchSemi=*/true, &KeepBraces); if (!KeepBraces) { assert(!NestedTooDeep.empty()); if (!NestedTooDeep.back()) - markOptionalBraces(LeftBrace); + markOptionalBraces(LeftBrace, true); } if (WrapRightBrace) addUnwrappedLine();