[clang] cc67cb6 - [clang-format] Add AfterComma option for BreakConstructorInitializers (#180541)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 16 11:26:06 PST 2026
Author: Perceval Anichini
Date: 2026-02-16T20:26:02+01:00
New Revision: cc67cb624de33a2e187f700eeb7ec3a1fd6756fe
URL: https://github.com/llvm/llvm-project/commit/cc67cb624de33a2e187f700eeb7ec3a1fd6756fe
DIFF: https://github.com/llvm/llvm-project/commit/cc67cb624de33a2e187f700eeb7ec3a1fd6756fe.diff
LOG: [clang-format] Add AfterComma option for BreakConstructorInitializers (#180541)
This patch introduces a new `AfterComma` value for the
`BreakConstructorInitializers` style option. This style keeps the
constructor initializer colon on the same line as the constructor
declaration and breaks after each comma in the initializer list.
Example formatting:
```cpp
Constructor() : initializer1(),
initializer2()
```
This style provides an alternative to the existing BeforeColon,
BeforeComma, and AfterColon options, allowing developers to maintain the
colon on the constructor line while placing each initializer on its own
line after commas.
---------
Co-authored-by: Perceval <perceval at trilogic.fr>
Added:
Modified:
clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Format/Format.h
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/ConfigParseTest.cpp
clang/unittests/Format/FormatTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 378a0c591d747..437f559fc0395 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3686,6 +3686,14 @@ the configuration (without a prefix: ``Auto``).
initializer1(),
initializer2()
+ * ``BCIS_AfterComma`` (in configuration: ``AfterComma``)
+ Break constructor initializers only after the commas.
+
+ .. code-block:: c++
+
+ Constructor() : initializer1(),
+ initializer2()
+
.. _BreakFunctionDefinitionParameters:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5ac5ae4a7d37e..a2cdeb7bc1744 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -384,8 +384,10 @@ AST Matchers
clang-format
------------
-- Add ``ObjCSpaceAfterMethodDeclarationPrefix`` option to control space between the
+- Add ``ObjCSpaceAfterMethodDeclarationPrefix`` option to control space between the
'-'/'+' and the return type in Objective-C method declarations
+- Add ``AfterComma`` value to ``BreakConstructorInitializers`` to allow breaking
+ constructor initializers after commas, keeping the colon on the same line.
libclang
--------
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 57ae14304b969..ca0bd47d10613 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2477,7 +2477,13 @@ struct FormatStyle {
/// initializer1(),
/// initializer2()
/// \endcode
- BCIS_AfterColon
+ BCIS_AfterColon,
+ /// Break constructor initializers only after the commas.
+ /// \code
+ /// Constructor() : initializer1(),
+ /// initializer2()
+ /// \endcode
+ BCIS_AfterComma
};
/// The break constructor initializers style to use.
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 1272bb72d423f..f1edd71df73fa 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -510,7 +510,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon
? Previous
: Current;
- if (BreakConstructorInitializersToken.is(TT_CtorInitializerColon) &&
+ if (Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterComma &&
+ BreakConstructorInitializersToken.is(TT_CtorInitializerColon) &&
(State.Column + State.Line->Last->TotalLength - Previous.TotalLength >
getColumnLimit(State) ||
CurrentState.BreakBeforeParameter) &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 1e68de531791f..738e99dbb56a8 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -282,6 +282,7 @@ struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
+ IO.enumCase(Value, "AfterComma", FormatStyle::BCIS_AfterComma);
}
};
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 9e54c3f253abb..c66d883b30870 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5964,6 +5964,11 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma)) {
return true;
}
+
+ if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterComma &&
+ Left.is(TT_CtorInitializerComma)) {
+ return true;
+ }
}
if (Style.PackConstructorInitializers < FormatStyle::PCIS_CurrentLine &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
@@ -6509,11 +6514,16 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return true;
if (Left.is(TT_CtorInitializerColon)) {
- return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&
+ return (Style.BreakConstructorInitializers ==
+ FormatStyle::BCIS_AfterColon ||
+ Style.BreakConstructorInitializers ==
+ FormatStyle::BCIS_AfterComma) &&
(!Right.isTrailingComment() || Right.NewlinesBefore > 0);
}
- if (Right.is(TT_CtorInitializerColon))
- return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon;
+ if (Right.is(TT_CtorInitializerColon)) {
+ return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon &&
+ Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterComma;
+ }
if (Left.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) {
return false;
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 0a116b770f52a..bea6b54883265 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -466,6 +466,8 @@ TEST(ConfigParseTest, ParsesConfiguration) {
BreakConstructorInitializers, FormatStyle::BCIS_BeforeComma);
CHECK_PARSE("BreakConstructorInitializers: AfterColon",
BreakConstructorInitializers, FormatStyle::BCIS_AfterColon);
+ CHECK_PARSE("BreakConstructorInitializers: AfterComma",
+ BreakConstructorInitializers, FormatStyle::BCIS_AfterComma);
CHECK_PARSE("BreakConstructorInitializers: BeforeColon",
BreakConstructorInitializers, FormatStyle::BCIS_BeforeColon);
// For backward compatibility:
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 33836e28289b4..d6c49163abbc9 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -8448,6 +8448,54 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) {
Style);
}
+TEST_F(FormatTest, BreakConstructorInitializersAfterComma) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterComma;
+
+ verifyFormat("Constructor() : Initializer(FitsOnTheLine) {}", Style);
+ verifyFormat("Constructor() : a(a), b(b), c(c) {}", Style);
+
+ Style.PackConstructorInitializers = FormatStyle::PCIS_Never;
+ verifyFormat("SomeClass::Constructor() : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}",
+ Style);
+ verifyFormat("SomeClassWithALongName::Constructor(\n"
+ " int aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " int bbbbbbbbbbbbb) : aaaaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbb(b) {}",
+ Style);
+
+ Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
+ verifyFormat("SomeClass::Constructor() : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}",
+ Style);
+
+ Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
+ verifyFormat("SomeClass::Constructor() : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}",
+ Style);
+
+ Style.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
+ verifyFormat("SomeClass::Constructor() : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}",
+ Style);
+
+ Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly;
+ verifyFormat("SomeClass::Constructor() : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
+ " aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}",
+ Style);
+
+ Style.ColumnLimit = 0;
+ Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
+ verifyFormat("SomeClass::Constructor() : a(a), b(b), c(c) {}", Style);
+ verifyNoChange("SomeClass::Constructor() : a(a),\n"
+ " b(b),\n"
+ " c(c) {}",
+ Style);
+}
+
#ifndef EXPENSIVE_CHECKS
// Expensive checks enables libstdc++ checking which includes validating the
// state of ranges used in std::priority_queue - this blows out the
More information about the cfe-commits
mailing list