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 <yldhome...@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 <yldhome...@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));
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to