[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-02 Thread Björn Schäpers via cfe-commits


@@ -366,8 +366,14 @@ bool ContinuationIndenter::mustBreak(const LineState 
) {
   const auto  = State.Stack.back();
   if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
   Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) {
-auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
-return LambdaBodyLength > getColumnLimit(State);
+if (Current.MatchingParen->MustBreakBefore)

HazardyKnusperkeks wrote:

> I noticed there is code in `TokenAnnotator` than can set `MustBreakBefore` on 
> the lambda left brace token:
> 
> https://github.com/llvm/llvm-project/blob/0e01c72c5645259d9a08a1a7ed39cb5cc41ce311/clang/lib/Format/TokenAnnotator.cpp#L5297-L5299
> 
> Introduced in 
> [37c2233](https://github.com/llvm/llvm-project/commit/37c2233097ac44697b87228d86eef1fce10ea5c1)
>  seemingly for code like this:
> 
> ```c++
> auto select = [this]() -> std::unique_ptr { return 
> MyAssignment::SelectFromList(this); }
> ```
> 
> Both before this current PR and here the `MustBreakBefore` field of the 
> `Current` token is ignored. Should behavior change to observe this and thus 
> force a break?
> 
> Would seem the _BraceWrapping.BeforeLambdaBody_ setting would then force 
> lambda across multiple lines if on, but not if off.
> 
> Should the code in `TokenAnnotator` be changed and maybe only set 
> `CanBreakBefore`?

So as far as I put everything together we should break before the `{`, if 
`BeforeLambdaBody` is set. Except for short lambdas, if 
`AllowShortLambdasOnASingleLine` matches our lambda **and** it would fit on a 
single line. If the lambda has to be broken somewhere, it should break before 
`{`.

What is needed to be changed I don't know, but also have not the time to 
investigate. I'm willing to hear your analysis, or maybe @mydeveloperday can 
shed some light into the issue?

https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-02 Thread Björn Schäpers via cfe-commits


@@ -22965,6 +22965,84 @@ TEST_F(FormatTest, EmptyLinesInLambdas) {
"};");
 }
 
+TEST_F(FormatTest, BreakBeforeLambdaBodyWrapping) {
+  verifyFormat("connect([]() {\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});");
+
+  auto Style = getLLVMStyle();
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.BeforeLambdaBody = true;
+
+  verifyFormat("connect(\n"
+   "[]()\n"
+   "{\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});",
+   Style);
+
+  for (unsigned l : {0, 41}) {

HazardyKnusperkeks wrote:

They make it hard to see which is failing, yes. But also why introduce 
additional runtime for the tests, if there is no real gain?

https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread James Grant via cfe-commits

https://github.com/jamesg-nz edited 
https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread James Grant via cfe-commits


@@ -366,8 +366,14 @@ bool ContinuationIndenter::mustBreak(const LineState 
) {
   const auto  = State.Stack.back();
   if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
   Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) {
-auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
-return LambdaBodyLength > getColumnLimit(State);
+if (Current.MatchingParen->MustBreakBefore)

jamesg-nz wrote:

I noticed there is code in `TokenAnnotator` than can set `MustBreakBefore` on 
the lambda left brace token:
https://github.com/llvm/llvm-project/blob/0e01c72c5645259d9a08a1a7ed39cb5cc41ce311/clang/lib/Format/TokenAnnotator.cpp#L5297-L5299
Introduced in 37c2233097ac44697b87228d86eef1fce10ea5c1 seemingly for code like 
this:

```cpp
auto select = [this]() -> std::unique_ptr { return 
MyAssignment::SelectFromList(this); }
```

Both before this current PR and here the `MustBreakBefore` state of the token 
is ignored. Should behavior change to observe this and thus force a break?

Would seem the _BraceWrapping.BeforeLambdaBody_ setting would then force lambda 
across multiple lines if on, but not if off.

Should the code in `TokenAnnotator` be changed and maybe only set 
`CanBreakBefore`?

https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread James Grant via cfe-commits


@@ -22965,6 +22965,84 @@ TEST_F(FormatTest, EmptyLinesInLambdas) {
"};");
 }
 
+TEST_F(FormatTest, BreakBeforeLambdaBodyWrapping) {
+  verifyFormat("connect([]() {\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});");
+
+  auto Style = getLLVMStyle();
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.BeforeLambdaBody = true;
+
+  verifyFormat("connect(\n"
+   "[]()\n"
+   "{\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});",
+   Style);
+
+  for (unsigned l : {0, 41}) {

jamesg-nz wrote:

Now testing ColumnLimit = 0 once separately. Unrolled remaining loop (that 
doesn't test = 0) into two verifications.

Loops make it hard to see in test results for what value it is failing for, I 
guess. Although saw other people had used them in that file.

https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread James Grant via cfe-commits

https://github.com/jamesg-nz updated 
https://github.com/llvm/llvm-project/pull/76673

>From 04885844162b5390d8041a44a1895ad6ac160228 Mon Sep 17 00:00:00 2001
From: James Grant <42079499+jamesg...@users.noreply.github.com>
Date: Mon, 1 Jan 2024 20:27:41 +1300
Subject: [PATCH 1/2] [clang-format] Fix erroneous
 BraceWrapping.BeforeLambdaBody column calcs

Firstly, must check ColumnLimit > 0 before comparing calculated columns
to the limit. Otherwise it always breaks before the brace if ColumnLimit
= 0 (no limit). Fixes #50275

Secondly, the lambda body length alone is currently compared with the
column limit. Should instead be comparing a column position, which
includes everything before the lambda body, the body length itself, and
any unbreakable tail. Fixes #59724

Thirdly, if must break before the lambda right brace, e.g. line comment
in body, then must also break before the left brace. Can't use column
calculation in this instance.
---
 clang/lib/Format/ContinuationIndenter.cpp | 10 ++-
 clang/unittests/Format/FormatTest.cpp | 78 +++
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 102504182c4505..f4f8b694f7ff51 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -366,8 +366,14 @@ bool ContinuationIndenter::mustBreak(const LineState 
) {
   const auto  = State.Stack.back();
   if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
   Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) {
-auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
-return LambdaBodyLength > getColumnLimit(State);
+if (Current.MatchingParen->MustBreakBefore)
+  return true;
+
+auto LambdaEnd = getLengthToMatchingParen(Current, State.Stack) +
+ Current.MatchingParen->UnbreakableTailLength +
+ State.Column - 1;
+
+return Style.ColumnLimit > 0 && LambdaEnd > getColumnLimit(State);
   }
   if (Current.MustBreakBefore ||
   (Current.is(TT_InlineASMColon) &&
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 881993ede17c3d..f5aadec3500ccb 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -22965,6 +22965,84 @@ TEST_F(FormatTest, EmptyLinesInLambdas) {
"};");
 }
 
+TEST_F(FormatTest, BreakBeforeLambdaBodyWrapping) {
+  verifyFormat("connect([]() {\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});");
+
+  auto Style = getLLVMStyle();
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.BeforeLambdaBody = true;
+
+  verifyFormat("connect(\n"
+   "[]()\n"
+   "{\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});",
+   Style);
+
+  for (unsigned l : {0, 41}) {
+Style.ColumnLimit = l;
+verifyFormat("auto lambda = []() { return foo + bar; };", Style);
+  }
+  for (unsigned l : {40, 22}) {
+Style.ColumnLimit = l;
+verifyFormat("auto lambda = []()\n"
+ "{ return foo + bar; };",
+ Style);
+  }
+  Style.ColumnLimit = 21;
+  verifyFormat("auto lambda = []()\n"
+   "{\n"
+   "  return foo + bar;\n"
+   "};",
+   Style);
+
+  for (unsigned l : {0, 67}) {
+Style.ColumnLimit = l;
+verifyFormat(
+"auto result = [](int foo, int bar) { return foo + bar; }(foo, bar);",
+Style);
+  }
+  Style.ColumnLimit = 66;
+  verifyFormat("auto result = [](int foo, int bar)\n"
+   "{ return foo + bar; }(foo, bar);",
+   Style);
+
+  Style.ColumnLimit = 36;
+  verifyFormat("myFunc([&]() { return foo + bar; });", Style);
+  Style.ColumnLimit = 35;
+  verifyFormat("myFunc([&]()\n"
+   "   { return foo + bar; });",
+   Style);
+
+  Style = getGoogleStyleWithColumns(100);
+  Style.BreakBeforeBraces = FormatStyle::BS_Allman;
+  Style.IndentWidth = 4;
+  verifyFormat(
+  "void Func()\n"
+  "{\n"
+  "[]()\n"
+  "{\n"
+  "return TestVeryLongThingName::TestVeryLongFunctionName()\n"
+  ".TestAnotherVeryVeryLongFunctionName();\n"
+  "}\n"
+  "}\n",
+  Style);
+  verifyFormat(
+  "void Func()\n"
+  "{\n"
+  "[]()\n"
+  "{\n"
+  "return TestVeryLongThingName::TestVeryLongFunctionName()\n"
+  ".TestAnotherVeryVeryVeryLongFunctionName();\n"
+  "}\n"
+  "}\n",
+  Style);
+}
+
 TEST_F(FormatTest, FormatsBlocks) {
   FormatStyle ShortBlocks = getLLVMStyle();
   ShortBlocks.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always;

>From 346e7da1f6eb184f7fc5212af94f5e7c83d5a494 Mon Sep 17 00:00:00 2001
From: James Grant 

[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread Björn Schäpers via cfe-commits


@@ -22965,6 +22965,84 @@ TEST_F(FormatTest, EmptyLinesInLambdas) {
"};");
 }
 
+TEST_F(FormatTest, BreakBeforeLambdaBodyWrapping) {
+  verifyFormat("connect([]() {\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});");
+
+  auto Style = getLLVMStyle();
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.BeforeLambdaBody = true;
+
+  verifyFormat("connect(\n"
+   "[]()\n"
+   "{\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});",
+   Style);
+
+  for (unsigned l : {0, 41}) {

HazardyKnusperkeks wrote:

Don't loop. Pick some values.

https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread James Grant via cfe-commits

jamesg-nz wrote:

n.b. there's relevant test coverage provided by existing 
`LambdaWithLineComments` test.


https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-format

Author: James Grant (jamesg-nz)


Changes

Firstly, must check ColumnLimit  0 before comparing calculated columns to 
the limit. Otherwise it always breaks before the brace if ColumnLimit = 0 (no 
limit). Fixes #50275

Secondly, the lambda body length alone is currently compared with the column 
limit. Should instead be comparing a column position, which includes everything 
before the lambda body, the body length itself, and any unbreakable tail. Fixes 
#59724

Thirdly, if must break before the lambda right brace, e.g. line comment in 
body, then must also break before the left brace. Can't use column calculation 
in this instance.

---
Full diff: https://github.com/llvm/llvm-project/pull/76673.diff


2 Files Affected:

- (modified) clang/lib/Format/ContinuationIndenter.cpp (+8-2) 
- (modified) clang/unittests/Format/FormatTest.cpp (+78) 


``diff
diff --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 102504182c4505..f4f8b694f7ff51 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -366,8 +366,14 @@ bool ContinuationIndenter::mustBreak(const LineState 
) {
   const auto  = State.Stack.back();
   if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
   Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) {
-auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
-return LambdaBodyLength > getColumnLimit(State);
+if (Current.MatchingParen->MustBreakBefore)
+  return true;
+
+auto LambdaEnd = getLengthToMatchingParen(Current, State.Stack) +
+ Current.MatchingParen->UnbreakableTailLength +
+ State.Column - 1;
+
+return Style.ColumnLimit > 0 && LambdaEnd > getColumnLimit(State);
   }
   if (Current.MustBreakBefore ||
   (Current.is(TT_InlineASMColon) &&
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 881993ede17c3d..f5aadec3500ccb 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -22965,6 +22965,84 @@ TEST_F(FormatTest, EmptyLinesInLambdas) {
"};");
 }
 
+TEST_F(FormatTest, BreakBeforeLambdaBodyWrapping) {
+  verifyFormat("connect([]() {\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});");
+
+  auto Style = getLLVMStyle();
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.BeforeLambdaBody = true;
+
+  verifyFormat("connect(\n"
+   "[]()\n"
+   "{\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});",
+   Style);
+
+  for (unsigned l : {0, 41}) {
+Style.ColumnLimit = l;
+verifyFormat("auto lambda = []() { return foo + bar; };", Style);
+  }
+  for (unsigned l : {40, 22}) {
+Style.ColumnLimit = l;
+verifyFormat("auto lambda = []()\n"
+ "{ return foo + bar; };",
+ Style);
+  }
+  Style.ColumnLimit = 21;
+  verifyFormat("auto lambda = []()\n"
+   "{\n"
+   "  return foo + bar;\n"
+   "};",
+   Style);
+
+  for (unsigned l : {0, 67}) {
+Style.ColumnLimit = l;
+verifyFormat(
+"auto result = [](int foo, int bar) { return foo + bar; }(foo, bar);",
+Style);
+  }
+  Style.ColumnLimit = 66;
+  verifyFormat("auto result = [](int foo, int bar)\n"
+   "{ return foo + bar; }(foo, bar);",
+   Style);
+
+  Style.ColumnLimit = 36;
+  verifyFormat("myFunc([&]() { return foo + bar; });", Style);
+  Style.ColumnLimit = 35;
+  verifyFormat("myFunc([&]()\n"
+   "   { return foo + bar; });",
+   Style);
+
+  Style = getGoogleStyleWithColumns(100);
+  Style.BreakBeforeBraces = FormatStyle::BS_Allman;
+  Style.IndentWidth = 4;
+  verifyFormat(
+  "void Func()\n"
+  "{\n"
+  "[]()\n"
+  "{\n"
+  "return TestVeryLongThingName::TestVeryLongFunctionName()\n"
+  ".TestAnotherVeryVeryLongFunctionName();\n"
+  "}\n"
+  "}\n",
+  Style);
+  verifyFormat(
+  "void Func()\n"
+  "{\n"
+  "[]()\n"
+  "{\n"
+  "return TestVeryLongThingName::TestVeryLongFunctionName()\n"
+  ".TestAnotherVeryVeryVeryLongFunctionName();\n"
+  "}\n"
+  "}\n",
+  Style);
+}
+
 TEST_F(FormatTest, FormatsBlocks) {
   FormatStyle ShortBlocks = getLLVMStyle();
   ShortBlocks.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always;

``




https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread via cfe-commits

github-actions[bot] wrote:

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from 
other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/76673
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs (PR #76673)

2024-01-01 Thread James Grant via cfe-commits

https://github.com/jamesg-nz created 
https://github.com/llvm/llvm-project/pull/76673

Firstly, must check ColumnLimit > 0 before comparing calculated columns to the 
limit. Otherwise it always breaks before the brace if ColumnLimit = 0 (no 
limit). Fixes #50275

Secondly, the lambda body length alone is currently compared with the column 
limit. Should instead be comparing a column position, which includes everything 
before the lambda body, the body length itself, and any unbreakable tail. Fixes 
#59724

Thirdly, if must break before the lambda right brace, e.g. line comment in 
body, then must also break before the left brace. Can't use column calculation 
in this instance.

>From 04885844162b5390d8041a44a1895ad6ac160228 Mon Sep 17 00:00:00 2001
From: James Grant <42079499+jamesg...@users.noreply.github.com>
Date: Mon, 1 Jan 2024 20:27:41 +1300
Subject: [PATCH] [clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody
 column calcs

Firstly, must check ColumnLimit > 0 before comparing calculated columns
to the limit. Otherwise it always breaks before the brace if ColumnLimit
= 0 (no limit). Fixes #50275

Secondly, the lambda body length alone is currently compared with the
column limit. Should instead be comparing a column position, which
includes everything before the lambda body, the body length itself, and
any unbreakable tail. Fixes #59724

Thirdly, if must break before the lambda right brace, e.g. line comment
in body, then must also break before the left brace. Can't use column
calculation in this instance.
---
 clang/lib/Format/ContinuationIndenter.cpp | 10 ++-
 clang/unittests/Format/FormatTest.cpp | 78 +++
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 102504182c4505..f4f8b694f7ff51 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -366,8 +366,14 @@ bool ContinuationIndenter::mustBreak(const LineState 
) {
   const auto  = State.Stack.back();
   if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
   Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) {
-auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
-return LambdaBodyLength > getColumnLimit(State);
+if (Current.MatchingParen->MustBreakBefore)
+  return true;
+
+auto LambdaEnd = getLengthToMatchingParen(Current, State.Stack) +
+ Current.MatchingParen->UnbreakableTailLength +
+ State.Column - 1;
+
+return Style.ColumnLimit > 0 && LambdaEnd > getColumnLimit(State);
   }
   if (Current.MustBreakBefore ||
   (Current.is(TT_InlineASMColon) &&
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 881993ede17c3d..f5aadec3500ccb 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -22965,6 +22965,84 @@ TEST_F(FormatTest, EmptyLinesInLambdas) {
"};");
 }
 
+TEST_F(FormatTest, BreakBeforeLambdaBodyWrapping) {
+  verifyFormat("connect([]() {\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});");
+
+  auto Style = getLLVMStyle();
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.BeforeLambdaBody = true;
+
+  verifyFormat("connect(\n"
+   "[]()\n"
+   "{\n"
+   "  foo();\n"
+   "  bar();\n"
+   "});",
+   Style);
+
+  for (unsigned l : {0, 41}) {
+Style.ColumnLimit = l;
+verifyFormat("auto lambda = []() { return foo + bar; };", Style);
+  }
+  for (unsigned l : {40, 22}) {
+Style.ColumnLimit = l;
+verifyFormat("auto lambda = []()\n"
+ "{ return foo + bar; };",
+ Style);
+  }
+  Style.ColumnLimit = 21;
+  verifyFormat("auto lambda = []()\n"
+   "{\n"
+   "  return foo + bar;\n"
+   "};",
+   Style);
+
+  for (unsigned l : {0, 67}) {
+Style.ColumnLimit = l;
+verifyFormat(
+"auto result = [](int foo, int bar) { return foo + bar; }(foo, bar);",
+Style);
+  }
+  Style.ColumnLimit = 66;
+  verifyFormat("auto result = [](int foo, int bar)\n"
+   "{ return foo + bar; }(foo, bar);",
+   Style);
+
+  Style.ColumnLimit = 36;
+  verifyFormat("myFunc([&]() { return foo + bar; });", Style);
+  Style.ColumnLimit = 35;
+  verifyFormat("myFunc([&]()\n"
+   "   { return foo + bar; });",
+   Style);
+
+  Style = getGoogleStyleWithColumns(100);
+  Style.BreakBeforeBraces = FormatStyle::BS_Allman;
+  Style.IndentWidth = 4;
+  verifyFormat(
+  "void Func()\n"
+  "{\n"
+  "[]()\n"
+  "{\n"
+  "return TestVeryLongThingName::TestVeryLongFunctionName()\n"
+  ".TestAnotherVeryVeryLongFunctionName();\n"