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) {