diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -968,6 +968,24 @@
} else {
}
+ * ``bool BeforeLambdaBody`` Wrap lambda block.
+
+ .. code-block:: c++
+
+ true:
+ connect(
+ []()
+ {
+ foo();
+ bar();
+ });
+
+ false:
+ connect([]() {
+ foo();
+ bar();
+ });
+
* ``bool IndentBraces`` Indent the wrapped braces themselves.
* ``bool SplitEmptyFunction`` If ``false``, empty function body can be put on a single line.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1,272 +1,291 @@
-========================================
-Clang 11.0.0 (In-Progress) Release Notes
-========================================
-
-.. contents::
- :local:
- :depth: 2
-
-Written by the `LLVM Team `_
-
-.. warning::
-
- These are in-progress notes for the upcoming Clang 11 release.
- Release notes for previous releases can be found on
- `the Download Page `_.
-
-Introduction
-============
-
-This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release 11.0.0. Here we
-describe the status of Clang in some detail, including major
-improvements from the previous release and new feature work. For the
-general LLVM release notes, see `the LLVM
-documentation `_. All LLVM
-releases may be downloaded from the `LLVM releases web
-site `_.
-
-For more information about Clang or LLVM, including information about the
-latest release, please see the `Clang Web Site `_ or the
-`LLVM Web Site `_.
-
-Note that if you are reading this file from a Git checkout or the
-main Clang web page, this document applies to the *next* release, not
-the current one. To see the release notes for a specific release, please
-see the `releases page `_.
-
-What's New in Clang 11.0.0?
-===========================
-
-Some of the major new features and improvements to Clang are listed
-here. Generic improvements to Clang as a whole or to its underlying
-infrastructure are described first, followed by language-specific
-sections with improvements to Clang's support for those languages.
-
-Major New Features
-------------------
-
-- ...
-
-Improvements to Clang's diagnostics
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-- ...
-
-Non-comprehensive list of changes in this release
--------------------------------------------------
-
-
-New Compiler Flags
-------------------
-
-
-- -fstack-clash-protection will provide a protection against the stack clash
- attack for x86 architecture through automatic probing of each page of
- allocated stack.
-
-Deprecated Compiler Flags
--------------------------
-
-The following options are deprecated and ignored. They will be removed in
-future versions of Clang.
-
-- ...
-
-Modified Compiler Flags
------------------------
-
-
-New Pragmas in Clang
---------------------
-
-- ...
-
-Attribute Changes in Clang
---------------------------
-
-- ...
-
-Windows Support
----------------
-
-C Language Changes in Clang
----------------------------
-
-- ...
-
-C11 Feature Support
-^^^^^^^^^^^^^^^^^^^
-
-...
-
-C++ Language Changes in Clang
------------------------------
-
-- Clang now implements a restriction on giving non-C-compatible anonymous
- structs a typedef name for linkage purposes, as described in C++ committee
- paper `P1766R1 `. This paper was adopted by the
- C++ committee as a Defect Report resolution, so it is applied retroactively
- to all C++ standard versions. This affects code such as:
-
- .. code-block:: c++
-
- typedef struct {
- int f() { return 0; }
- } S;
-
- Previous versions of Clang rejected some constructs of this form
- (specifically, where the linkage of the type happened to be computed
- before the parser reached the typedef name); those cases are still rejected
- in Clang 11. In addition, cases that previous versions of Clang did not
- reject now produce an extension warning. This warning can be disabled with
- the warning flag ``-Wno-non-c-typedef-for-linkage``.
-
- Affected code should be updated to provide a tag name for the anonymous
- struct:
-
- .. code-block:: c++
-
- struct S {
- int f() { return 0; }
- };
-
- If the code is shared with a C compilation (for example, if the parts that
- are not C-compatible are guarded with ``#ifdef __cplusplus``), the typedef
- declaration should be retained, but a tag name should still be provided:
-
- .. code-block:: c++
-
- typedef struct S {
- int f() { return 0; }
- } S;
-
-C++1z Feature Support
-^^^^^^^^^^^^^^^^^^^^^
-
-...
-
-Objective-C Language Changes in Clang
--------------------------------------
-
-
-OpenCL C Language Changes in Clang
-----------------------------------
-
-...
-
-ABI Changes in Clang
---------------------
-
-
-OpenMP Support in Clang
------------------------
-
-- ...
-
-CUDA Support in Clang
----------------------
-
-- ...
-
-Internal API Changes
---------------------
-
-These are major API changes that have happened since the 10.0.0 release of
-Clang. If upgrading an external codebase that uses Clang as a library,
-this section should help get you past the largest hurdles of upgrading.
-
-
-Build System Changes
---------------------
-
-These are major changes to the build system that have happened since the 10.0.0
-release of Clang. Users of the build system should adjust accordingly.
-
-- ...
-
-AST Matchers
-------------
-
-- ...
-
-clang-format
-------------
-
-
-- Option ``IndentCaseBlocks`` has been added to support treating the block
- following a switch case label as a scope block which gets indented itself.
- It helps avoid having the closing bracket align with the switch statement's
- closing bracket (when ``IndentCaseLabels`` is ``false``).
-
-- Option ``ObjCBreakBeforeNestedBlockParam`` has been added to optionally apply
- linebreaks for function arguments declarations before nested blocks.
-
- .. code-block:: c++
-
- switch (fool) { vs. switch (fool) {
- case 1: case 1: {
- { bar();
- bar(); } break;
- } default: {
- break; plop();
- default: }
- { }
- plop();
- }
- }
-
-- Option ``InsertTrailingCommas`` can be set to ``TCS_Wrapped`` to insert
- trailing commas in container literals (arrays and objects) that wrap across
- multiple lines. It is currently only available for JavaScript and disabled by
- default (``TCS_None``).
-
-libclang
---------
-
-- ...
-
-Static Analyzer
----------------
-
-- ...
-
-.. _release-notes-ubsan:
-
-Undefined Behavior Sanitizer (UBSan)
-------------------------------------
-
-
-Core Analysis Improvements
-==========================
-
-- ...
-
-New Issues Found
-================
-
-- ...
-
-Python Binding Changes
-----------------------
-
-The following methods have been added:
-
-- ...
-
-Significant Known Problems
-==========================
-
-Additional Information
-======================
-
-A wide variety of additional information is available on the `Clang web
-page `_. The web page contains versions of the
-API documentation which are up-to-date with the Subversion version of
-the source code. You can access versions of these documents specific to
-this release by going into the "``clang/docs/``" directory in the Clang
-tree.
-
-If you have any questions or comments about Clang, please feel free to
-contact us via the `mailing
-list `_.
+========================================
+Clang 11.0.0 (In-Progress) Release Notes
+========================================
+
+.. contents::
+ :local:
+ :depth: 2
+
+Written by the `LLVM Team `_
+
+.. warning::
+
+ These are in-progress notes for the upcoming Clang 11 release.
+ Release notes for previous releases can be found on
+ `the Download Page `_.
+
+Introduction
+============
+
+This document contains the release notes for the Clang C/C++/Objective-C
+frontend, part of the LLVM Compiler Infrastructure, release 11.0.0. Here we
+describe the status of Clang in some detail, including major
+improvements from the previous release and new feature work. For the
+general LLVM release notes, see `the LLVM
+documentation `_. All LLVM
+releases may be downloaded from the `LLVM releases web
+site `_.
+
+For more information about Clang or LLVM, including information about the
+latest release, please see the `Clang Web Site `_ or the
+`LLVM Web Site `_.
+
+Note that if you are reading this file from a Git checkout or the
+main Clang web page, this document applies to the *next* release, not
+the current one. To see the release notes for a specific release, please
+see the `releases page `_.
+
+What's New in Clang 11.0.0?
+===========================
+
+Some of the major new features and improvements to Clang are listed
+here. Generic improvements to Clang as a whole or to its underlying
+infrastructure are described first, followed by language-specific
+sections with improvements to Clang's support for those languages.
+
+Major New Features
+------------------
+
+- ...
+
+Improvements to Clang's diagnostics
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- ...
+
+Non-comprehensive list of changes in this release
+-------------------------------------------------
+
+
+New Compiler Flags
+------------------
+
+
+- -fstack-clash-protection will provide a protection against the stack clash
+ attack for x86 architecture through automatic probing of each page of
+ allocated stack.
+
+Deprecated Compiler Flags
+-------------------------
+
+The following options are deprecated and ignored. They will be removed in
+future versions of Clang.
+
+- ...
+
+Modified Compiler Flags
+-----------------------
+
+
+New Pragmas in Clang
+--------------------
+
+- ...
+
+Attribute Changes in Clang
+--------------------------
+
+- ...
+
+Windows Support
+---------------
+
+C Language Changes in Clang
+---------------------------
+
+- ...
+
+C11 Feature Support
+^^^^^^^^^^^^^^^^^^^
+
+...
+
+C++ Language Changes in Clang
+-----------------------------
+
+- Clang now implements a restriction on giving non-C-compatible anonymous
+ structs a typedef name for linkage purposes, as described in C++ committee
+ paper `P1766R1 `. This paper was adopted by the
+ C++ committee as a Defect Report resolution, so it is applied retroactively
+ to all C++ standard versions. This affects code such as:
+
+ .. code-block:: c++
+
+ typedef struct {
+ int f() { return 0; }
+ } S;
+
+ Previous versions of Clang rejected some constructs of this form
+ (specifically, where the linkage of the type happened to be computed
+ before the parser reached the typedef name); those cases are still rejected
+ in Clang 11. In addition, cases that previous versions of Clang did not
+ reject now produce an extension warning. This warning can be disabled with
+ the warning flag ``-Wno-non-c-typedef-for-linkage``.
+
+ Affected code should be updated to provide a tag name for the anonymous
+ struct:
+
+ .. code-block:: c++
+
+ struct S {
+ int f() { return 0; }
+ };
+
+ If the code is shared with a C compilation (for example, if the parts that
+ are not C-compatible are guarded with ``#ifdef __cplusplus``), the typedef
+ declaration should be retained, but a tag name should still be provided:
+
+ .. code-block:: c++
+
+ typedef struct S {
+ int f() { return 0; }
+ } S;
+
+C++1z Feature Support
+^^^^^^^^^^^^^^^^^^^^^
+
+...
+
+Objective-C Language Changes in Clang
+-------------------------------------
+
+
+OpenCL C Language Changes in Clang
+----------------------------------
+
+...
+
+ABI Changes in Clang
+--------------------
+
+
+OpenMP Support in Clang
+-----------------------
+
+- ...
+
+CUDA Support in Clang
+---------------------
+
+- ...
+
+Internal API Changes
+--------------------
+
+These are major API changes that have happened since the 10.0.0 release of
+Clang. If upgrading an external codebase that uses Clang as a library,
+this section should help get you past the largest hurdles of upgrading.
+
+
+Build System Changes
+--------------------
+
+These are major changes to the build system that have happened since the 10.0.0
+release of Clang. Users of the build system should adjust accordingly.
+
+- ...
+
+AST Matchers
+------------
+
+- ...
+
+clang-format
+------------
+
+
+- Option ``IndentCaseBlocks`` has been added to support treating the block
+ following a switch case label as a scope block which gets indented itself.
+ It helps avoid having the closing bracket align with the switch statement's
+ closing bracket (when ``IndentCaseLabels`` is ``false``).
+
+- Option ``ObjCBreakBeforeNestedBlockParam`` has been added to optionally apply
+ linebreaks for function arguments declarations before nested blocks.
+
+ .. code-block:: c++
+
+ switch (fool) { vs. switch (fool) {
+ case 1: case 1: {
+ { bar();
+ bar(); } break;
+ } default: {
+ break; plop();
+ default: }
+ { }
+ plop();
+ }
+ }
+
+- Option ``InsertTrailingCommas`` can be set to ``TCS_Wrapped`` to insert
+ trailing commas in container literals (arrays and objects) that wrap across
+ multiple lines. It is currently only available for JavaScript and disabled by
+ default (``TCS_None``).
+
+- Option ``BraceWrapping.BeforeLambdaBody`` has been added to manage lambda
+ line break inside function parameter call in Allman style.
+
+ .. code-block:: c++
+
+ true:
+ connect(
+ []()
+ {
+ foo();
+ bar();
+ });
+
+ false:
+ connect([]() {
+ foo();
+ bar();
+ });
+
+libclang
+--------
+
+- ...
+
+Static Analyzer
+---------------
+
+- ...
+
+.. _release-notes-ubsan:
+
+Undefined Behavior Sanitizer (UBSan)
+------------------------------------
+
+
+Core Analysis Improvements
+==========================
+
+- ...
+
+New Issues Found
+================
+
+- ...
+
+Python Binding Changes
+----------------------
+
+The following methods have been added:
+
+- ...
+
+Significant Known Problems
+==========================
+
+Additional Information
+======================
+
+A wide variety of additional information is available on the `Clang web
+page `_. The web page contains versions of the
+API documentation which are up-to-date with the Subversion version of
+the source code. You can access versions of these documents specific to
+this release by going into the "``clang/docs/``" directory in the Clang
+tree.
+
+If you have any questions or comments about Clang, please feel free to
+contact us via the `mailing
+list `_.
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -992,6 +992,23 @@
/// }
/// \endcode
bool BeforeElse;
+ /// Wrap lambda block.
+ /// \code
+ /// true:
+ /// connect(
+ /// []()
+ /// {
+ /// foo();
+ /// bar();
+ /// });
+ ///
+ /// false:
+ /// connect([]() {
+ /// foo();
+ /// bar();
+ /// });
+ /// \endcode
+ bool BeforeLambdaBody;
/// Indent the wrapped braces themselves.
bool IndentBraces;
/// If ``false``, empty function body can be put on a single line.
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -329,6 +329,11 @@
bool ContinuationIndenter::mustBreak(const LineState &State) {
const FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *Current.Previous;
+ if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
+ Current.is(TT_LambdaLBrace)) {
+ auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
+ return (LambdaBodyLength > getColumnLimit(State));
+ }
if (Current.MustBreakBefore || Current.is(TT_InlineASMColon))
return true;
if (State.Stack.back().BreakBeforeClosingBrace &&
@@ -1081,6 +1086,18 @@
return State.Stack.back().Indent;
}
+static bool hasNestedBlockInlined(const FormatToken *Previous,
+ const FormatToken &Current,
+ const FormatStyle &Style) {
+ if (Previous->isNot(tok::l_paren))
+ return true;
+ if (Previous->ParameterCount > 1)
+ return true;
+
+ // Also a nested block if contains a lambda inside function with 1 parameter
+ return (Style.BraceWrapping.BeforeLambdaBody && Current.is(TT_LambdaLSquare));
+}
+
unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
bool DryRun, bool Newline) {
assert(State.Stack.size());
@@ -1183,8 +1200,7 @@
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) &&
!Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
State.Stack.back().NestedBlockInlined =
- !Newline &&
- (Previous->isNot(tok::l_paren) || Previous->ParameterCount > 1);
+ !Newline && hasNestedBlockInlined(Previous, Current, Style);
}
moveStatePastFakeLParens(State, Newline);
@@ -1421,7 +1437,21 @@
ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
- State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1;
+ State.Stack.back().HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);
+
+ if (Style.BraceWrapping.BeforeLambdaBody &&
+ Current.Next != nullptr && Current.Tok.is(tok::l_paren)) {
+ // Search for any parameter that is a lambda
+ FormatToken const *next = Current.Next;
+ while (next != nullptr) {
+ if (next->is(TT_LambdaLSquare)) {
+ State.Stack.back().HasMultipleNestedBlocks = true;
+ break;
+ }
+ next = next->Next;
+ }
+ }
+
State.Stack.back().IsInsideObjCArrayLiteral =
Current.is(TT_ArrayInitializerLSquare) && Current.Previous &&
Current.Previous->is(tok::at);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -581,6 +581,7 @@
IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
+ IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
@@ -668,8 +669,8 @@
false, false, false,
false, false, false,
false, false, false,
- false, true, true,
- true};
+ false, false, true,
+ true, true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -717,14 +718,15 @@
Expanded.BraceWrapping.AfterExternBlock = true;
Expanded.BraceWrapping.BeforeCatch = true;
Expanded.BraceWrapping.BeforeElse = true;
+ Expanded.BraceWrapping.BeforeLambdaBody = true;
break;
case FormatStyle::BS_GNU:
- Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always,
- true, true, true,
- true, true, true,
- true, true, true,
- true, true, true,
- true};
+ Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always,
+ true, true, true,
+ true, true, true,
+ true, true, true,
+ false, true, true,
+ true, true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -768,8 +770,8 @@
false, false, false,
false, false, false,
false, false, false,
- false, true, true,
- true};
+ false, false, true,
+ true, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -3122,6 +3122,56 @@
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);
}
+// Returns 'true' if 'Tok' is an function argument.
+static bool IsFunctionArgument(const FormatToken &Tok) {
+ return Tok.MatchingParen && Tok.MatchingParen->Next &&
+ Tok.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren);
+}
+
+static bool
+isItAnEmptyLambdaAllowed(const FormatToken &Tok,
+ FormatStyle::ShortLambdaStyle ShortLambdaOption) {
+ return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;
+}
+
+static bool
+isItAInlineLambdaAllowed(const FormatToken &Tok,
+ FormatStyle::ShortLambdaStyle ShortLambdaOption) {
+ return (ShortLambdaOption == FormatStyle::SLS_Inline &&
+ IsFunctionArgument(Tok)) ||
+ (ShortLambdaOption == FormatStyle::SLS_All);
+}
+
+static bool isOneChildWithoutMustBreakBefore(const FormatToken &Tok) {
+ if (Tok.Children.size() != 1)
+ return false;
+ FormatToken *curElt = Tok.Children[0]->First;
+ while (curElt) {
+ if (curElt->MustBreakBefore)
+ return false;
+ curElt = curElt->Next;
+ }
+ return true;
+}
+static bool
+isAllmanLambdaBrace(const FormatToken &Tok) {
+ return (Tok.is(tok::l_brace) && Tok.BlockKind == BK_Block &&
+ !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral));
+}
+
+static bool
+isAllmanBraceIncludedBreakableLambda(const FormatToken &Tok,
+ FormatStyle::ShortLambdaStyle ShortLambdaOption) {
+ if (!isAllmanLambdaBrace(Tok))
+ return false;
+
+ if (isItAnEmptyLambdaAllowed(Tok, ShortLambdaOption))
+ return false;
+
+ return !isItAInlineLambdaAllowed(Tok, ShortLambdaOption) ||
+ !isOneChildWithoutMustBreakBefore(Tok);
+}
+
bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
@@ -3257,6 +3307,14 @@
}
if (Right.is(TT_InlineASMBrace))
return Right.HasUnescapedNewline;
+
+ auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
+ if (Style.BraceWrapping.BeforeLambdaBody &&
+ (isAllmanBraceIncludedBreakableLambda(Left, ShortLambdaOption) ||
+ isAllmanBraceIncludedBreakableLambda(Right, ShortLambdaOption))) {
+ return true;
+ }
+
if (isAllmanBrace(Left) || isAllmanBrace(Right))
return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) ||
(Line.startsWith(tok::kw_typedef, tok::kw_enum) &&
@@ -3268,8 +3326,7 @@
return true;
if (Left.is(TT_LambdaLBrace)) {
- if (Left.MatchingParen && Left.MatchingParen->Next &&
- Left.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren) &&
+ if (IsFunctionArgument(Left) &&
Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline)
return false;
@@ -3667,11 +3724,21 @@
if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) ||
(Left.is(tok::r_square) && Right.is(TT_AttributeSquare)))
return false;
+
+ auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
+ if (Style.BraceWrapping.BeforeLambdaBody) {
+ if (isAllmanLambdaBrace(Left))
+ return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);
+ if (isAllmanLambdaBrace(Right))
+ return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
+ }
+
return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct, tok::comment) ||
Right.isMemberAccess() ||
Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,
tok::colon, tok::l_square, tok::at) ||
+ (Style.BraceWrapping.BeforeLambdaBody && Right.is(tok::l_brace)) ||
(Left.is(tok::r_paren) &&
Right.isOneOf(tok::identifier, tok::kw_const)) ||
(Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -12673,6 +12673,7 @@
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterExternBlock);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeLambdaBody);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord);
@@ -13962,6 +13963,245 @@
"function([]() { return b; }, a)", MergeInline);
verifyFormat("function(a, []() { return b; })",
"function(a, []() { return b; })", MergeInline);
+
+ // Check option "BraceWrapping.BeforeLambdaBody" and different state of
+ // AllowShortLambdasOnASingleLine
+ FormatStyle LLVMWithBeforeLambdaBody = getLLVMStyle();
+ LLVMWithBeforeLambdaBody.BreakBeforeBraces = FormatStyle::BS_Custom;
+ LLVMWithBeforeLambdaBody.BraceWrapping.BeforeLambdaBody = true;
+ LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
+ FormatStyle::ShortLambdaStyle::SLS_None;
+ verifyFormat("FctWithOneNestedLambdaInline_SLS_None(\n"
+ " []()\n"
+ " {\n"
+ " return 17;\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithOneNestedLambdaEmpty_SLS_None(\n"
+ " []()\n"
+ " {\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("auto fct_SLS_None = []()\n"
+ "{\n"
+ " return 17;\n"
+ "};",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("TwoNestedLambdas_SLS_None(\n"
+ " []()\n"
+ " {\n"
+ " return Call(\n"
+ " []()\n"
+ " {\n"
+ " return 17;\n"
+ " });\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("void Fct()\n"
+ "{\n"
+ " return {[]()\n"
+ " {\n"
+ " return 17;\n"
+ " }};\n"
+ "}",
+ LLVMWithBeforeLambdaBody);
+
+ LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
+ FormatStyle::ShortLambdaStyle::SLS_Empty;
+ verifyFormat("FctWithOneNestedLambdaInline_SLS_Empty(\n"
+ " []()\n"
+ " {\n"
+ " return 17;\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithOneNestedLambdaEmpty_SLS_Empty([]() {});",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithOneNestedLambdaEmptyInsideAVeryVeryVeryVeryVeryVeryVeryL"
+ "ongFunctionName_SLS_Empty(\n"
+ " []() {});",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithMultipleParams_SLS_Empty(A, B,\n"
+ " []()\n"
+ " {\n"
+ " return 17;\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("auto fct_SLS_Empty = []()\n"
+ "{\n"
+ " return 17;\n"
+ "};",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("TwoNestedLambdas_SLS_Empty(\n"
+ " []()\n"
+ " {\n"
+ " return Call([]() {});\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("TwoNestedLambdas_SLS_Empty(A,\n"
+ " []()\n"
+ " {\n"
+ " return Call([]() {});\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "FctWithLongLineInLambda_SLS_Empty(\n"
+ " []()\n"
+ " {\n"
+ " return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
+ " AndShouldNotBeConsiderAsInline,\n"
+ " LambdaBodyMustBeBreak);\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+
+ LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
+ FormatStyle::ShortLambdaStyle::SLS_Inline;
+ verifyFormat("FctWithOneNestedLambdaInline_SLS_Inline([]() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithOneNestedLambdaEmpty_SLS_Inline([]() {});",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("auto fct_SLS_Inline = []()\n"
+ "{\n"
+ " return 17;\n"
+ "};",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("TwoNestedLambdas_SLS_Inline([]() { return Call([]() { return "
+ "17; }); });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "FctWithLongLineInLambda_SLS_Inline(\n"
+ " []()\n"
+ " {\n"
+ " return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
+ " AndShouldNotBeConsiderAsInline,\n"
+ " LambdaBodyMustBeBreak);\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithMultipleParams_SLS_Inline("
+ "VeryLongParameterThatShouldAskToBeOnMultiLine,\n"
+ " []() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "FctWithMultipleParams_SLS_Inline(FirstParam, []() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+
+ LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
+ FormatStyle::ShortLambdaStyle::SLS_All;
+ verifyFormat("FctWithOneNestedLambdaInline_SLS_All([]() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithOneNestedLambdaEmpty_SLS_All([]() {});",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("auto fct_SLS_All = []() { return 17; };",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithOneParam_SLS_All(\n"
+ " []()\n"
+ " {\n"
+ " // A cool function...\n"
+ " return 43;\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithMultipleParams_SLS_All("
+ "VeryLongParameterThatShouldAskToBeOnMultiLine,\n"
+ " []() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithMultipleParams_SLS_All(A, []() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithMultipleParams_SLS_All(A, B, []() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "FctWithLongLineInLambda_SLS_All(\n"
+ " []()\n"
+ " {\n"
+ " return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
+ " AndShouldNotBeConsiderAsInline,\n"
+ " LambdaBodyMustBeBreak);\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "auto fct_SLS_All = []()\n"
+ "{\n"
+ " return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
+ " AndShouldNotBeConsiderAsInline,\n"
+ " LambdaBodyMustBeBreak);\n"
+ "};",
+ LLVMWithBeforeLambdaBody);
+ LLVMWithBeforeLambdaBody.BinPackParameters = false;
+ verifyFormat("FctAllOnSameLine_SLS_All([]() { return S; }, Fst, Second);",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "FctWithLongLineInLambda_SLS_All([]() { return SomeValueNotSoLong; },\n"
+ " FirstParam,\n"
+ " SecondParam,\n"
+ " ThirdParam,\n"
+ " FourthParam);",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithLongLineInLambda_SLS_All(\n"
+ " []() { return "
+ "SomeValueVeryVeryVeryVeryVeryVeryVeryVeryVeryLong; },\n"
+ " FirstParam,\n"
+ " SecondParam,\n"
+ " ThirdParam,\n"
+ " FourthParam);",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "FctWithLongLineInLambda_SLS_All(FirstParam,\n"
+ " SecondParam,\n"
+ " ThirdParam,\n"
+ " FourthParam,\n"
+ " []() { return SomeValueNotSoLong; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithLongLineInLambda_SLS_All(\n"
+ " []()\n"
+ " {\n"
+ " return "
+ "HereAVeryLongLineThatWillBeFormattedOnMultipleLineAndShouldNotB"
+ "eConsiderAsInline;\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "FctWithLongLineInLambda_SLS_All(\n"
+ " []()\n"
+ " {\n"
+ " return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
+ " AndShouldNotBeConsiderAsInline,\n"
+ " LambdaBodyMustBeBreak);\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithTwoParams_SLS_All(\n"
+ " []()\n"
+ " {\n"
+ " // A cool function...\n"
+ " return 43;\n"
+ " },\n"
+ " 87);",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithTwoParams_SLS_All([]() { return 43; }, 87);",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("FctWithOneNestedLambdas_SLS_All([]() { return 17; });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat(
+ "TwoNestedLambdas_SLS_All([]() { return Call([]() { return 17; }); });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("TwoNestedLambdas_SLS_All([]() { return Call([]() { return 17; "
+ "}); }, x);",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("TwoNestedLambdas_SLS_All(\n"
+ " []()\n"
+ " {\n"
+ " // A cool function...\n"
+ " return Call([]() { return 17; });\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
+ verifyFormat("TwoNestedLambdas_SLS_All(\n"
+ " []()\n"
+ " {\n"
+ " return Call(\n"
+ " []()\n"
+ " {\n"
+ " // A cool function...\n"
+ " return 17;\n"
+ " });\n"
+ " });",
+ LLVMWithBeforeLambdaBody);
}
TEST_F(FormatTest, EmptyLinesInLambdas) {