[clang] [clang-format] Add AlignAfterOpenBracketOptions (PR #108332)
Gedare Bloom via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 9 15:47:42 PST 2025
https://github.com/gedare updated https://github.com/llvm/llvm-project/pull/108332
>From 5cec30f5d93a22f10a985cb3e4418e7d29d31a00 Mon Sep 17 00:00:00 2001
From: Gedare Bloom <gedare at rtems.org>
Date: Thu, 20 Jun 2024 17:35:39 -0600
Subject: [PATCH 1/7] Format: add AlignAfterOpenBracketOptions
Introduce new options to allow for control of AlwaysBreak and
BlockIndent selectively for If conditional statements (as currently
supported), other conditional statements (for/while/switch), and
other statements.
Fixes #67738.
Fixes #79176.
Fixes #80123.
---
clang/docs/ClangFormatStyleOptions.rst | 60 +++++++++
clang/include/clang/Format/Format.h | 73 +++++++++++
clang/lib/Format/ContinuationIndenter.cpp | 44 +++++--
clang/lib/Format/Format.cpp | 26 ++++
clang/lib/Format/TokenAnnotator.cpp | 8 +-
clang/unittests/Format/ConfigParseTest.cpp | 12 ++
clang/unittests/Format/FormatTest.cpp | 143 +++++++++++++++++++++
7 files changed, 355 insertions(+), 11 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index bf6dd9e13915f8c..8e3383ec027dede 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -246,6 +246,66 @@ the configuration (without a prefix: ``Auto``).
+.. _AlignAfterOpenBracketBreak:
+
+**AlignAfterOpenBracketBreak** (``AlignAfterOpenBracketCustom``) :versionbadge:`clang-format 20` :ref:`¶ <AlignAfterOpenBracketBreak>`
+ Control of when ``AlignAfterOpenBracket`` breaks an opening bracket.
+
+ If ``AlignAfterOpenBracket`` is set to ``AlwaysBreak`` or ``BlockIndent``,
+ use this to specify how different cases of breaking the opening brackets
+ should be handled. Otherwise, this is ignored. Setting any of these to
+ ``false`` will cause them to not break. At least one of these must be set
+ to ``true``, otherwise a default (backward compatible) breaking behavior
+ is used. This is ignored for ``Align`` and ``DontAlign``.
+
+ .. code-block:: c++
+
+ # Example of usage:
+ AlignAfterOpenBracket: AlwaysBreak
+ AlignAfterOpenBracketBreak:
+ InIfConditionalStatements: true
+ InOtherConditionalStatements: false
+ Other: true
+
+ Nested configuration flags:
+
+ Precise control over breaking the opening bracket of
+ ``AlignAfterOpenBracket``.
+
+ .. code-block:: c++
+
+ # Should be declared this way:
+ AlignAfterOpenBracketBreak:
+ InIfConditionalStatements: true
+ InOtherConditionalStatements: false
+ Other: true
+
+ * ``bool InIfConditionalStatements`` Break inside if/else if statements.
+
+ .. code-block:: c++
+
+ true: false:
+ if constexpr ( vs. if constexpr (a ||
+ a || b) b)
+
+ * ``bool InOtherConditionalStatements`` Break inside conditional statements not covered by preceding options.
+ (``for/while/switch...``).
+
+ .. code-block:: c++
+
+ true: false:
+ while ( vs. while (a &&
+ a && b ) { b) {
+
+ * ``bool Other`` Break inside brackets not covered by preceding options.
+
+ .. code-block:: c++
+
+ true: false:
+ someLongFunction( vs. someLongFunction(argument1,
+ argument1, argument2); argument2);
+
+
.. _AlignArrayOfStructures:
**AlignArrayOfStructures** (``ArrayInitializerAlignmentStyle``) :versionbadge:`clang-format 13` :ref:`¶ <AlignArrayOfStructures>`
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 16956b4e0fbd4f3..4a24e39ab3aff7a 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -106,6 +106,78 @@ struct FormatStyle {
/// \version 3.8
BracketAlignmentStyle AlignAfterOpenBracket;
+ /// Precise control over breaking the opening bracket of
+ /// ``AlignAfterOpenBracket``.
+ /// \code
+ /// # Should be declared this way:
+ /// AlignAfterOpenBracketBreak:
+ /// InIfConditionalStatements: true
+ /// InOtherConditionalStatements: false
+ /// Other: true
+ /// \endcode
+ struct AlignAfterOpenBracketCustom {
+ /// Break inside if/else if statements.
+ /// \code
+ /// true: false:
+ /// if constexpr ( vs. if constexpr (a ||
+ /// a || b) b)
+ /// \endcode
+ bool InIfConditionalStatements;
+ /// Break inside conditional statements not covered by preceding options.
+ /// (``for/while/switch...``).
+ /// \code
+ /// true: false:
+ /// while ( vs. while (a &&
+ /// a && b ) { b) {
+ /// \endcode
+ bool InOtherConditionalStatements;
+ /// Break inside brackets not covered by preceding options.
+ /// \code
+ /// true: false:
+ /// someLongFunction( vs. someLongFunction(argument1,
+ /// argument1, argument2); argument2);
+ /// \endcode
+ bool Other;
+
+ AlignAfterOpenBracketCustom()
+ : InIfConditionalStatements(false), InOtherConditionalStatements(false),
+ Other(false) {}
+
+ AlignAfterOpenBracketCustom(bool InIfConditionalStatements,
+ bool InOtherConditionalStatements, bool Other)
+ : InIfConditionalStatements(InIfConditionalStatements),
+ InOtherConditionalStatements(InOtherConditionalStatements),
+ Other(Other) {}
+
+ bool operator==(const AlignAfterOpenBracketCustom &R) const {
+ return InIfConditionalStatements == R.InIfConditionalStatements &&
+ InOtherConditionalStatements == R.InOtherConditionalStatements &&
+ Other == R.Other;
+ }
+ bool operator!=(const AlignAfterOpenBracketCustom &R) const {
+ return !(*this == R);
+ }
+ };
+
+ /// Control of when ``AlignAfterOpenBracket`` breaks an opening bracket.
+ ///
+ /// If ``AlignAfterOpenBracket`` is set to ``AlwaysBreak`` or ``BlockIndent``,
+ /// use this to specify how different cases of breaking the opening brackets
+ /// should be handled. Otherwise, this is ignored. Setting any of these to
+ /// ``false`` will cause them to not break. At least one of these must be set
+ /// to ``true``, otherwise a default (backward compatible) breaking behavior
+ /// is used. This is ignored for ``Align`` and ``DontAlign``.
+ /// \code
+ /// # Example of usage:
+ /// AlignAfterOpenBracket: AlwaysBreak
+ /// AlignAfterOpenBracketBreak:
+ /// InIfConditionalStatements: true
+ /// InOtherConditionalStatements: false
+ /// Other: true
+ /// \endcode
+ /// \version 20
+ AlignAfterOpenBracketCustom AlignAfterOpenBracketBreak;
+
/// Different style for aligning array initializers.
enum ArrayInitializerAlignmentStyle : int8_t {
/// Align array column and left justify the columns e.g.:
@@ -5241,6 +5313,7 @@ struct FormatStyle {
bool operator==(const FormatStyle &R) const {
return AccessModifierOffset == R.AccessModifierOffset &&
AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
+ AlignAfterOpenBracketBreak == R.AlignAfterOpenBracketBreak &&
AlignArrayOfStructures == R.AlignArrayOfStructures &&
AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
AlignConsecutiveBitFields == R.AlignConsecutiveBitFields &&
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 3e51b4aab10824a..886e992f26cdbcb 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -811,6 +811,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
// parenthesis by disallowing any further line breaks if there is no line
// break after the opening parenthesis. Don't break if it doesn't conserve
// columns.
+ auto IsOtherConditional = [&](const FormatToken &Tok) {
+ return Tok.isOneOf(tok::kw_for, tok::kw_while, tok::kw_switch) ||
+ (Style.isJavaScript() && Tok.is(Keywords.kw_await) && Tok.Previous &&
+ Tok.Previous->is(tok::kw_for));
+ };
auto IsOpeningBracket = [&](const FormatToken &Tok) {
auto IsStartOfBracedList = [&]() {
return Tok.is(tok::l_brace) && Tok.isNot(BK_Block) &&
@@ -823,10 +828,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
if (!Tok.Previous)
return true;
if (Tok.Previous->isIf())
- return Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak;
- return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
- tok::kw_switch) &&
- !(Style.isJavaScript() && Tok.Previous->is(Keywords.kw_await));
+ return Style.AlignAfterOpenBracketBreak.InIfConditionalStatements;
+ if (IsOtherConditional(*Tok.Previous))
+ return Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements;
+ return !Tok.Previous->is(TT_CastRParen) &&
+ Style.AlignAfterOpenBracketBreak.Other;
};
auto IsFunctionCallParen = [](const FormatToken &Tok) {
return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous &&
@@ -863,10 +869,15 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
Tok.isOneOf(tok::ellipsis, Keywords.kw_await))) {
return true;
}
- const auto *Previous = Tok.Previous;
- if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen,
- TT_LambdaDefinitionLParen) &&
- !IsFunctionCallParen(*Previous))) {
+ const auto *Previous = TokAfterLParen.Previous;
+ assert(Previous); // IsOpeningBracket(Previous)
+ if (Previous->Previous && (Previous->Previous->isIf() ||
+ IsOtherConditional(*Previous->Previous))) {
+ return false;
+ }
+ if (!Previous->isOneOf(TT_FunctionDeclarationLParen,
+ TT_LambdaDefinitionLParen) &&
+ !IsFunctionCallParen(*Previous)) {
return true;
}
if (IsOpeningBracket(Tok) || IsInTemplateString(Tok))
@@ -1244,8 +1255,21 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
}
if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) {
- CurrentState.BreakBeforeClosingParen =
- Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent;
+ CurrentState.BreakBeforeClosingParen = false;
+ if (Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) {
+ auto Previous = PreviousNonComment->Previous;
+ if (Previous && Previous->isIf()) {
+ CurrentState.BreakBeforeClosingParen =
+ Style.AlignAfterOpenBracketBreak.InIfConditionalStatements;
+ } else if (Previous && Previous->isOneOf(tok::kw_for, tok::kw_while,
+ tok::kw_switch)) {
+ CurrentState.BreakBeforeClosingParen =
+ Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements;
+ } else {
+ CurrentState.BreakBeforeClosingParen =
+ Style.AlignAfterOpenBracketBreak.Other;
+ }
+ }
}
if (PreviousNonComment && PreviousNonComment->is(TT_TemplateOpener))
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 0898b69528ebcde..16a40f270d28a7c 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -215,6 +215,16 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::AlignAfterOpenBracketCustom> {
+ static void mapping(IO &IO, FormatStyle::AlignAfterOpenBracketCustom &Value) {
+ IO.mapOptional("InIfConditionalStatements",
+ Value.InIfConditionalStatements);
+ IO.mapOptional("InOtherConditionalStatements",
+ Value.InOtherConditionalStatements);
+ IO.mapOptional("Other", Value.Other);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceWrappingAfterControlStatementStyle> {
@@ -944,6 +954,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
+ IO.mapOptional("AlignAfterOpenBracketBreak",
+ Style.AlignAfterOpenBracketBreak);
IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
IO.mapOptional("AlignConsecutiveAssignments",
Style.AlignConsecutiveAssignments);
@@ -1192,6 +1204,18 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("WrapNamespaceBodyWithEmptyLines",
Style.WrapNamespaceBodyWithEmptyLines);
+ // If AlignAfterOpenBracket was specified but AlignAfterOpenBracketBreak
+ // was not, initialize the latter for backwards compatibility.
+ if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak ||
+ Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) &&
+ Style.AlignAfterOpenBracketBreak ==
+ FormatStyle::AlignAfterOpenBracketCustom()) {
+ if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak)
+ Style.AlignAfterOpenBracketBreak.InIfConditionalStatements = true;
+ Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements = false;
+ Style.AlignAfterOpenBracketBreak.Other = true;
+ }
+
// If AlwaysBreakAfterDefinitionReturnType was specified but
// BreakAfterReturnType was not, initialize the latter from the former for
// backwards compatibility.
@@ -1475,6 +1499,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
FormatStyle LLVMStyle;
LLVMStyle.AccessModifierOffset = -2;
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
+ LLVMStyle.AlignAfterOpenBracketBreak = {};
LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
LLVMStyle.AlignConsecutiveAssignments = {};
LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
@@ -1791,6 +1816,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.SpacesBeforeTrailingComments = 1;
} else if (Language == FormatStyle::LK_JavaScript) {
GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ GoogleStyle.AlignAfterOpenBracketBreak = {true, false, true};
GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
// TODO: still under discussion whether to switch to SLS_All.
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index b3540f39e6f69fc..bbe2ba082cab6cc 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -6174,7 +6174,13 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Next && Next->is(tok::l_paren))
return false;
const FormatToken *Previous = Right.MatchingParen->Previous;
- return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf()));
+ if (!Previous)
+ return true;
+ if (Previous->isOneOf(tok::kw_for, tok::kw_while, tok::kw_switch))
+ return Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements;
+ if (Previous->isIf())
+ return Style.AlignAfterOpenBracketBreak.InIfConditionalStatements;
+ return Style.AlignAfterOpenBracketBreak.Other;
}
if (Left.isOneOf(tok::r_paren, TT_TrailingAnnotation) &&
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 9cd262960b72468..63cf4d84551dc38 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -215,6 +215,11 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(SpaceBeforeSquareBrackets);
CHECK_PARSE_BOOL(VerilogBreakBetweenInstancePorts);
+ CHECK_PARSE_NESTED_BOOL(AlignAfterOpenBracketBreak,
+ InIfConditionalStatements);
+ CHECK_PARSE_NESTED_BOOL(AlignAfterOpenBracketBreak,
+ InOtherConditionalStatements);
+ CHECK_PARSE_NESTED_BOOL(AlignAfterOpenBracketBreak, Other);
CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, Enabled);
CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements,
AcrossEmptyLines);
@@ -534,6 +539,13 @@ TEST(ConfigParseTest, ParsesConfiguration) {
FormatStyle::BAS_DontAlign);
CHECK_PARSE("AlignAfterOpenBracket: true", AlignAfterOpenBracket,
FormatStyle::BAS_Align);
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_Align;
+ Style.AlignAfterOpenBracketBreak = {};
+ CHECK_PARSE("AlignAfterOpenBracket: AlwaysBreak", AlignAfterOpenBracketBreak,
+ FormatStyle::AlignAfterOpenBracketCustom(true, false, true));
+ Style.AlignAfterOpenBracketBreak = {};
+ CHECK_PARSE("AlignAfterOpenBracket: BlockIndent", AlignAfterOpenBracketBreak,
+ FormatStyle::AlignAfterOpenBracketCustom(false, false, true));
Style.AlignEscapedNewlines = FormatStyle::ENAS_Left;
CHECK_PARSE("AlignEscapedNewlines: DontAlign", AlignEscapedNewlines,
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 9b9ce35f83bc597..3c8bc768fa29aa6 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -5079,6 +5079,7 @@ TEST_F(FormatTest, BracedInitializerIndentWidth) {
auto Style = getLLVMStyleWithColumns(60);
Style.BinPackArguments = true;
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
Style.BracedInitializerIndentWidth = 6;
// Non-initializing braces are unaffected by BracedInitializerIndentWidth.
@@ -7339,6 +7340,7 @@ TEST_F(FormatTest, ExpressionIndentationBreakingBeforeOperators) {
Style = getLLVMStyleWithColumns(20);
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
Style.BinPackParameters = FormatStyle::BPPS_OnePerLine;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
Style.ContinuationIndentWidth = 2;
verifyFormat("struct Foo {\n"
@@ -8008,12 +8010,14 @@ TEST_F(FormatTest, AllowAllArgumentsOnNextLineDontAlign) {
// However, BAS_AlwaysBreak and BAS_BlockIndent should take precedence over
// AllowAllArgumentsOnNextLine.
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat(StringRef("functionCall(\n"
" paramA, paramB, paramC);\n"
"void functionDecl(\n"
" int A, int B, int C);"),
Input, Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.AlignAfterOpenBracketBreak = {false, false, true};
verifyFormat("functionCall(\n"
" paramA, paramB, paramC\n"
");\n"
@@ -8026,6 +8030,7 @@ TEST_F(FormatTest, AllowAllArgumentsOnNextLineDontAlign) {
// first argument.
Style.AllowAllArgumentsOnNextLine = true;
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat(StringRef("functionCall(\n"
" paramA, paramB, paramC);\n"
"void functionDecl(\n"
@@ -8947,6 +8952,7 @@ TEST_F(FormatTest, FormatsOneParameterPerLineIfNecessary) {
TEST_F(FormatTest, FormatsDeclarationBreakAlways) {
FormatStyle BreakAlways = getGoogleStyle();
BreakAlways.BinPackParameters = FormatStyle::BPPS_AlwaysOnePerLine;
+ BreakAlways.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat("void f(int a,\n"
" int b);",
BreakAlways);
@@ -8975,6 +8981,7 @@ TEST_F(FormatTest, FormatsDeclarationBreakAlways) {
TEST_F(FormatTest, FormatsDefinitionBreakAlways) {
FormatStyle BreakAlways = getGoogleStyle();
BreakAlways.BinPackParameters = FormatStyle::BPPS_AlwaysOnePerLine;
+ BreakAlways.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat("void f(int a,\n"
" int b) {\n"
" f(a, b);\n"
@@ -9480,6 +9487,7 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) {
Style.ColumnLimit = 80;
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
Style.BinPackArguments = false;
Style.BinPackParameters = FormatStyle::BPPS_OnePerLine;
verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
@@ -9531,6 +9539,7 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) {
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.AlignAfterOpenBracketBreak = {false, false, true};
Style.BinPackArguments = false;
Style.BinPackParameters = FormatStyle::BPPS_OnePerLine;
verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
@@ -9642,6 +9651,127 @@ TEST_F(FormatTest, ParenthesesAndOperandAlignment) {
Style);
}
+TEST_F(FormatTest, AlignAfterOpenBracketBreakConditionalStatements) {
+ FormatStyle Style = getLLVMStyle();
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.BinPackArguments = false;
+ Style.BinPackParameters = FormatStyle::BPPS_OnePerLine;
+ Style.AlignAfterOpenBracketBreak = {true, true, false};
+
+ verifyFormat(
+ "aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa(\n"
+ " aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa)) &&\n"
+ " aaaaaaaaaaaaaaaa);",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " if constexpr (\n"
+ " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+ ") == 0) {\n"
+ " return;\n"
+ " } else if (\n"
+ " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+ ") == 0) {\n"
+ " return;\n"
+ " }\n"
+ "}",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " switch (\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n"
+ " default:\n"
+ " break;\n"
+ " }\n"
+ "}",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " for (\n"
+ " aaaaaaaaaaaaaaaaaaaaaa = 0;\n"
+ " (aaaaaaaaaaaaaaaaaaaaaa->bbbbbbbbbbbbbb |\n"
+ " aaaaaaaaaaaaaaaaaaaaaa->ccccccccccccccccccccccc) == 0;\n"
+ " aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaa->next) {\n"
+ " ;\n"
+ " }\n"
+ "}",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " while (\n"
+ " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) == 0) "
+ "{\n"
+ " continue;\n"
+ " }\n"
+ "}",
+ Style);
+
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.BinPackArguments = false;
+ Style.BinPackParameters = FormatStyle::BPPS_OnePerLine;
+ Style.AlignAfterOpenBracketBreak = {true, true, false};
+
+ verifyFormat(
+ "aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa(\n"
+ " aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa)) &&\n"
+ " aaaaaaaaaaaaaaaa);",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " if constexpr (\n"
+ " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+ ") == 0\n"
+ " ) {\n"
+ " return;\n"
+ " } else if (\n"
+ " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+ ") == 0\n"
+ " ) {\n"
+ " return;\n"
+ " }\n"
+ "}",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " switch (\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | "
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
+ " ) {\n"
+ " default:\n"
+ " break;\n"
+ " }\n"
+ "}",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " for (\n"
+ " aaaaaaaaaaaaaaaaaaaaaa = 0;\n"
+ " (aaaaaaaaaaaaaaaaaaaaaa->bbbbbbbbbbbbbb |\n"
+ " aaaaaaaaaaaaaaaaaaaaaa->ccccccccccccccccccccccc) == 0;\n"
+ " aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaa->next\n"
+ " ) {\n"
+ " ;\n"
+ " }\n"
+ "}",
+ Style);
+
+ verifyFormat("void foo() {\n"
+ " while (\n"
+ " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) == 0\n"
+ " ) {\n"
+ " continue;\n"
+ " }\n"
+ "}",
+ Style);
+}
+
TEST_F(FormatTest, BreaksConditionalExpressions) {
verifyFormat(
"aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaa\n"
@@ -11473,6 +11603,7 @@ TEST_F(FormatTest, WrapsTemplateParameters) {
" y;",
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
verifyFormat("template <typename... a> struct s {};\n"
"extern s<\n"
@@ -11483,6 +11614,7 @@ TEST_F(FormatTest, WrapsTemplateParameters) {
" y;",
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
verifyFormat("template <typename... a> struct t {};\n"
"extern t<\n"
@@ -14466,6 +14598,7 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
NoBinPacking);
NoBinPacking.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ NoBinPacking.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat("static uint8 CddDp83848Reg[] = {\n"
" CDDDP83848_BMCR_REGISTER,\n"
" CDDDP83848_BMSR_REGISTER,\n"
@@ -16110,12 +16243,14 @@ TEST_F(FormatTest, BreaksStringLiteralOperands) {
// the first must be broken with a line break before it.
FormatStyle Style = getLLVMStyleWithColumns(25);
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat("someFunction(\n"
" \"long long long \"\n"
" \"long\",\n"
" a);",
"someFunction(\"long long long long\", a);", Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.AlignAfterOpenBracketBreak = {false, false, true};
verifyFormat("someFunction(\n"
" \"long long long \"\n"
" \"long\",\n"
@@ -17899,6 +18034,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
Spaces.ColumnLimit = 80;
Spaces.IndentWidth = 4;
Spaces.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Spaces.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat("void foo( ) {\n"
" size_t foo = (*(function))(\n"
" Foooo, Barrrrr, Foooo, Barrrr, FoooooooooLooooong, "
@@ -17924,6 +18060,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
Spaces);
Spaces.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Spaces.AlignAfterOpenBracketBreak = {false, false, true};
verifyFormat("void foo( ) {\n"
" size_t foo = (*(function))(\n"
" Foooo, Barrrrr, Foooo, Barrrr, FoooooooooLooooong, "
@@ -22833,6 +22970,7 @@ TEST_F(FormatTest, ConstructorInitializerIndentWidth) {
" aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}",
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
verifyFormat(
"SomeLongTemplateVariableName<\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>",
@@ -24087,6 +24225,7 @@ TEST_F(FormatTest, FormatsLambdas) {
" }} {}",
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.AlignAfterOpenBracketBreak = {true, false, true};
// FIXME: The following test should pass, but fails at the time of writing.
#if 0
// As long as all the non-lambda arguments fit on a single line, AlwaysBreak
@@ -27280,6 +27419,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndent) {
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.AlignAfterOpenBracketBreak = {false, false, true};
verifyFormat(Short, Style);
verifyFormat(
@@ -27404,6 +27544,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentIfStatement) {
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.AlignAfterOpenBracketBreak = {false, false, true};
verifyFormat("if (foo()) {\n"
" return;\n"
@@ -27466,6 +27607,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentForStatement) {
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.AlignAfterOpenBracketBreak = {false, false, true};
verifyFormat("for (int i = 0; i < 5; ++i) {\n"
" doSomething();\n"
@@ -27483,6 +27625,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentForStatement) {
TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentInitializers) {
auto Style = getLLVMStyleWithColumns(60);
Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent;
+ Style.AlignAfterOpenBracketBreak = {false, false, true};
// Aggregate initialization.
verifyFormat("int LooooooooooooooooooooooooongVariable[2] = {\n"
" 10000000, 20000000\n"
>From f4c32a32c5bff9c9265cb0bd980e39b40f0c5444 Mon Sep 17 00:00:00 2001
From: Gedare Bloom <gedare at rtems.org>
Date: Wed, 11 Sep 2024 22:48:12 -0600
Subject: [PATCH 2/7] Update release notes
---
clang/docs/ReleaseNotes.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 50d3bbbc97e9192..5266c4a17e3345e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -241,6 +241,8 @@ clang-format
- Adds ``BreakBeforeTemplateCloser`` option.
- Adds ``BinPackLongBracedList`` option to override bin packing options in
long (20 item or more) braced list initializer lists.
+- Adds ``AlignAfterOpenBracketBreak`` sub-options for better control of
+ ``AlignAfterOpenBracket`` with ``AlwaysBreak`` or ``BlockIndent`` modes.
libclang
--------
>From 10ddf0a801d6b89a886f0e631190e1d5ca7d899c Mon Sep 17 00:00:00 2001
From: Gedare Bloom <gedare at rtems.org>
Date: Tue, 28 Jan 2025 15:26:43 -0700
Subject: [PATCH 3/7] Handle nested blocks in template strings
---
clang/lib/Format/ContinuationIndenter.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 886e992f26cdbcb..98122043d159b34 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -838,16 +838,16 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous &&
Tok.Previous->is(tok::identifier);
};
- auto IsInTemplateString = [this](const FormatToken &Tok) {
+ auto IsInTemplateString = [this](const FormatToken &Tok, bool NestBlocks) {
if (!Style.isJavaScript())
return false;
for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) {
if (Prev->is(TT_TemplateString) && Prev->opensScope())
return true;
- if (Prev->opensScope() ||
- (Prev->is(TT_TemplateString) && Prev->closesScope())) {
- break;
- }
+ if (Prev->opensScope() && !NestBlocks)
+ return false;
+ if (Prev->is(TT_TemplateString) && Prev->closesScope())
+ return false;
}
return false;
};
@@ -880,7 +880,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
!IsFunctionCallParen(*Previous)) {
return true;
}
- if (IsOpeningBracket(Tok) || IsInTemplateString(Tok))
+ if (IsOpeningBracket(Tok) || IsInTemplateString(Tok, true))
return true;
const auto *Next = Tok.Next;
return !Next || Next->isMemberAccess() ||
@@ -918,7 +918,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
!(Current.MacroParent && Previous.MacroParent) &&
(Current.isNot(TT_LineComment) ||
Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) &&
- !IsInTemplateString(Current)) {
+ !IsInTemplateString(Current, false)) {
CurrentState.Indent = State.Column + Spaces;
CurrentState.IsAligned = true;
}
>From 10d25badf46be81a6be8884a3a37656772a0f8b9 Mon Sep 17 00:00:00 2001
From: Gedare Bloom <gedare at rtems.org>
Date: Tue, 28 Jan 2025 15:38:53 -0700
Subject: [PATCH 4/7] Format: address review comments on initial values
---
clang/lib/Format/Format.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 16a40f270d28a7c..8d416f03e5aa2de 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1499,7 +1499,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
FormatStyle LLVMStyle;
LLVMStyle.AccessModifierOffset = -2;
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
- LLVMStyle.AlignAfterOpenBracketBreak = {};
+ LLVMStyle.AlignAfterOpenBracketBreak = {false, false, false};
LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
LLVMStyle.AlignConsecutiveAssignments = {};
LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
>From 7497ad3e2a227f371cd606cdb7f02b2183d1708c Mon Sep 17 00:00:00 2001
From: Gedare Bloom <gedare at rtems.org>
Date: Tue, 28 Jan 2025 15:42:11 -0700
Subject: [PATCH 5/7] Format.cpp: accept suggested change
---
clang/lib/Format/Format.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 8d416f03e5aa2de..076282d9154a45e 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1210,8 +1210,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) &&
Style.AlignAfterOpenBracketBreak ==
FormatStyle::AlignAfterOpenBracketCustom()) {
- if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak)
- Style.AlignAfterOpenBracketBreak.InIfConditionalStatements = true;
+ Style.AlignAfterOpenBracketBreak.InIfConditionalStatements =
+ Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak;
Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements = false;
Style.AlignAfterOpenBracketBreak.Other = true;
}
>From 50102cc1c2f357e45dce1cdec3a19f7707847630 Mon Sep 17 00:00:00 2001
From: Gedare Bloom <gedare at rtems.org>
Date: Wed, 29 Jan 2025 16:30:58 -0700
Subject: [PATCH 6/7] Format.h: bump version to 21
---
clang/include/clang/Format/Format.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 4a24e39ab3aff7a..46bfaadc5d56ba1 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -175,7 +175,7 @@ struct FormatStyle {
/// InOtherConditionalStatements: false
/// Other: true
/// \endcode
- /// \version 20
+ /// \version 21
AlignAfterOpenBracketCustom AlignAfterOpenBracketBreak;
/// Different style for aligning array initializers.
>From f6bc2ca2934f9172caddbc550eb0e9f7e0b8c81d Mon Sep 17 00:00:00 2001
From: Gedare Bloom <gedare at rtems.org>
Date: Wed, 29 Jan 2025 16:31:23 -0700
Subject: [PATCH 7/7] Run clang-format-style
---
clang/docs/ClangFormatStyleOptions.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 8e3383ec027dede..ce1e557082eb155 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -248,7 +248,7 @@ the configuration (without a prefix: ``Auto``).
.. _AlignAfterOpenBracketBreak:
-**AlignAfterOpenBracketBreak** (``AlignAfterOpenBracketCustom``) :versionbadge:`clang-format 20` :ref:`¶ <AlignAfterOpenBracketBreak>`
+**AlignAfterOpenBracketBreak** (``AlignAfterOpenBracketCustom``) :versionbadge:`clang-format 21` :ref:`¶ <AlignAfterOpenBracketBreak>`
Control of when ``AlignAfterOpenBracket`` breaks an opening bracket.
If ``AlignAfterOpenBracket`` is set to ``AlwaysBreak`` or ``BlockIndent``,
More information about the cfe-commits
mailing list