[clang] [clang-format] allow short function body on a single line (PR #151428)
Lidong Yan via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 22 08:36:32 PDT 2025
https://github.com/brandb97 updated https://github.com/llvm/llvm-project/pull/151428
>From 04cd330ab306e6718cf96ff3d29b446d35424a5e Mon Sep 17 00:00:00 2001
From: Lidong Yan <yldhome2d2 at gmail.com>
Date: Fri, 22 Aug 2025 23:31:28 +0800
Subject: [PATCH] [clang-format] allow short function bodies on a single line
When set AllowShortBlocksOnASingleLine as Empty or Always and we
can't put the whole function on a single line, clang-format doesn't
tries to put the function body on a seperate line from function
signature. Add tryMergeLines to put function bodies on a single line
if possible.
Signed-off-by: Lidong Yan <yldhome2d2 at gmail.com>
---
clang/lib/Format/UnwrappedLineFormatter.cpp | 51 ++++++++++++++++-----
clang/lib/Format/UnwrappedLineParser.cpp | 6 ++-
clang/unittests/Format/FormatTest.cpp | 32 +++++++++++++
3 files changed, 76 insertions(+), 13 deletions(-)
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index c938ff3965f9e..37c04874c98f5 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -242,19 +242,24 @@ class LineJoiner {
if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
return 0;
- unsigned Limit =
+ const unsigned LimitStripIndent =
Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
// If we already exceed the column limit, we set 'Limit' to 0. The different
// tryMerge..() functions can then decide whether to still do merging.
- Limit = TheLine->Last->TotalLength > Limit
- ? 0
- : Limit - TheLine->Last->TotalLength;
+ unsigned Limit = TheLine->Last->TotalLength > LimitStripIndent
+ ? 0
+ : LimitStripIndent - TheLine->Last->TotalLength;
if (TheLine->Last->is(TT_FunctionLBrace) &&
- TheLine->First == TheLine->Last &&
- !Style.BraceWrapping.SplitEmptyFunction &&
- NextLine.First->is(tok::r_brace)) {
- return tryMergeSimpleBlock(I, E, Limit);
+ TheLine->First == TheLine->Last) {
+ if (!Style.BraceWrapping.SplitEmptyFunction &&
+ NextLine.First->is(tok::r_brace)) {
+ return tryMergeSimpleBlock(I, E, Limit);
+ }
+ if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always &&
+ I + 2 != E && I[2]->First->is(tok::r_brace)) {
+ return tryMergeSimpleBlock(I, E, Limit);
+ }
}
const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] : nullptr;
@@ -510,7 +515,8 @@ class LineJoiner {
// Try to merge a function block with left brace wrapped.
if (NextLine.First->is(TT_FunctionLBrace) &&
- Style.BraceWrapping.AfterFunction) {
+ (Style.BraceWrapping.AfterFunction ||
+ Style.AllowShortBlocksOnASingleLine > FormatStyle::SBS_Never)) {
if (NextLine.Last->is(TT_LineComment))
return 0;
@@ -520,17 +526,38 @@ class LineJoiner {
Limit -= 2;
unsigned MergedLines = 0;
+ const bool NextShortBlock = NextLine.First == NextLine.Last &&
+ I + 3 != E && I[3]->First->is(tok::r_brace);
+ const bool NextEmptyBlock = NextLine.First == NextLine.Last &&
+ I + 2 != E && I[2]->First->is(tok::r_brace);
if (MergeShortFunctions ||
(Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
- NextLine.First == NextLine.Last && I + 2 != E &&
- I[2]->First->is(tok::r_brace))) {
+ NextEmptyBlock) ||
+ (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All &&
+ NextShortBlock)) {
MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
// If we managed to merge the block, count the function header, which is
// on a separate line.
if (MergedLines > 0)
++MergedLines;
}
- return MergedLines;
+ // Return early if we shouldn't merge left brace back to function header.
+ if (Style.BraceWrapping.AfterFunction || MergedLines)
+ return MergedLines;
+
+ // If we can't put function body on a single line, we should merge left
+ // brace back to function header.
+ const unsigned NextLineLimit =
+ NextLine.Last->TotalLength > LimitStripIndent
+ ? 0
+ : LimitStripIndent - NextLine.Last->TotalLength;
+ if ((NextShortBlock &&
+ Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always) ||
+ (NextEmptyBlock &&
+ Style.AllowShortBlocksOnASingleLine > FormatStyle::SBS_Never)) {
+ MergedLines = tryMergeSimpleBlock(I + 1, E, NextLineLimit);
+ }
+ return MergedLines ? 0 : 1;
}
auto IsElseLine = [&TheLine]() -> bool {
const FormatToken *First = TheLine->First;
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 91b8fdc8a3c38..e3884c472a133 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1919,7 +1919,11 @@ void UnwrappedLineParser::parseStructuralElement(
FormatStyle::BWACS_Always) {
addUnwrappedLine();
}
- } else if (Style.BraceWrapping.AfterFunction) {
+ } else if (Style.BraceWrapping.AfterFunction ||
+ // Wrap left brace here in case that we want
+ // to merge function body on a single line.
+ Style.AllowShortBlocksOnASingleLine >
+ FormatStyle::SBS_Never) {
addUnwrappedLine();
}
if (!Previous || Previous->isNot(TT_TypeDeclarationParen))
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 83c664c3b81f3..fef7607c30587 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -14953,11 +14953,25 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
FormatStyle DoNotMerge = getLLVMStyle();
DoNotMerge.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ FormatStyle MergeBodyAlways = getLLVMStyle();
+ MergeBodyAlways.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ MergeBodyAlways.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always;
+
+ FormatStyle MergeBodyIfPossible = getLLVMStyleWithColumns(20);
+ MergeBodyIfPossible.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ MergeBodyIfPossible.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always;
+
verifyFormat("void f() { return 42; }");
verifyFormat("void f() {\n"
" return 42;\n"
"}",
DoNotMerge);
+ verifyFormat("void f()\n"
+ "{ return 42; }",
+ MergeBodyAlways);
+ verifyFormat("void long_function_name()\n"
+ "{ return 42; }",
+ MergeBodyIfPossible);
verifyFormat("void f() {\n"
" // Comment\n"
"}");
@@ -14982,6 +14996,24 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
"} // comment",
getLLVMStyleWithColumns(15));
+ verifyFormat("void f()\n"
+ "{} // comment",
+ MergeBodyAlways);
+ verifyFormat("void f()\n"
+ "{ int a; } // comment",
+ MergeBodyAlways);
+ verifyFormat("void long_function_name()\n"
+ "{} // comment",
+ MergeBodyIfPossible);
+ verifyFormat("void f() {\n"
+ " int a;\n"
+ "} // comment",
+ MergeBodyIfPossible);
+ MergeBodyIfPossible.ColumnLimit = 21;
+ verifyFormat("void f()\n"
+ "{ int a; } // comment",
+ MergeBodyIfPossible);
+
verifyFormat("void f() { return 42; }", getLLVMStyleWithColumns(23));
verifyFormat("void f() {\n return 42;\n}", getLLVMStyleWithColumns(22));
More information about the cfe-commits
mailing list