https://github.com/goyaladitya05 updated https://github.com/llvm/llvm-project/pull/216465
>From b719a66222b7bec941c5f5a1dd770214057a4d74 Mon Sep 17 00:00:00 2001 From: Aditya Goyal <[email protected]> Date: Sat, 15 Aug 2026 13:09:17 +0530 Subject: [PATCH 1/2] [clang-format] Add BraceWrapping.AfterRequiresExpression option --- clang/docs/ClangFormatStyleOptions.md | 17 ++++ clang/docs/ReleaseNotes.md | 3 + clang/include/clang/Format/Format.h | 16 ++++ clang/lib/Format/ContinuationIndenter.cpp | 15 ++++ clang/lib/Format/Format.cpp | 6 ++ clang/lib/Format/TokenAnnotator.cpp | 5 ++ clang/unittests/Format/ConfigParseTest.cpp | 1 + clang/unittests/Format/FormatTest.cpp | 92 ++++++++++++++++++++++ 8 files changed, 155 insertions(+) diff --git a/clang/docs/ClangFormatStyleOptions.md b/clang/docs/ClangFormatStyleOptions.md index 9b962e6e1e083..f51bf691ec6a4 100644 --- a/clang/docs/ClangFormatStyleOptions.md +++ b/clang/docs/ClangFormatStyleOptions.md @@ -2552,6 +2552,23 @@ the configuration (without a prefix: `Auto`). according to `AfterControlStatement` flag. ::: + - `bool AfterRequiresExpression` Wrap requires expression body. + + ```c++ + true: + template <typename T> + concept C = requires(T t) + { + foo(t); + }; + + false: + template <typename T> + concept C = requires(T t) { + foo(t); + }; + ``` + - `bool AfterStruct` Wrap struct definitions. ```c++ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index a7a31946610ae..768abc317f9a7 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -583,6 +583,9 @@ features cannot lower the translation-unit ABI level; - Add `SpacesInBlockComments` option to control spacing after `/*` and before `*/` in ordinary block comments. +- Add `AfterRequiresExpression` sub-option of `BraceWrapping` to wrap the + body of requires expressions. It is enabled by the `Allman`, `Whitesmiths`, + and `GNU` styles of `BreakBeforeBraces`. ### libclang diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 3948337d2fc3d..7241864fff50e 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1507,6 +1507,22 @@ struct FormatStyle { /// according to `AfterControlStatement` flag. /// \endnote bool AfterObjCDeclaration; + /// Wrap requires expression body. + /// \code + /// true: + /// template <typename T> + /// concept C = requires(T t) + /// { + /// foo(t); + /// }; + /// + /// false: + /// template <typename T> + /// concept C = requires(T t) { + /// foo(t); + /// }; + /// \endcode + bool AfterRequiresExpression; /// Wrap struct definitions. /// \code /// true: diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 085b48fd1ed78..aa264c1487bce 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -449,6 +449,9 @@ bool ContinuationIndenter::canBreak(const LineState &State) { // enabled. (!Style.BraceWrapping.BeforeLambdaBody || Current.isNot(TT_LambdaLBrace)) && + // Same for the opening brace of requires expressions. + (!Style.BraceWrapping.AfterRequiresExpression || + Current.isNot(TT_RequiresExpressionLBrace)) && CurrentState.NoLineBreakInOperand) { return false; } @@ -477,6 +480,11 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack); return LambdaBodyLength > getColumnLimit(State); } + if (Style.BraceWrapping.AfterRequiresExpression && Current.CanBreakBefore && + Current.is(TT_RequiresExpressionLBrace) && + getLengthToMatchingParen(Current, State.Stack) > getColumnLimit(State)) { + return true; + } if (Current.MustBreakBefore || (Current.is(TT_InlineASMColon) && (Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always || @@ -1508,6 +1516,13 @@ ContinuationIndenter::getNewLineColumn(const LineState &State) { return From + Style.IndentWidth; } + // Align the wrapped opening brace of a requires expression with its + // closing brace. + if (Style.BraceWrapping.AfterRequiresExpression && + Current.is(TT_RequiresExpressionLBrace)) { + return CurrentState.NestedBlockIndent; + } + if ((NextNonComment->is(tok::l_brace) && NextNonComment->is(BK_Block)) || (Style.isVerilog() && Keywords.isVerilogBegin(*NextNonComment))) { if (Current.NestingLevel == 0 || diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 2b6e65efbf026..1e4c2c6080912 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -223,6 +223,7 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { IO.mapOptional("AfterFunction", Wrapping.AfterFunction); IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); + IO.mapOptional("AfterRequiresExpression", Wrapping.AfterRequiresExpression); IO.mapOptional("AfterStruct", Wrapping.AfterStruct); IO.mapOptional("AfterUnion", Wrapping.AfterUnion); IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); @@ -1722,6 +1723,7 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { /*AfterFunction=*/false, /*AfterNamespace=*/false, /*AfterObjCDeclaration=*/false, + /*AfterRequiresExpression=*/false, /*AfterStruct=*/false, /*AfterUnion=*/false, /*AfterExternBlock=*/false, @@ -1762,6 +1764,7 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterNamespace = true; Expanded.BraceWrapping.AfterObjCDeclaration = true; + Expanded.BraceWrapping.AfterRequiresExpression = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; Expanded.BraceWrapping.AfterExternBlock = true; @@ -1777,6 +1780,7 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterNamespace = true; Expanded.BraceWrapping.AfterObjCDeclaration = true; + Expanded.BraceWrapping.AfterRequiresExpression = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterExternBlock = true; Expanded.BraceWrapping.BeforeCatch = true; @@ -1792,6 +1796,7 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) { /*AfterFunction=*/true, /*AfterNamespace=*/true, /*AfterObjCDeclaration=*/true, + /*AfterRequiresExpression=*/true, /*AfterStruct=*/true, /*AfterUnion=*/true, /*AfterExternBlock=*/true, @@ -1894,6 +1899,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { /*AfterFunction=*/false, /*AfterNamespace=*/false, /*AfterObjCDeclaration=*/false, + /*AfterRequiresExpression=*/false, /*AfterStruct=*/false, /*AfterUnion=*/false, /*AfterExternBlock=*/false, diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index b6c33279b0aca..105c98e704c3b 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -6724,6 +6724,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return false; } + if (Style.BraceWrapping.AfterRequiresExpression && + Right.is(TT_RequiresExpressionLBrace)) { + return true; + } + auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine; if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) { if (isAllmanLambdaBrace(Left)) diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 9350ba7eb3de4..abf8c0b55a67b 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -241,6 +241,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterFunction); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterNamespace); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterObjCDeclaration); + CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterRequiresExpression); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterStruct); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterUnion); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterExternBlock); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index b72a683ac1fff..18e2aa551918c 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -24676,6 +24676,98 @@ TEST_F(FormatTest, RequiresExpressionIndentation) { Style); } +TEST_F(FormatTest, RequiresExpressionBraceWrapping) { + auto Style = getLLVMStyle(); + EXPECT_FALSE(Style.BraceWrapping.AfterRequiresExpression); + + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterRequiresExpression = true; + + // Requires expressions that fit on a single line are not wrapped. + verifyFormat("template <typename T>\n" + "concept C = requires(T t) { t.foo(); };", + Style); + verifyFormat("static_assert(requires(int i) { i + 1; });", Style); + + verifyFormat("template <typename T>\n" + "concept C = requires(T t)\n" + "{\n" + " t.foo();\n" + " t.bar();\n" + "};", + Style); + + verifyFormat("template <typename T>\n" + "concept C = requires\n" + "{\n" + " typename T::value_type;\n" + " typename T::size_type;\n" + "};", + Style); + + verifyFormat("template <typename T>\n" + "concept C = requires(T t)\n" + "{\n" + " { t.foo() } -> std::same_as<int>;\n" + "};", + Style); + + verifyFormat("template <typename T>\n" + "void bar(T)\n" + " requires requires(T t)\n" + " {\n" + " t.foo();\n" + " t.bar();\n" + " };", + Style); + + verifyFormat("template <typename T> void f() {\n" + " if constexpr (requires(T t)\n" + " {\n" + " { t.bar() } -> std::same_as<bool>;\n" + " }) {\n" + " }\n" + "}", + Style); + + // The wrapped brace is aligned with the closing brace. + verifyFormat("template <typename T>\n" + " requires Foo<T> &&\n" + " requires(T t)\n" + " {\n" + " { t.foo() } -> std::same_as<int>;\n" + " } &&\n" + " requires(T t)\n" + " {\n" + " { t.bar() } -> std::same_as<bool>;\n" + " --t;\n" + " }\n" + "void bar(T);", + Style); + + Style.RequiresExpressionIndentation = FormatStyle::REI_Keyword; + verifyFormat("template <typename T>\n" + "concept C = requires(T t)\n" + " {\n" + " typename T::value;\n" + " requires requires(typename T::value v)\n" + " {\n" + " { t == v } -> std::same_as<bool>;\n" + " };\n" + " };", + Style); + Style.RequiresExpressionIndentation = FormatStyle::REI_OuterScope; + + Style.BreakBeforeBraces = FormatStyle::BS_Allman; + verifyFormat("template <typename T>\n" + "concept Uart = requires(T a)\n" + "{\n" + " { a.write() } -> std::convertible_to<std::size_t>;\n" + " a.flush();\n" + "};", + Style); +} + TEST_F(FormatTest, StatementAttributeLikeMacros) { FormatStyle Style = getLLVMStyle(); StringRef Source = "void Foo::slot() {\n" >From 39a51afb14f29ed2c2232176c1386a02ee88ddce Mon Sep 17 00:00:00 2001 From: Aditya Goyal <[email protected]> Date: Sat, 15 Aug 2026 13:24:32 +0530 Subject: [PATCH 2/2] retrigger CI _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
