Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -1214,6 +1214,21 @@ If ``true``, ``while (true) continue;`` can be put on a single line. +**AllowShortRequiresExpressionOnASingleLine** (``Boolean``) :versionbadge:`clang-format 16` + Allow short requires expression on a single line. + + .. code-block:: c++ + + true: + template + concept c = requires(T a, T b) { a + b; }; + + false: + template + concept c = requires(T a, T b) { + a + b; + }; + **AlwaysBreakAfterDefinitionReturnType** (``DefinitionReturnTypeBreakingStyle``) :versionbadge:`clang-format 3.7` The function definition return type breaking style to use. This option is **deprecated** and is retained for backwards compatibility. Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -714,6 +714,21 @@ /// \version 3.7 bool AllowShortLoopsOnASingleLine; + /// Allow short requires expression on a single line. + /// \code + /// true: + /// template + /// concept c = requires(T a, T b) { a + b; }; + /// + /// false: + /// template + /// concept c = requires(T a, T b) { + /// a + b; + /// }; + /// \endcode + /// \version 16 + bool AllowShortRequiresExpressionOnASingleLine; + /// Different ways to break after the function definition return type. /// This option is **deprecated** and is retained for backwards compatibility. enum DefinitionReturnTypeBreakingStyle : int8_t { @@ -4038,6 +4053,8 @@ R.AllowShortIfStatementsOnASingleLine && AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine && AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine && + AllowShortRequiresExpressionOnASingleLine == + R.AllowShortRequiresExpressionOnASingleLine && AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType && AlwaysBreakBeforeMultilineStrings == R.AlwaysBreakBeforeMultilineStrings && Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -816,6 +816,8 @@ Style.AllowShortLambdasOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); + IO.mapOptional("AllowShortRequiresExpressionOnASingleLine", + Style.AllowShortRequiresExpressionOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakAfterReturnType", @@ -1265,6 +1267,7 @@ LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; LLVMStyle.AllowShortLoopsOnASingleLine = false; + LLVMStyle.AllowShortRequiresExpressionOnASingleLine = true; LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; Index: clang/lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- clang/lib/Format/UnwrappedLineFormatter.cpp +++ clang/lib/Format/UnwrappedLineFormatter.cpp @@ -502,6 +502,8 @@ // Try to merge records. if (TheLine->Last->is(TT_EnumLBrace)) { ShouldMerge = Style.AllowShortEnumsOnASingleLine; + } else if (TheLine->Last->is(TT_RequiresExpressionLBrace)) { + ShouldMerge = Style.AllowShortRequiresExpressionOnASingleLine; } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) { // NOTE: We use AfterClass (whereas AfterStruct exists) for both classes // and structs, but it seems that wrapping is still handled correctly Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -1085,6 +1085,12 @@ FormatTok->setBlockKind(BK_Block); const FormatToken *OpeningBrace = FormatTok; nextToken(); + + if (NextLBracesType == TT_CompoundRequirementLBrace && + !Style.AllowShortRequiresExpressionOnASingleLine) { + addUnwrappedLine(); + } + { bool SkipIndent = (Style.isJavaScript() && (isGoogScope(*Line) || isIIFE(*Line, Keywords))); Index: clang/unittests/Format/ConfigParseTest.cpp =================================================================== --- clang/unittests/Format/ConfigParseTest.cpp +++ clang/unittests/Format/ConfigParseTest.cpp @@ -149,6 +149,7 @@ CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine); CHECK_PARSE_BOOL(AllowShortEnumsOnASingleLine); CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine); + CHECK_PARSE_BOOL(AllowShortRequiresExpressionOnASingleLine); CHECK_PARSE_BOOL(BinPackArguments); CHECK_PARSE_BOOL(BinPackParameters); CHECK_PARSE_BOOL(BreakAfterJavaFieldAnnotations); Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -2899,6 +2899,20 @@ Style); } +TEST_F(FormatTest, ShortRequiresExpression) { + FormatStyle Style = getLLVMStyle(); + EXPECT_TRUE(Style.AllowShortRequiresExpressionOnASingleLine); + verifyFormat("template \n" + "concept c = requires(T a, T b) { a + b; };", + Style); + Style.AllowShortRequiresExpressionOnASingleLine = false; + verifyFormat("template \n" + "concept c = requires(T a, T b) {\n" + " a + b;\n" + "};", + Style); +} + TEST_F(FormatTest, ShortCaseLabels) { FormatStyle Style = getLLVMStyle(); Style.AllowShortCaseLabelsOnASingleLine = true;