[clang] [clang-format] Add BreakParametersAfter formatting option (PR #181281)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 16 20:23:14 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-format
Author: None (Ezlanding1)
<details>
<summary>Changes</summary>
Adds the `BreakParametersAfter` option based on the feature request.
Resolves #<!-- -->54220.
---
Full diff: https://github.com/llvm/llvm-project/pull/181281.diff
6 Files Affected:
- (modified) clang/docs/ClangFormatStyleOptions.rst (+31)
- (modified) clang/include/clang/Format/Format.h (+30)
- (modified) clang/lib/Format/Format.cpp (+2)
- (modified) clang/lib/Format/TokenAnnotator.cpp (+17)
- (modified) clang/unittests/Format/ConfigParseTest.cpp (+1)
- (modified) clang/unittests/Format/FormatTest.cpp (+89)
``````````diff
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 5ba117c231ad5..a0673cb8dcbc2 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3752,6 +3752,37 @@ the configuration (without a prefix: ``Auto``).
+.. _BreakParametersAfter:
+
+**BreakParametersAfter** (``Unsigned``) :versionbadge:`clang-format 23` :ref:`¶ <BreakParametersAfter>`
+ If set to a value greater than 0, any parenthesized parameter or argument
+ list with more parameters than the specified number will be formatted with
+ one parameter per line. This applies to all parameter-like lists enclosed
+ in parentheses, including function declarations, function definitions,
+ function calls, and comma expressions.
+
+ .. code-block:: c++
+
+ BreakParametersAfter: 3
+
+ void foo(int a);
+
+ void bar(int a, int b, int c);
+
+ void baz(int a,
+ int b,
+ int c,
+ int d);
+
+ foo(1);
+
+ bar(1, 2, 3);
+
+ baz(1,
+ 2,
+ 3,
+ 4);
+
.. _BreakStringLiterals:
**BreakStringLiterals** (``Boolean``) :versionbadge:`clang-format 3.9` :ref:`¶ <BreakStringLiterals>`
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 43bea4b80cb8a..25ad43d588485 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2609,6 +2609,35 @@ struct FormatStyle {
/// \version 7
BreakInheritanceListStyle BreakInheritanceList;
+ /// If set to a value greater than 0, any parenthesized parameter or argument
+ /// list with more parameters than the specified number will be formatted with
+ /// one parameter per line. This applies to all parameter-like lists enclosed
+ /// in parentheses, including function declarations, function definitions,
+ /// function calls, and comma expressions.
+ /// \code
+ /// BreakParametersAfter: 3
+ ///
+ /// void foo(int a);
+ ///
+ /// void bar(int a, int b, int c);
+ ///
+ /// void baz(int a,
+ /// int b,
+ /// int c,
+ /// int d);
+ ///
+ /// foo(1);
+ ///
+ /// bar(1, 2, 3);
+ ///
+ /// baz(1,
+ /// 2,
+ /// 3,
+ /// 4);
+ /// \endcode
+ /// \version 23
+ unsigned BreakParametersAfter;
+
/// The template declaration breaking style to use.
/// \version 19
BreakTemplateDeclarationsStyle BreakTemplateDeclarations;
@@ -5725,6 +5754,7 @@ struct FormatStyle {
BreakFunctionDefinitionParameters ==
R.BreakFunctionDefinitionParameters &&
BreakInheritanceList == R.BreakInheritanceList &&
+ BreakParametersAfter == R.BreakParametersAfter &&
BreakStringLiterals == R.BreakStringLiterals &&
BreakTemplateDeclarations == R.BreakTemplateDeclarations &&
ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 1e68de531791f..e0388a17f2ef0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1355,6 +1355,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.WhitespaceSensitiveMacros);
IO.mapOptional("WrapNamespaceBodyWithEmptyLines",
Style.WrapNamespaceBodyWithEmptyLines);
+ IO.mapOptional("BreakParametersAfter", Style.BreakParametersAfter);
// If AlwaysBreakAfterDefinitionReturnType was specified but
// BreakAfterReturnType was not, initialize the latter from the former for
@@ -1728,6 +1729,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakFunctionDefinitionParameters = false;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
+ LLVMStyle.BreakParametersAfter = 0;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
LLVMStyle.ColumnLimit = 80;
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index b1c1afbf8684d..44be5ead41e39 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4246,6 +4246,23 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
ChildSize + Current->SpacesRequiredBefore;
}
+ if (Style.BreakParametersAfter > 0 && Prev->is(tok::l_paren) &&
+ Prev->ParameterCount > Style.BreakParametersAfter) {
+ const auto *RParen = Prev->MatchingParen;
+ for (auto *ParamTok = Current; ParamTok && ParamTok != RParen;
+ ParamTok = ParamTok->Next) {
+ if (ParamTok->opensScope()) {
+ ParamTok = ParamTok->MatchingParen;
+ continue;
+ }
+
+ if (startsNextParameter(*ParamTok, Style)) {
+ ParamTok->MustBreakBefore = true;
+ ParamTok->CanBreakBefore = true;
+ }
+ }
+ }
+
if (Current->is(TT_ControlStatementLBrace)) {
if (Style.ColumnLimit > 0 &&
Style.BraceWrapping.AfterControlStatement ==
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 0a116b770f52a..ef442a17a7a8f 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -283,6 +283,7 @@ TEST(ConfigParseTest, ParsesConfigurationIntegers) {
CHECK_PARSE_INT(BracedInitializerIndentWidth);
CHECK_PARSE_INT(PPIndentWidth);
+ CHECK_PARSE_UNSIGNED(BreakParametersAfter);
CHECK_PARSE_UNSIGNED(ColumnLimit);
CHECK_PARSE_UNSIGNED(ConstructorInitializerIndentWidth);
CHECK_PARSE_UNSIGNED(ContinuationIndentWidth);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 33836e28289b4..b9a07d960e67c 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -8164,6 +8164,95 @@ TEST_F(FormatTest, BreakFunctionDefinitionParameters) {
" int B)\n"
" : m_A(A), m_B(B) {}",
Input, Style);
+
+ Style.BinPackParameters = FormatStyle::BPPS_BinPack;
+ Style.BreakFunctionDefinitionParameters = false;
+ Style.BreakParametersAfter = 2;
+ verifyFormat("void functionDecl(paramA, paramB);\n"
+ "void functionDecl(paramA,\n"
+ " paramB,\n"
+ " paramC);\n"
+ "void functionDecl(paramA,\n"
+ " paramB,\n"
+ " paramC,\n"
+ " paramD,\n"
+ " paramE);\n"
+ "void functionDefinition(int A, int B) {}\n"
+ "void functionDefinition(int A,\n"
+ " int B,\n"
+ " int C) {}\n"
+ "Class::Class(int A, int B) {}\n"
+ "Class::Class(int A,\n"
+ " int B,\n"
+ " int C) {}\n"
+ "call(a, b);\n"
+ "call(a,\n"
+ " b,\n"
+ " c);\n"
+ "new Class(a, b);\n"
+ "new Class(a,\n"
+ " b,\n"
+ " c);\n"
+ "int x = (a, b);\n"
+ "int y = (a,\n"
+ " b,\n"
+ " c);\n"
+ "(a, b);\n"
+ "(a,\n"
+ " b,\n"
+ " c);",
+ Style);
+ Style.BreakParametersAfter = 4;
+ verifyFormat("void functionDecl(paramA);\n"
+ "void functionDecl(paramA, paramB);\n"
+ "void functionDecl(paramA, paramB, paramC);\n"
+ "void functionDecl(paramA, paramB, paramC, paramD);\n"
+ "void functionDecl(paramA,\n"
+ " paramB,\n"
+ " paramC,\n"
+ " paramD,\n"
+ " paramE);\n"
+ "void functionDecl(paramA,\n"
+ " paramB,\n"
+ " paramC,\n"
+ " paramD,\n"
+ " paramE,\n"
+ " paramF);\n"
+ "void functionDefinition(int A, int B, int C, int D) {}\n"
+ "void functionDefinition(int A,\n"
+ " int B,\n"
+ " int C,\n"
+ " int D,\n"
+ " int E) {}\n"
+ "Class::Class(int A, int B) {}\n"
+ "Class::Class(int A, int B, int C, int D) {}\n"
+ "Class::Class(int A,\n"
+ " int B,\n"
+ " int C,\n"
+ " int D,\n"
+ " int E) {}\n"
+ "call(a,\n"
+ " b,\n"
+ " c,\n"
+ " d,\n"
+ " e);\n"
+ "new Class(a,\n"
+ " b,\n"
+ " c,\n"
+ " d,\n"
+ " e);\n"
+ "int y = (a,\n"
+ " b,\n"
+ " c,\n"
+ " d,\n"
+ " e);\n"
+ "(a,\n"
+ " b,\n"
+ " c,\n"
+ " d,\n"
+ " e);",
+ Style);
+ Style.BreakParametersAfter = 0;
}
TEST_F(FormatTest, BreakBeforeInlineASMColon) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/181281
More information about the cfe-commits
mailing list