https://github.com/itzexpoexpo updated https://github.com/llvm/llvm-project/pull/154580
From 3a8be59bd1fb94102d446cdb8fdf1b266123c613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Slanina?= <itzexpoe...@gmail.com> Date: Wed, 20 Aug 2025 19:28:23 +0200 Subject: [PATCH 1/7] [clang-format] Add option AllowShortRecordsOnASingleLine This commit supersedes PR #151970 by adding the option AllowShortRecordsOnASingleLine that allows the following formatting: struct foo {}; struct bar { int i; }; struct baz { int i; int j; int k; }; --- clang/docs/ClangFormatStyleOptions.rst | 32 +++++++++ clang/include/clang/Format/Format.h | 26 ++++++++ clang/lib/Format/Format.cpp | 11 ++++ clang/lib/Format/TokenAnnotator.cpp | 13 ++-- clang/lib/Format/UnwrappedLineFormatter.cpp | 22 ++++++- clang/lib/Format/UnwrappedLineParser.cpp | 23 +++++-- clang/unittests/Format/ConfigParseTest.cpp | 8 +++ clang/unittests/Format/FormatTest.cpp | 73 +++++++++++++++++++++ 8 files changed, 193 insertions(+), 15 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 02986a94a656c..537d81747a834 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2093,6 +2093,38 @@ the configuration (without a prefix: ``Auto``). **AllowShortNamespacesOnASingleLine** (``Boolean``) :versionbadge:`clang-format 20` :ref:`¶ <AllowShortNamespacesOnASingleLine>` If ``true``, ``namespace a { class b; }`` can be put on a single line. +.. _AllowShortRecordsOnASingleLine: + +**AllowShortRecordsOnASingleLine** (``ShortRecordStyle``) :ref:`¶ <AllowShortRecordsOnASingleLine>` + Dependent on the value, ``struct bar { int i; }`` can be put on a single + line. + + Possible values: + + * ``SRS_Never`` (in configuration: ``Never``) + Never merge records into a single line. + + * ``SRS_Empty`` (in configuration: ``Empty``) + Only merge empty records. + + .. code-block:: c++ + + struct foo {}; + struct bar + { + int i; + }; + + * ``SRS_All`` (in configuration: ``All``) + Merge all records that fit on a single line. + + .. code-block:: c++ + + struct foo {}; + struct bar { int i; }; + + + .. _AlwaysBreakAfterDefinitionReturnType: **AlwaysBreakAfterDefinitionReturnType** (``DefinitionReturnTypeBreakingStyle``) :versionbadge:`clang-format 3.7` :ref:`¶ <AlwaysBreakAfterDefinitionReturnType>` diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 31582a40de866..27f4e7cd9b6a7 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -992,6 +992,32 @@ struct FormatStyle { /// \version 20 bool AllowShortNamespacesOnASingleLine; + /// Different styles for merging short records + /// (``class``,``struct``,``union``). + enum ShortRecordStyle : int8_t { + /// Never merge records into a single line. + SRS_Never, + /// Only merge empty records. + /// \code + /// struct foo {}; + /// struct bar + /// { + /// int i; + /// }; + /// \endcode + SRS_Empty, + /// Merge all records that fit on a single line. + /// \code + /// struct foo {}; + /// struct bar { int i; }; + /// \endcode + SRS_All + }; + + /// Dependent on the value, ``struct bar { int i; }`` can be put on a single + /// line. + ShortRecordStyle AllowShortRecordsOnASingleLine; + /// Different ways to break after the function definition return type. /// This option is **deprecated** and is retained for backwards compatibility. enum DefinitionReturnTypeBreakingStyle : int8_t { diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 063780721423f..4f9c0dfcad722 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -660,6 +660,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> { } }; +template <> struct ScalarEnumerationTraits<FormatStyle::ShortRecordStyle> { + static void enumeration(IO &IO, FormatStyle::ShortRecordStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::SRS_Never); + IO.enumCase(Value, "Empty", FormatStyle::SRS_Empty); + IO.enumCase(Value, "All", FormatStyle::SRS_All); + } +}; + template <> struct MappingTraits<FormatStyle::SortIncludesOptions> { static void enumInput(IO &IO, FormatStyle::SortIncludesOptions &Value) { IO.enumCase(Value, "Never", FormatStyle::SortIncludesOptions({})); @@ -1012,6 +1020,8 @@ template <> struct MappingTraits<FormatStyle> { Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLambdasOnASingleLine", Style.AllowShortLambdasOnASingleLine); + IO.mapOptional("AllowShortRecordsOnASingleLine", + Style.AllowShortRecordsOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); IO.mapOptional("AllowShortNamespacesOnASingleLine", @@ -1535,6 +1545,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; + LLVMStyle.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Never; LLVMStyle.AllowShortLoopsOnASingleLine = false; LLVMStyle.AllowShortNamespacesOnASingleLine = false; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 4801d27b1395a..50ed77313366a 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5933,12 +5933,15 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; } - // Don't attempt to interpret struct return types as structs. + // Don't attempt to interpret record return types as records. if (Right.isNot(TT_FunctionLBrace)) { - return (Line.startsWith(tok::kw_class) && - Style.BraceWrapping.AfterClass) || - (Line.startsWith(tok::kw_struct) && - Style.BraceWrapping.AfterStruct); + return ((Line.startsWith(tok::kw_class) && + Style.BraceWrapping.AfterClass) || + (Line.startsWith(tok::kw_struct) && + Style.BraceWrapping.AfterStruct) || + (Line.startsWith(tok::kw_union) && + Style.BraceWrapping.AfterUnion)) && + Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_Never; } } diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 0adf7ee9ed543..f07559ab96418 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -453,6 +453,19 @@ class LineJoiner { } } + auto ShouldMergeShortRecords = [this, &I, &NextLine, PreviousLine, + TheLine]() { + if (Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_All) + return true; + if (Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_Empty && + NextLine.First->is(tok::r_brace)) { + return true; + } + return false; + }; + + bool MergeShortRecord = ShouldMergeShortRecords(); + // Don't merge an empty template class or struct if SplitEmptyRecords // is defined. if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord && @@ -495,7 +508,8 @@ class LineJoiner { // elsewhere. ShouldMerge = !Style.BraceWrapping.AfterClass || (NextLine.First->is(tok::r_brace) && - !Style.BraceWrapping.SplitEmptyRecord); + !Style.BraceWrapping.SplitEmptyRecord) || + MergeShortRecord; } else if (TheLine->InPPDirective || !TheLine->First->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct)) { @@ -869,9 +883,11 @@ class LineJoiner { return 1; } else if (Limit != 0 && !Line.startsWithNamespace() && !startsExternCBlock(Line)) { - // We don't merge short records. - if (isRecordLBrace(*Line.Last)) + // Merge short records only when requested. + if (isRecordLBrace(*Line.Last) && + Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_Never) { return 0; + } // Check that we still have three lines and they fit into the limit. if (I + 2 == E || I[2]->Type == LT_Invalid) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 91b8fdc8a3c38..3b23502febede 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -952,20 +952,26 @@ static bool isIIFE(const UnwrappedLine &Line, } static bool ShouldBreakBeforeBrace(const FormatStyle &Style, - const FormatToken &InitialToken) { + const FormatToken &InitialToken, + const FormatToken &NextToken) { tok::TokenKind Kind = InitialToken.Tok.getKind(); if (InitialToken.is(TT_NamespaceMacro)) Kind = tok::kw_namespace; + bool IsEmptyBlock = NextToken.is(tok::r_brace); + bool WrapRecordAllowed = + !(IsEmptyBlock && + Style.AllowShortRecordsOnASingleLine != FormatStyle::SRS_Never); + switch (Kind) { case tok::kw_namespace: return Style.BraceWrapping.AfterNamespace; case tok::kw_class: - return Style.BraceWrapping.AfterClass; + return Style.BraceWrapping.AfterClass && WrapRecordAllowed; case tok::kw_union: - return Style.BraceWrapping.AfterUnion; + return Style.BraceWrapping.AfterUnion && WrapRecordAllowed; case tok::kw_struct: - return Style.BraceWrapping.AfterStruct; + return Style.BraceWrapping.AfterStruct && WrapRecordAllowed; case tok::kw_enum: return Style.BraceWrapping.AfterEnum; default: @@ -3191,7 +3197,7 @@ void UnwrappedLineParser::parseNamespace() { if (FormatTok->is(tok::l_brace)) { FormatTok->setFinalizedType(TT_NamespaceLBrace); - if (ShouldBreakBeforeBrace(Style, InitialToken)) + if (ShouldBreakBeforeBrace(Style, InitialToken, *Tokens->peekNextToken())) addUnwrappedLine(); unsigned AddLevels = @@ -3856,7 +3862,7 @@ bool UnwrappedLineParser::parseEnum() { } if (!Style.AllowShortEnumsOnASingleLine && - ShouldBreakBeforeBrace(Style, InitialToken)) { + ShouldBreakBeforeBrace(Style, InitialToken, *Tokens->peekNextToken())) { addUnwrappedLine(); } // Parse enum body. @@ -4151,8 +4157,11 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr, bool IsJavaRecord) { if (ParseAsExpr) { parseChildBlock(); } else { - if (ShouldBreakBeforeBrace(Style, InitialToken)) + if (Style.AllowShortRecordsOnASingleLine != FormatStyle::SRS_All && + ShouldBreakBeforeBrace(Style, InitialToken, + *Tokens->peekNextToken())) { addUnwrappedLine(); + } unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u; parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/false); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 9de3cca71630d..338f10f8ff4b9 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -655,6 +655,14 @@ TEST(ConfigParseTest, ParsesConfiguration) { CHECK_PARSE("AllowShortLambdasOnASingleLine: true", AllowShortLambdasOnASingleLine, FormatStyle::SLS_All); + Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Never; + CHECK_PARSE("AllowShortRecordsOnASingleLine: Empty", + AllowShortRecordsOnASingleLine, FormatStyle::SRS_Empty); + CHECK_PARSE("AllowShortRecordsOnASingleLine: All", + AllowShortRecordsOnASingleLine, FormatStyle::SRS_All); + CHECK_PARSE("AllowShortRecordsOnASingleLine: Never", + AllowShortRecordsOnASingleLine, FormatStyle::SRS_Never); + Style.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Both; CHECK_PARSE("SpaceAroundPointerQualifiers: Default", SpaceAroundPointerQualifiers, FormatStyle::SAPQ_Default); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 96cc650f52a5d..e62a37a772cbd 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -8624,6 +8624,19 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { Style); } +TEST_F(FormatTest, BreakFunctionsReturningRecords) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterFunction = true; + Style.BraceWrapping.AfterClass = false; + Style.BraceWrapping.AfterStruct = false; + Style.BraceWrapping.AfterUnion = false; + + verifyFormat("class Bar foo() {}", Style); + verifyFormat("struct Bar foo() {}", Style); + verifyFormat("union Bar foo() {}", Style); +} + TEST_F(FormatTest, DontBreakBeforeQualifiedOperator) { // Regression test for https://bugs.llvm.org/show_bug.cgi?id=40516: // Prefer keeping `::` followed by `operator` together. @@ -15615,6 +15628,66 @@ TEST_F(FormatTest, NeverMergeShortRecords) { Style); } +TEST_F(FormatTest, AllowShortRecordsOnASingleLine) { + FormatStyle Style = getLLVMStyle(); + + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterClass = true; + Style.BraceWrapping.AfterStruct = true; + Style.BraceWrapping.AfterUnion = true; + Style.BraceWrapping.SplitEmptyRecord = false; + Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Never; + + verifyFormat("class foo\n{\n" + " void bar();\n" + "};", + Style); + verifyFormat("class foo\n{};", Style); + + verifyFormat("struct foo\n{\n" + " int bar;\n" + "};", + Style); + verifyFormat("struct foo\n{};", Style); + + verifyFormat("union foo\n{\n" + " int bar;\n" + "};", + Style); + verifyFormat("union foo\n{};", Style); + + Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Empty; + + verifyFormat("class foo\n{\n" + " void bar();\n" + "};", + Style); + verifyFormat("class foo {};", Style); + + verifyFormat("struct foo\n{\n" + " int bar;\n" + "};", + Style); + verifyFormat("struct foo {};", Style); + + verifyFormat("union foo\n{\n" + " int bar;\n" + "};", + Style); + verifyFormat("union foo {};", Style); + + Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_All; + + verifyFormat("class foo { void bar(); };", Style); + verifyFormat("class foo {};", Style); + + verifyFormat("struct foo { int bar; };", Style); + verifyFormat("struct foo {};", Style); + + verifyFormat("union foo { int bar; };", Style); + verifyFormat("union foo {};", Style); +} + TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) { // Elaborate type variable declarations. verifyFormat("struct foo a = {bar};\nint n;"); From 6659057cfc4ecebc8ed963d57cb158b3b34d209e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Slanina?= <itzexpoe...@gmail.com> Date: Wed, 20 Aug 2025 23:54:07 +0200 Subject: [PATCH 2/7] Fixup: option order, inline MergeShortRecord lambda --- clang/lib/Format/Format.cpp | 4 ++-- clang/lib/Format/UnwrappedLineFormatter.cpp | 18 ++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 4f9c0dfcad722..be5ca9133b3de 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1020,12 +1020,12 @@ template <> struct MappingTraits<FormatStyle> { Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLambdasOnASingleLine", Style.AllowShortLambdasOnASingleLine); - IO.mapOptional("AllowShortRecordsOnASingleLine", - Style.AllowShortRecordsOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); IO.mapOptional("AllowShortNamespacesOnASingleLine", Style.AllowShortNamespacesOnASingleLine); + IO.mapOptional("AllowShortRecordsOnASingleLine", + Style.AllowShortRecordsOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index f07559ab96418..ac5aa33d8d5e0 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -453,18 +453,16 @@ class LineJoiner { } } - auto ShouldMergeShortRecords = [this, &I, &NextLine, PreviousLine, - TheLine]() { - if (Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_All) - return true; - if (Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_Empty && - NextLine.First->is(tok::r_brace)) { + const bool MergeShortRecord = [this, &NextLine]() { + switch (Style.AllowShortRecordsOnASingleLine) { + case FormatStyle::SRS_All: return true; + case FormatStyle::SRS_Empty: + return NextLine.First->is(tok::r_brace); + case FormatStyle::SRS_Never: + return false; } - return false; - }; - - bool MergeShortRecord = ShouldMergeShortRecords(); + }(); // Don't merge an empty template class or struct if SplitEmptyRecords // is defined. From cd7677169ef991f84bf3461c16a4a8072b508166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Slanina?= <itzexpoe...@gmail.com> Date: Sun, 24 Aug 2025 15:24:59 +0200 Subject: [PATCH 3/7] Use consistently named enum values --- clang/include/clang/Format/Format.h | 2 +- clang/lib/Format/Format.cpp | 2 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 2 +- clang/lib/Format/UnwrappedLineParser.cpp | 2 +- clang/unittests/Format/ConfigParseTest.cpp | 4 ++-- clang/unittests/Format/FormatTest.cpp | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 27f4e7cd9b6a7..9c620ff8dd3fc 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1011,7 +1011,7 @@ struct FormatStyle { /// struct foo {}; /// struct bar { int i; }; /// \endcode - SRS_All + SRS_Always }; /// Dependent on the value, ``struct bar { int i; }`` can be put on a single diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index be5ca9133b3de..8e62b8e533d06 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -664,7 +664,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortRecordStyle> { static void enumeration(IO &IO, FormatStyle::ShortRecordStyle &Value) { IO.enumCase(Value, "Never", FormatStyle::SRS_Never); IO.enumCase(Value, "Empty", FormatStyle::SRS_Empty); - IO.enumCase(Value, "All", FormatStyle::SRS_All); + IO.enumCase(Value, "Always", FormatStyle::SRS_Always); } }; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index ac5aa33d8d5e0..6d0e266457a66 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -455,7 +455,7 @@ class LineJoiner { const bool MergeShortRecord = [this, &NextLine]() { switch (Style.AllowShortRecordsOnASingleLine) { - case FormatStyle::SRS_All: + case FormatStyle::SRS_Always: return true; case FormatStyle::SRS_Empty: return NextLine.First->is(tok::r_brace); diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 3b23502febede..25d76ed2fb2b1 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -4157,7 +4157,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr, bool IsJavaRecord) { if (ParseAsExpr) { parseChildBlock(); } else { - if (Style.AllowShortRecordsOnASingleLine != FormatStyle::SRS_All && + if (Style.AllowShortRecordsOnASingleLine != FormatStyle::SRS_Always && ShouldBreakBeforeBrace(Style, InitialToken, *Tokens->peekNextToken())) { addUnwrappedLine(); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 338f10f8ff4b9..e7d2b41d417ce 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -658,8 +658,8 @@ TEST(ConfigParseTest, ParsesConfiguration) { Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Never; CHECK_PARSE("AllowShortRecordsOnASingleLine: Empty", AllowShortRecordsOnASingleLine, FormatStyle::SRS_Empty); - CHECK_PARSE("AllowShortRecordsOnASingleLine: All", - AllowShortRecordsOnASingleLine, FormatStyle::SRS_All); + CHECK_PARSE("AllowShortRecordsOnASingleLine: Always", + AllowShortRecordsOnASingleLine, FormatStyle::SRS_Always); CHECK_PARSE("AllowShortRecordsOnASingleLine: Never", AllowShortRecordsOnASingleLine, FormatStyle::SRS_Never); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index e62a37a772cbd..e1b2c7f822ccf 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15676,7 +15676,7 @@ TEST_F(FormatTest, AllowShortRecordsOnASingleLine) { Style); verifyFormat("union foo {};", Style); - Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_All; + Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Always; verifyFormat("class foo { void bar(); };", Style); verifyFormat("class foo {};", Style); From df53107146f35be70cf3a10ae02bba0dfad6157c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Slanina?= <itzexpoe...@gmail.com> Date: Sun, 24 Aug 2025 15:54:21 +0200 Subject: [PATCH 4/7] Change option name to use singular form --- clang/include/clang/Format/Format.h | 2 +- clang/lib/Format/Format.cpp | 6 +++--- clang/lib/Format/TokenAnnotator.cpp | 2 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 4 ++-- clang/lib/Format/UnwrappedLineParser.cpp | 4 ++-- clang/unittests/Format/ConfigParseTest.cpp | 14 +++++++------- clang/unittests/Format/FormatTest.cpp | 6 +++--- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 9c620ff8dd3fc..51ec4b9bcedcc 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1016,7 +1016,7 @@ struct FormatStyle { /// Dependent on the value, ``struct bar { int i; }`` can be put on a single /// line. - ShortRecordStyle AllowShortRecordsOnASingleLine; + ShortRecordStyle AllowShortRecordOnASingleLine; /// Different ways to break after the function definition return type. /// This option is **deprecated** and is retained for backwards compatibility. diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 8e62b8e533d06..6a422a879c8ba 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1024,8 +1024,8 @@ template <> struct MappingTraits<FormatStyle> { Style.AllowShortLoopsOnASingleLine); IO.mapOptional("AllowShortNamespacesOnASingleLine", Style.AllowShortNamespacesOnASingleLine); - IO.mapOptional("AllowShortRecordsOnASingleLine", - Style.AllowShortRecordsOnASingleLine); + IO.mapOptional("AllowShortRecordOnASingleLine", + Style.AllowShortRecordOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", @@ -1545,7 +1545,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; - LLVMStyle.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Never; + LLVMStyle.AllowShortRecordOnASingleLine = FormatStyle::SRS_Never; LLVMStyle.AllowShortLoopsOnASingleLine = false; LLVMStyle.AllowShortNamespacesOnASingleLine = false; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 50ed77313366a..36541141edd16 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5941,7 +5941,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, Style.BraceWrapping.AfterStruct) || (Line.startsWith(tok::kw_union) && Style.BraceWrapping.AfterUnion)) && - Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_Never; + Style.AllowShortRecordOnASingleLine == FormatStyle::SRS_Never; } } diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 6d0e266457a66..03b8637699367 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -454,7 +454,7 @@ class LineJoiner { } const bool MergeShortRecord = [this, &NextLine]() { - switch (Style.AllowShortRecordsOnASingleLine) { + switch (Style.AllowShortRecordOnASingleLine) { case FormatStyle::SRS_Always: return true; case FormatStyle::SRS_Empty: @@ -883,7 +883,7 @@ class LineJoiner { !startsExternCBlock(Line)) { // Merge short records only when requested. if (isRecordLBrace(*Line.Last) && - Style.AllowShortRecordsOnASingleLine == FormatStyle::SRS_Never) { + Style.AllowShortRecordOnASingleLine == FormatStyle::SRS_Never) { return 0; } diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 25d76ed2fb2b1..bf5ebeb4c9f54 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -961,7 +961,7 @@ static bool ShouldBreakBeforeBrace(const FormatStyle &Style, bool IsEmptyBlock = NextToken.is(tok::r_brace); bool WrapRecordAllowed = !(IsEmptyBlock && - Style.AllowShortRecordsOnASingleLine != FormatStyle::SRS_Never); + Style.AllowShortRecordOnASingleLine != FormatStyle::SRS_Never); switch (Kind) { case tok::kw_namespace: @@ -4157,7 +4157,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr, bool IsJavaRecord) { if (ParseAsExpr) { parseChildBlock(); } else { - if (Style.AllowShortRecordsOnASingleLine != FormatStyle::SRS_Always && + if (Style.AllowShortRecordOnASingleLine != FormatStyle::SRS_Always && ShouldBreakBeforeBrace(Style, InitialToken, *Tokens->peekNextToken())) { addUnwrappedLine(); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index e7d2b41d417ce..8351a6cd379c8 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -655,13 +655,13 @@ TEST(ConfigParseTest, ParsesConfiguration) { CHECK_PARSE("AllowShortLambdasOnASingleLine: true", AllowShortLambdasOnASingleLine, FormatStyle::SLS_All); - Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Never; - CHECK_PARSE("AllowShortRecordsOnASingleLine: Empty", - AllowShortRecordsOnASingleLine, FormatStyle::SRS_Empty); - CHECK_PARSE("AllowShortRecordsOnASingleLine: Always", - AllowShortRecordsOnASingleLine, FormatStyle::SRS_Always); - CHECK_PARSE("AllowShortRecordsOnASingleLine: Never", - AllowShortRecordsOnASingleLine, FormatStyle::SRS_Never); + Style.AllowShortRecordOnASingleLine = FormatStyle::SRS_Never; + CHECK_PARSE("AllowShortRecordOnASingleLine: Empty", + AllowShortRecordOnASingleLine, FormatStyle::SRS_Empty); + CHECK_PARSE("AllowShortRecordOnASingleLine: Always", + AllowShortRecordOnASingleLine, FormatStyle::SRS_Always); + CHECK_PARSE("AllowShortRecordOnASingleLine: Never", + AllowShortRecordOnASingleLine, FormatStyle::SRS_Never); Style.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Both; CHECK_PARSE("SpaceAroundPointerQualifiers: Default", diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index e1b2c7f822ccf..10fbe129ebbe9 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15636,7 +15636,7 @@ TEST_F(FormatTest, AllowShortRecordsOnASingleLine) { Style.BraceWrapping.AfterStruct = true; Style.BraceWrapping.AfterUnion = true; Style.BraceWrapping.SplitEmptyRecord = false; - Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Never; + Style.AllowShortRecordOnASingleLine = FormatStyle::SRS_Never; verifyFormat("class foo\n{\n" " void bar();\n" @@ -15656,7 +15656,7 @@ TEST_F(FormatTest, AllowShortRecordsOnASingleLine) { Style); verifyFormat("union foo\n{};", Style); - Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Empty; + Style.AllowShortRecordOnASingleLine = FormatStyle::SRS_Empty; verifyFormat("class foo\n{\n" " void bar();\n" @@ -15676,7 +15676,7 @@ TEST_F(FormatTest, AllowShortRecordsOnASingleLine) { Style); verifyFormat("union foo {};", Style); - Style.AllowShortRecordsOnASingleLine = FormatStyle::SRS_Always; + Style.AllowShortRecordOnASingleLine = FormatStyle::SRS_Always; verifyFormat("class foo { void bar(); };", Style); verifyFormat("class foo {};", Style); From fabc84fc8a973b530d58aff1038ac73ad3082ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Slanina?= <itzexpoe...@gmail.com> Date: Sun, 24 Aug 2025 15:56:58 +0200 Subject: [PATCH 5/7] Fix docs after rename --- clang/docs/ClangFormatStyleOptions.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 537d81747a834..76f5f3f583d6b 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2093,9 +2093,9 @@ the configuration (without a prefix: ``Auto``). **AllowShortNamespacesOnASingleLine** (``Boolean``) :versionbadge:`clang-format 20` :ref:`¶ <AllowShortNamespacesOnASingleLine>` If ``true``, ``namespace a { class b; }`` can be put on a single line. -.. _AllowShortRecordsOnASingleLine: +.. _AllowShortRecordOnASingleLine: -**AllowShortRecordsOnASingleLine** (``ShortRecordStyle``) :ref:`¶ <AllowShortRecordsOnASingleLine>` +**AllowShortRecordOnASingleLine** (``ShortRecordStyle``) :ref:`¶ <AllowShortRecordOnASingleLine>` Dependent on the value, ``struct bar { int i; }`` can be put on a single line. @@ -2115,7 +2115,7 @@ the configuration (without a prefix: ``Auto``). int i; }; - * ``SRS_All`` (in configuration: ``All``) + * ``SRS_Always`` (in configuration: ``Always``) Merge all records that fit on a single line. .. code-block:: c++ From 334ebf9c9f58f5c40d89f73959e89fe1f300fbf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Slanina?= <itzexpoe...@gmail.com> Date: Mon, 25 Aug 2025 00:38:53 +0200 Subject: [PATCH 6/7] Fixup documentation --- clang/docs/ClangFormatStyleOptions.rst | 2 +- clang/include/clang/Format/Format.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index cde28a2608a34..0694d2ca33df9 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2098,7 +2098,7 @@ the configuration (without a prefix: ``Auto``). .. _AllowShortRecordOnASingleLine: -**AllowShortRecordOnASingleLine** (``ShortRecordStyle``) :ref:`¶ <AllowShortRecordOnASingleLine>` +**AllowShortRecordOnASingleLine** (``ShortRecordStyle``) :versionbadge:`clang-format 22` :ref:`¶ <AllowShortRecordOnASingleLine>` Dependent on the value, ``struct bar { int i; }`` can be put on a single line. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 4e629340947f6..af04f6d88455a 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -992,8 +992,8 @@ struct FormatStyle { /// \version 20 bool AllowShortNamespacesOnASingleLine; - /// Different styles for merging short records - /// (``class``,``struct``,``union``). + /// Different styles for merging short records (``class``,``struct``, and + /// ``union``). enum ShortRecordStyle : int8_t { /// Never merge records into a single line. SRS_Never, @@ -1016,6 +1016,7 @@ struct FormatStyle { /// Dependent on the value, ``struct bar { int i; }`` can be put on a single /// line. + /// \version 22 ShortRecordStyle AllowShortRecordOnASingleLine; /// Different ways to break after the function definition return type. From 4e136a4442e589751851d9dc89ccd6c6ad6a77b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Slanina?= <itzexpoe...@gmail.com> Date: Tue, 26 Aug 2025 23:54:53 +0200 Subject: [PATCH 7/7] Fix SplitEmptyRecord handling, docs --- clang/docs/ClangFormatStyleOptions.rst | 2 +- clang/include/clang/Format/Format.h | 2 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 2 +- clang/lib/Format/UnwrappedLineParser.cpp | 3 ++- clang/unittests/Format/FormatTest.cpp | 25 ++++++++++++--------- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 0694d2ca33df9..808c447e37767 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2099,7 +2099,7 @@ the configuration (without a prefix: ``Auto``). .. _AllowShortRecordOnASingleLine: **AllowShortRecordOnASingleLine** (``ShortRecordStyle``) :versionbadge:`clang-format 22` :ref:`¶ <AllowShortRecordOnASingleLine>` - Dependent on the value, ``struct bar { int i; }`` can be put on a single + Dependent on the value, ``struct bar { int i; };`` can be put on a single line. Possible values: diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index af04f6d88455a..12fc8a98da17c 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1014,7 +1014,7 @@ struct FormatStyle { SRS_Always }; - /// Dependent on the value, ``struct bar { int i; }`` can be put on a single + /// Dependent on the value, ``struct bar { int i; };`` can be put on a single /// line. /// \version 22 ShortRecordStyle AllowShortRecordOnASingleLine; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 07c2ec6e1ef19..e8118d54628bd 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -462,7 +462,7 @@ class LineJoiner { case FormatStyle::SRS_Never: return false; } - }(); + }() && !Style.BraceWrapping.SplitEmptyRecord; // Don't merge an empty template class or struct if SplitEmptyRecords // is defined. diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 359aaed1bb049..f9c87d618b98e 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -961,7 +961,8 @@ static bool ShouldBreakBeforeBrace(const FormatStyle &Style, bool IsEmptyBlock = NextToken.is(tok::r_brace); bool WrapRecordAllowed = !(IsEmptyBlock && - Style.AllowShortRecordOnASingleLine != FormatStyle::SRS_Never); + Style.AllowShortRecordOnASingleLine != FormatStyle::SRS_Never) || + Style.BraceWrapping.SplitEmptyRecord; switch (Kind) { case tok::kw_namespace: diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 203a3375bbc1d..e0f20754edad2 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15668,6 +15668,17 @@ TEST_F(FormatTest, AllowShortRecordsOnASingleLine) { Style); verifyFormat("union foo\n{};", Style); + Style.AllowShortRecordOnASingleLine = FormatStyle::SRS_Always; + + verifyFormat("class foo { void bar(); };", Style); + verifyFormat("class foo {};", Style); + + verifyFormat("struct foo { int bar; };", Style); + verifyFormat("struct foo {};", Style); + + verifyFormat("union foo { int bar; };", Style); + verifyFormat("union foo {};", Style); + Style.AllowShortRecordOnASingleLine = FormatStyle::SRS_Empty; verifyFormat("class foo\n{\n" @@ -15688,16 +15699,10 @@ TEST_F(FormatTest, AllowShortRecordsOnASingleLine) { Style); verifyFormat("union foo {};", Style); - Style.AllowShortRecordOnASingleLine = FormatStyle::SRS_Always; - - verifyFormat("class foo { void bar(); };", Style); - verifyFormat("class foo {};", Style); - - verifyFormat("struct foo { int bar; };", Style); - verifyFormat("struct foo {};", Style); - - verifyFormat("union foo { int bar; };", Style); - verifyFormat("union foo {};", Style); + Style.BraceWrapping.SplitEmptyRecord = true; + verifyFormat("class foo\n{\n}", Style); + verifyFormat("struct foo\n{\n}", Style); + verifyFormat("union foo\n{\n}", Style); } TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits