diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 97500ee41259f..df44e6994c478 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1803,7 +1803,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, } if (Current.MatchingParen && Current.is(BK_Block)) { - moveStateToNewBlock(State); + moveStateToNewBlock(State, Newline); return; } @@ -1991,7 +1991,7 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) { } } -void ContinuationIndenter::moveStateToNewBlock(LineState &State) { +void ContinuationIndenter::moveStateToNewBlock(LineState &State, bool NewLine) { if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope && State.NextToken->is(TT_LambdaLBrace) && !State.Line->MightBeFunctionDecl) { @@ -2003,10 +2003,18 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State) { NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace) ? Style.ObjCBlockIndentWidth : Style.IndentWidth); + + // Even when wrapping before lambda body, the left brace can still be added to + // the same line. This occurs when checking whether the whole lambda body can + // go on a single line. In this case we have to make sure there are no line + // breaks in the body, otherwise we could just end up with a regular lambda + // body without the brace wrapped. + bool NoLineBreak = Style.BraceWrapping.BeforeLambdaBody && !NewLine && + State.NextToken->is(TT_LambdaLBrace); + State.Stack.push_back(ParenState(State.NextToken, NewIndent, State.Stack.back().LastSpace, - /*AvoidBinPacking=*/true, - /*NoLineBreak=*/false)); + /*AvoidBinPacking=*/true, NoLineBreak)); State.Stack.back().NestedBlockIndent = NestedBlockIndent; State.Stack.back().BreakBeforeParameter = true; } diff --git a/clang/lib/Format/ContinuationIndenter.h b/clang/lib/Format/ContinuationIndenter.h index 057b85bd32d50..2598947bb624c 100644 --- a/clang/lib/Format/ContinuationIndenter.h +++ b/clang/lib/Format/ContinuationIndenter.h @@ -104,7 +104,7 @@ class ContinuationIndenter { /// Update 'State' according to the next token being one of ")>}]". void moveStatePastScopeCloser(LineState &State); /// Update 'State' with the next token opening a nested block. - void moveStateToNewBlock(LineState &State); + void moveStateToNewBlock(LineState &State, bool NewLine); /// Reformats a raw string literal. /// diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index d9e369296eed1..24f62af8ddcb8 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -22893,6 +22893,19 @@ TEST_F(FormatTest, FormatsLambdas) { LLVMWithBeforeLambdaBody); verifyFormat("FctWithTwoParams_SLS_All([]() { return 43; }, 87);", LLVMWithBeforeLambdaBody); + verifyFormat( + "FctWithTwoParams_SLS_All(\n" + " 87, []() { return LongLineThatWillForceBothParamsToNewLine(); });", + LLVMWithBeforeLambdaBody); + verifyFormat( + "FctWithTwoParams_SLS_All(\n" + " 87,\n" + " []()\n" + " {\n" + " return " + "LongLineThatWillForceTheLambdaBodyToBeBrokenIntoMultipleLines();\n" + " });", + LLVMWithBeforeLambdaBody); verifyFormat("FctWithOneNestedLambdas_SLS_All([]() { return 17; });", LLVMWithBeforeLambdaBody); verifyFormat(