https://github.com/irymarchyk updated 
https://github.com/llvm/llvm-project/pull/134337

>From df25a8bbfd827085265c51a44bedbf38deebbab4 Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Sat, 29 Mar 2025 13:54:32 -0700
Subject: [PATCH 1/8] [clang-format]: Add `Custom` to `ShortFunctionStyle`; add
 new AllowShortFunctionsOnASingleLineOptions for granular setup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The current clang-format configuration option AllowShortFunctionsOnASingleLine 
uses a single enum (ShortFunctionStyle) to control when short function 
definitions can be merged onto a single line. This enum provides predefined 
combinations of conditions (e.g., None, Empty only, Inline only, Inline 
including Empty, All).

This approach has limitations:

1. **Lack of Granularity:** Users cannot specify arbitrary combinations of 
conditions. For example, a user might want to allow merging for both empty 
functions and short top-level functions, but not for short functions defined 
within classes. This is not possible with the current enum options except by 
choosing All, which might merge more than desired.

2. **Inflexibility:** Adding new conditions for merging (e.g., distinguishing 
between member functions and constructors, handling lambdas specifically) would 
require adding many new combined enum values, leading to a combinatorial 
explosion and making the configuration complex.

3. **Implicit Behavior:** Some options imply others (e.g., Inline implies 
Empty), which might not always be intuitive or desired.

The goal is to replace this single-choice enum with a more flexible mechanism 
allowing users to specify a set of conditions that must be met for a short 
function to be merged onto a single line.

**Proposed Solution**

1. Introduce a new configuration option: AllowShortFunctionsOnSingleLineOptions.

2. This option will accept a list of strings, where each string represents a 
specific condition allowing merging.

3. **Backward Compatibility:**

    - If AllowShortFunctionsOnSingleLineOptions is present in the 
configuration, it takes precedence.

    - If AllowShortFunctionsOnSingleLineOptions is not present, but the old 
AllowShortFunctionsOnASingleLine is present, the old option should be parsed 
and mapped to the corresponding new semantics for compatibility.
---
 clang/docs/ClangFormatStyleOptions.rst      |  64 +++++++++++
 clang/include/clang/Format/Format.h         |  70 ++++++++++++
 clang/lib/Format/Format.cpp                 |  52 +++++++++
 clang/lib/Format/TokenAnnotator.cpp         |   7 +-
 clang/lib/Format/UnwrappedLineFormatter.cpp |   9 +-
 clang/unittests/Format/ConfigParseTest.cpp  |   6 ++
 clang/unittests/Format/FormatTest.cpp       | 111 ++++++++++++++++++++
 7 files changed, 310 insertions(+), 9 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 9ecac68ae72bf..167701cf6585d 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1959,6 +1959,70 @@ the configuration (without a prefix: ``Auto``).
       };
       void f() { bar(); }
 
+  * ``SFS_Custom`` (in configuration: ``Custom``)
+    Configure merge behavior using AllowShortFunctionsOnASingleLineOptions
+
+
+
+.. _AllowShortFunctionsOnASingleLineOptions:
+
+**AllowShortFunctionsOnASingleLineOptions** (``ShortFunctionMergeFlags``) 
:versionbadge:`clang-format 21` :ref:`¶ 
<AllowShortFunctionsOnASingleLineOptions>`
+  Precise control over merging short functions
+
+  If ``AllowShortFunctionsOnASingleLine`` is set to ``Custom``, use this to
+  specify behavior in different situations.
+
+  .. code-block:: yaml
+
+    # Example of usage:
+    AllowShortFunctionsOnASingleLine: Custom
+    AllowShortFunctionsOnASingleLineOptions:
+      Empty: false
+      Inline: true
+      All: false
+
+  Nested configuration flags:
+
+  Precise control over merging short functions
+
+  .. code-block:: c++
+
+    # Should be declared this way:
+    AllowShortFunctionsOnASingleLine: Custom
+    AllowShortFunctionsOnASingleLineOptions:
+      Empty: false
+      Inline: true
+      All: false
+
+  * ``bool Empty`` Only merge empty functions.
+
+    .. code-block:: c++
+
+      void f() {}
+      void f2() {
+        bar2();
+      }
+
+  * ``bool Inline`` Only merge functions defined inside a class.
+
+    .. code-block:: c++
+
+      class Foo {
+        void f() { foo(); }
+      };
+      void f() {
+        foo();
+      }
+      void f() {}
+
+  * ``bool All`` Merge all functions fitting on a single line.
+
+    .. code-block:: c++
+
+      class Foo {
+        void f() { foo(); }
+      };
+      void f() { bar(); }
 
 
 .. _AllowShortIfStatementsOnASingleLine:
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index fec47a248abb4..96b1ecab04e63 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -871,6 +871,8 @@ struct FormatStyle {
     ///   void f() { bar(); }
     /// \endcode
     SFS_All,
+    /// Configure merge behavior using AllowShortFunctionsOnASingleLineOptions
+    SFS_Custom,
   };
 
   /// Dependent on the value, ``int f() { return 0; }`` can be put on a
@@ -878,6 +880,72 @@ struct FormatStyle {
   /// \version 3.5
   ShortFunctionStyle AllowShortFunctionsOnASingleLine;
 
+  /// Precise control over merging short functions
+  /// \code
+  ///   # Should be declared this way:
+  ///   AllowShortFunctionsOnASingleLine: Custom
+  ///   AllowShortFunctionsOnASingleLineOptions:
+  ///     Empty: false
+  ///     Inline: true
+  ///     All: false
+  /// \endcode
+  struct ShortFunctionMergeFlags {
+    /// Only merge empty functions.
+    /// \code
+    ///   void f() {}
+    ///   void f2() {
+    ///     bar2();
+    ///   }
+    /// \endcode
+    bool Empty;
+    /// Only merge functions defined inside a class.
+    /// \code
+    ///   class Foo {
+    ///     void f() { foo(); }
+    ///   };
+    ///   void f() {
+    ///     foo();
+    ///   }
+    ///   void f() {}
+    /// \endcode
+    bool Inline;
+    /// Merge all functions fitting on a single line.
+    /// \code
+    ///   class Foo {
+    ///     void f() { foo(); }
+    ///   };
+    ///   void f() { bar(); }
+    /// \endcode
+    bool All;
+
+    ShortFunctionMergeFlags() : Empty(false), Inline(false), All(false) {}
+
+    ShortFunctionMergeFlags(bool Empty, bool Inline, bool All)
+        : Empty(Empty), Inline(Inline), All(All) {}
+
+    bool operator==(const ShortFunctionMergeFlags &R) const {
+      return Empty == R.Empty && Inline == R.Inline && All == R.All;
+    }
+    bool operator!=(const ShortFunctionMergeFlags &R) const {
+      return !(*this == R);
+    }
+  };
+
+  /// Precise control over merging short functions
+  ///
+  /// If ``AllowShortFunctionsOnASingleLine`` is set to ``Custom``, use this to
+  /// specify behavior in different situations.
+  /// \code{.yaml}
+  ///   # Example of usage:
+  ///   AllowShortFunctionsOnASingleLine: Custom
+  ///   AllowShortFunctionsOnASingleLineOptions:
+  ///     Empty: false
+  ///     Inline: true
+  ///     All: false
+  /// \endcode
+  /// \version 21
+  ShortFunctionMergeFlags AllowShortFunctionsOnASingleLineOptions;
+
   /// Different styles for handling short if statements.
   enum ShortIfStyle : int8_t {
     /// Never put short ifs on the same line.
@@ -5281,6 +5349,8 @@ struct FormatStyle {
            AllowShortEnumsOnASingleLine == R.AllowShortEnumsOnASingleLine &&
            AllowShortFunctionsOnASingleLine ==
                R.AllowShortFunctionsOnASingleLine &&
+           AllowShortFunctionsOnASingleLineOptions ==
+               R.AllowShortFunctionsOnASingleLineOptions &&
            AllowShortIfStatementsOnASingleLine ==
                R.AllowShortIfStatementsOnASingleLine &&
            AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine 
&&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 28aea86139e0d..21f896c6e9cf0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -622,6 +622,15 @@ template <> struct 
ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
     IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
     IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
     IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
+    IO.enumCase(Value, "Custom", FormatStyle::SFS_Custom);
+  }
+};
+
+template <> struct MappingTraits<FormatStyle::ShortFunctionMergeFlags> {
+  static void mapping(IO &IO, FormatStyle::ShortFunctionMergeFlags &Value) {
+    IO.mapOptional("Empty", Value.Empty);
+    IO.mapOptional("Inline", Value.Inline);
+    IO.mapOptional("All", Value.All);
   }
 };
 
@@ -982,6 +991,8 @@ template <> struct MappingTraits<FormatStyle> {
                    Style.AllowShortEnumsOnASingleLine);
     IO.mapOptional("AllowShortFunctionsOnASingleLine",
                    Style.AllowShortFunctionsOnASingleLine);
+    IO.mapOptional("AllowShortFunctionsOnASingleLineOptions",
+                   Style.AllowShortFunctionsOnASingleLineOptions);
     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
                    Style.AllowShortIfStatementsOnASingleLine);
     IO.mapOptional("AllowShortLambdasOnASingleLine",
@@ -1472,6 +1483,30 @@ static void expandPresetsSpacesInParens(FormatStyle 
&Expanded) {
   Expanded.SpacesInParensOptions = {};
 }
 
+static void expandPresetsShortFunctionsOnSingleLine(FormatStyle &Expanded) {
+  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Custom)
+    return;
+  // Reset all flags
+  Expanded.AllowShortFunctionsOnASingleLineOptions = {};
+
+  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None)
+    return;
+
+  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||
+      Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline) {
+    Expanded.AllowShortFunctionsOnASingleLineOptions.Empty = true;
+  }
+
+  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline ||
+      Expanded.AllowShortFunctionsOnASingleLine ==
+          FormatStyle::SFS_InlineOnly) {
+    Expanded.AllowShortFunctionsOnASingleLineOptions.Inline = true;
+  }
+
+  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
+    Expanded.AllowShortFunctionsOnASingleLineOptions.All = true;
+}
+
 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   FormatStyle LLVMStyle;
   LLVMStyle.AccessModifierOffset = -2;
@@ -1501,6 +1536,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
   LLVMStyle.AllowShortEnumsOnASingleLine = true;
   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  LLVMStyle.AllowShortFunctionsOnASingleLineOptions = {};
+  LLVMStyle.AllowShortFunctionsOnASingleLineOptions.All = true;
   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
   LLVMStyle.AllowShortLoopsOnASingleLine = false;
@@ -1788,6 +1825,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
     GoogleStyle.AlignTrailingComments = {};
     GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
@@ -1798,6 +1837,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
     // TODO: still under discussion whether to switch to SLS_All.
     GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
@@ -1815,6 +1856,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
     GoogleStyle.SpacesInContainerLiterals = false;
   } else if (Language == FormatStyle::LK_Proto) {
     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
     // This affects protocol buffer options specifications and text protos.
     // Text protos are currently mostly formatted inside C++ raw string 
literals
@@ -1834,6 +1877,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
         tooling::IncludeStyle::IBS_Preserve;
   } else if (Language == FormatStyle::LK_CSharp) {
     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
+    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     GoogleStyle.BreakStringLiterals = false;
     GoogleStyle.ColumnLimit = 100;
@@ -1893,6 +1938,8 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind 
Language) {
   } else {
     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
     ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+    ChromiumStyle.AllowShortFunctionsOnASingleLineOptions = {};
+    ChromiumStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true;
     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
     ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
@@ -1907,6 +1954,8 @@ FormatStyle getMozillaStyle() {
   FormatStyle MozillaStyle = getLLVMStyle();
   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
   MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  MozillaStyle.AllowShortFunctionsOnASingleLineOptions = {};
+  MozillaStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true;
   MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
       FormatStyle::DRTBS_TopLevel;
   MozillaStyle.BinPackArguments = false;
@@ -1989,6 +2038,7 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind 
Language) {
   Style.PenaltyReturnTypeOnItsOwnLine = 1000;
   Style.AllowShortEnumsOnASingleLine = false;
   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLineOptions = {};
   Style.AllowShortCaseLabelsOnASingleLine = false;
   Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
   Style.AllowShortLoopsOnASingleLine = false;
@@ -2160,6 +2210,7 @@ std::string configurationAsText(const FormatStyle &Style) 
{
   expandPresetsBraceWrapping(NonConstStyle);
   expandPresetsSpaceBeforeParens(NonConstStyle);
   expandPresetsSpacesInParens(NonConstStyle);
+  expandPresetsShortFunctionsOnSingleLine(NonConstStyle);
   Output << NonConstStyle;
 
   return Stream.str();
@@ -3722,6 +3773,7 @@ reformat(const FormatStyle &Style, StringRef Code,
   expandPresetsBraceWrapping(Expanded);
   expandPresetsSpaceBeforeParens(Expanded);
   expandPresetsSpacesInParens(Expanded);
+  expandPresetsShortFunctionsOnSingleLine(Expanded);
   Expanded.InsertBraces = false;
   Expanded.RemoveBracesLLVM = false;
   Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index d87b3a6088bd8..c058354918140 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5687,11 +5687,10 @@ bool TokenAnnotator::mustBreakBefore(const 
AnnotatedLine &Line,
     if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
         !Left.Children.empty()) {
       // Support AllowShortFunctionsOnASingleLine for JavaScript.
-      return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
-             Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty 
||
+      return (!Style.AllowShortFunctionsOnASingleLineOptions.Inline &&
+              !Style.AllowShortFunctionsOnASingleLineOptions.All) ||
              (Left.NestingLevel == 0 && Line.Level == 0 &&
-              Style.AllowShortFunctionsOnASingleLine &
-                  FormatStyle::SFS_InlineOnly);
+              Style.AllowShortFunctionsOnASingleLineOptions.Inline);
     }
   } else if (Style.Language == FormatStyle::LK_Java) {
     if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight &&
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 000a5105ca407..5be28e895aab6 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -293,15 +293,14 @@ class LineJoiner {
 
     auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine,
                                       TheLine]() {
-      if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
+      if (Style.AllowShortFunctionsOnASingleLineOptions.All)
         return true;
-      if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
+      if (Style.AllowShortFunctionsOnASingleLineOptions.Empty &&
           NextLine.First->is(tok::r_brace)) {
         return true;
       }
 
-      if (Style.AllowShortFunctionsOnASingleLine &
-          FormatStyle::SFS_InlineOnly) {
+      if (Style.AllowShortFunctionsOnASingleLineOptions.Inline) {
         // Just checking TheLine->Level != 0 is not enough, because it
         // provokes treating functions inside indented namespaces as short.
         if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
@@ -551,7 +550,7 @@ class LineJoiner {
 
       unsigned MergedLines = 0;
       if (MergeShortFunctions ||
-          (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
+          (Style.AllowShortFunctionsOnASingleLineOptions.Empty &&
            NextLine.First == NextLine.Last && I + 2 != E &&
            I[2]->First->is(tok::r_brace))) {
         MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index 287191d04d885..54e484fcbe4cd 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -256,6 +256,9 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements);
   CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses);
   CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, Other);
+  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Empty);
+  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Inline);
+  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, All);
 }
 
 #undef CHECK_PARSE_BOOL
@@ -620,6 +623,9 @@ TEST(ConfigParseTest, ParsesConfiguration) {
               AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Empty);
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: All",
               AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All);
+  CHECK_PARSE("AllowShortFunctionsOnASingleLine: Custom",
+              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Custom);
+
   // For backward compatibility:
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: false",
               AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None);
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 0b90bd360b758..868d4e375b953 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -15120,6 +15120,117 @@ TEST_F(FormatTest, 
PullInlineFunctionDefinitionsIntoSingleLine) {
                MergeInlineOnly);
 }
 
+TEST_F(FormatTest, CustomShortFunctionOptions) {
+  FormatStyle CustomEmpty = getLLVMStyle();
+  CustomEmpty.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
+  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Empty = true;
+  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Inline = false;
+  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.All = false;
+
+  // Empty functions should be on a single line
+  verifyFormat("int f() {}", CustomEmpty);
+  verifyFormat("class C {\n"
+               "  int f() {}\n"
+               "};",
+               CustomEmpty);
+
+  // Non-empty functions should be multi-line
+  verifyFormat("int f() {\n"
+               "  return 42;\n"
+               "}",
+               CustomEmpty);
+  verifyFormat("class C {\n"
+               "  int f() {\n"
+               "    return 42;\n"
+               "  }\n"
+               "};",
+               CustomEmpty);
+
+  // Test with AfterFunction = true
+  CustomEmpty.BreakBeforeBraces = FormatStyle::BS_Custom;
+  CustomEmpty.BraceWrapping.AfterFunction = true;
+  verifyFormat("int f() {}", CustomEmpty);
+  verifyFormat("int g()\n"
+               "{\n"
+               "  return 42;\n"
+               "}",
+               CustomEmpty);
+
+  // Test with Inline = true, All = false
+  FormatStyle CustomInline = getLLVMStyle();
+  CustomInline.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
+  CustomInline.AllowShortFunctionsOnASingleLineOptions.Empty = false;
+  CustomInline.AllowShortFunctionsOnASingleLineOptions.Inline = true;
+  CustomInline.AllowShortFunctionsOnASingleLineOptions.All = false;
+
+  verifyFormat("class C {\n"
+               "  int f() {}\n"
+               "};",
+               CustomInline);
+
+  // Non-empty inline functions should be single-line
+  verifyFormat("class C {\n"
+               "  int f() { return 42; }\n"
+               "};",
+               CustomInline);
+
+  // Non-inline functions should be multi-line
+  verifyFormat("int f() {\n"
+               "  return 42;\n"
+               "}",
+               CustomInline);
+  verifyFormat("int g() {\n"
+               "}",
+               CustomInline);
+
+  // Test with All = true
+  FormatStyle CustomAll = getLLVMStyle();
+  CustomAll.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
+  CustomAll.AllowShortFunctionsOnASingleLineOptions.Empty = false;
+  CustomAll.AllowShortFunctionsOnASingleLineOptions.Inline = false;
+  CustomAll.AllowShortFunctionsOnASingleLineOptions.All = true;
+
+  // All functions should be on a single line if they fit
+  verifyFormat("int f() { return 42; }", CustomAll);
+  verifyFormat("int g() { return f() + h(); }", CustomAll);
+  verifyFormat("class C {\n"
+               "  int f() { return 42; }\n"
+               "};",
+               CustomAll);
+
+  verifyFormat("int f() {}", CustomAll);
+  verifyFormat("class C {\n"
+               "  int f() {}\n"
+               "};",
+               CustomAll);
+
+  // Test various combinations
+  FormatStyle CustomMixed = getLLVMStyle();
+  CustomMixed.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
+  CustomMixed.AllowShortFunctionsOnASingleLineOptions.Empty = true;
+  CustomMixed.AllowShortFunctionsOnASingleLineOptions.Inline = true;
+  CustomMixed.AllowShortFunctionsOnASingleLineOptions.All = false;
+
+  // Empty functions should be on a single line
+  verifyFormat("int f() {}", CustomMixed);
+  verifyFormat("class C {\n"
+               "  int f() {}\n"
+               "};",
+               CustomMixed);
+
+  // Inline non-empty functions should be on a single line
+  verifyFormat("class C {\n"
+               "  int f() { return 42; }\n"
+               "};",
+               CustomMixed);
+
+  // Non-inline non-empty functions should be multi-line
+  verifyFormat("int f() {\n"
+               "  return 42;\n"
+               "}",
+               CustomMixed);
+}
+
 TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) {
   FormatStyle MergeInlineOnly = getLLVMStyle();
   MergeInlineOnly.AllowShortFunctionsOnASingleLine =

>From e9e4e92afca915bfeba3fac0227930a99a5daa34 Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Fri, 4 Apr 2025 18:20:28 -0700
Subject: [PATCH 2/8] PR-134337: fixed PR comments

---
 clang/docs/ClangFormatStyleOptions.rst      | 11 +++++++----
 clang/include/clang/Format/Format.h         | 17 ++++++++++-------
 clang/lib/Format/Format.cpp                 |  6 +++---
 clang/lib/Format/TokenAnnotator.cpp         |  2 +-
 clang/lib/Format/UnwrappedLineFormatter.cpp |  2 +-
 clang/unittests/Format/ConfigParseTest.cpp  |  2 +-
 clang/unittests/Format/FormatTest.cpp       | 11 +++++++----
 7 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 167701cf6585d..c0529dd138f59 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1994,7 +1994,7 @@ the configuration (without a prefix: ``Auto``).
       Inline: true
       All: false
 
-  * ``bool Empty`` Only merge empty functions.
+  * ``bool Empty`` Merge top-level empty functions.
 
     .. code-block:: c++
 
@@ -2002,20 +2002,23 @@ the configuration (without a prefix: ``Auto``).
       void f2() {
         bar2();
       }
+      void f3() { /* comment */ }
 
-  * ``bool Inline`` Only merge functions defined inside a class.
+  * ``bool Inline`` Merge functions defined inside a class.
 
     .. code-block:: c++
 
       class Foo {
         void f() { foo(); }
+        void g() {}
       };
       void f() {
         foo();
       }
-      void f() {}
+      void f() {
+      }
 
-  * ``bool All`` Merge all functions fitting on a single line.
+  * ``bool Other`` Merge all functions fitting on a single line.
 
     .. code-block:: c++
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 96b1ecab04e63..971b978adc2c7 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -890,23 +890,26 @@ struct FormatStyle {
   ///     All: false
   /// \endcode
   struct ShortFunctionMergeFlags {
-    /// Only merge empty functions.
+    /// Merge top-level empty functions.
     /// \code
     ///   void f() {}
     ///   void f2() {
     ///     bar2();
     ///   }
+    ///   void f3() { /* comment */ }
     /// \endcode
     bool Empty;
-    /// Only merge functions defined inside a class.
+    /// Merge functions defined inside a class.
     /// \code
     ///   class Foo {
     ///     void f() { foo(); }
+    ///     void g() {}
     ///   };
     ///   void f() {
     ///     foo();
     ///   }
-    ///   void f() {}
+    ///   void f() {
+    ///   }
     /// \endcode
     bool Inline;
     /// Merge all functions fitting on a single line.
@@ -916,15 +919,15 @@ struct FormatStyle {
     ///   };
     ///   void f() { bar(); }
     /// \endcode
-    bool All;
+    bool Other;
 
-    ShortFunctionMergeFlags() : Empty(false), Inline(false), All(false) {}
+    ShortFunctionMergeFlags() : Empty(false), Inline(false), Other(false) {}
 
     ShortFunctionMergeFlags(bool Empty, bool Inline, bool All)
-        : Empty(Empty), Inline(Inline), All(All) {}
+        : Empty(Empty), Inline(Inline), Other(All) {}
 
     bool operator==(const ShortFunctionMergeFlags &R) const {
-      return Empty == R.Empty && Inline == R.Inline && All == R.All;
+      return Empty == R.Empty && Inline == R.Inline && Other == R.Other;
     }
     bool operator!=(const ShortFunctionMergeFlags &R) const {
       return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 21f896c6e9cf0..aff38f56f05e3 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -630,7 +630,7 @@ template <> struct 
MappingTraits<FormatStyle::ShortFunctionMergeFlags> {
   static void mapping(IO &IO, FormatStyle::ShortFunctionMergeFlags &Value) {
     IO.mapOptional("Empty", Value.Empty);
     IO.mapOptional("Inline", Value.Inline);
-    IO.mapOptional("All", Value.All);
+    IO.mapOptional("Other", Value.Other);
   }
 };
 
@@ -1504,7 +1504,7 @@ static void 
expandPresetsShortFunctionsOnSingleLine(FormatStyle &Expanded) {
   }
 
   if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
-    Expanded.AllowShortFunctionsOnASingleLineOptions.All = true;
+    Expanded.AllowShortFunctionsOnASingleLineOptions.Other = true;
 }
 
 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
@@ -1537,7 +1537,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.AllowShortEnumsOnASingleLine = true;
   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
   LLVMStyle.AllowShortFunctionsOnASingleLineOptions = {};
-  LLVMStyle.AllowShortFunctionsOnASingleLineOptions.All = true;
+  LLVMStyle.AllowShortFunctionsOnASingleLineOptions.Other = true;
   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
   LLVMStyle.AllowShortLoopsOnASingleLine = false;
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index c058354918140..cdf46f65e8b52 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5688,7 +5688,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine 
&Line,
         !Left.Children.empty()) {
       // Support AllowShortFunctionsOnASingleLine for JavaScript.
       return (!Style.AllowShortFunctionsOnASingleLineOptions.Inline &&
-              !Style.AllowShortFunctionsOnASingleLineOptions.All) ||
+              !Style.AllowShortFunctionsOnASingleLineOptions.Other) ||
              (Left.NestingLevel == 0 && Line.Level == 0 &&
               Style.AllowShortFunctionsOnASingleLineOptions.Inline);
     }
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 5be28e895aab6..6f30bbc8a9e5f 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -293,7 +293,7 @@ class LineJoiner {
 
     auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine,
                                       TheLine]() {
-      if (Style.AllowShortFunctionsOnASingleLineOptions.All)
+      if (Style.AllowShortFunctionsOnASingleLineOptions.Other)
         return true;
       if (Style.AllowShortFunctionsOnASingleLineOptions.Empty &&
           NextLine.First->is(tok::r_brace)) {
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index 54e484fcbe4cd..16ab406c9cade 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -258,7 +258,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, Other);
   CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Empty);
   CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Inline);
-  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, All);
+  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Other);
 }
 
 #undef CHECK_PARSE_BOOL
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 868d4e375b953..79ee1230eb6a7 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -15125,7 +15125,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
   CustomEmpty.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
   CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Empty = true;
   CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Inline = false;
-  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.All = false;
+  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Other = false;
 
   // Empty functions should be on a single line
   verifyFormat("int f() {}", CustomEmpty);
@@ -15146,6 +15146,9 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
                "};",
                CustomEmpty);
 
+  // test with comment
+  verifyFormat("void f3() { /* comment */ }", CustomEmpty);
+
   // Test with AfterFunction = true
   CustomEmpty.BreakBeforeBraces = FormatStyle::BS_Custom;
   CustomEmpty.BraceWrapping.AfterFunction = true;
@@ -15161,7 +15164,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
   CustomInline.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
   CustomInline.AllowShortFunctionsOnASingleLineOptions.Empty = false;
   CustomInline.AllowShortFunctionsOnASingleLineOptions.Inline = true;
-  CustomInline.AllowShortFunctionsOnASingleLineOptions.All = false;
+  CustomInline.AllowShortFunctionsOnASingleLineOptions.Other = false;
 
   verifyFormat("class C {\n"
                "  int f() {}\n"
@@ -15188,7 +15191,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
   CustomAll.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
   CustomAll.AllowShortFunctionsOnASingleLineOptions.Empty = false;
   CustomAll.AllowShortFunctionsOnASingleLineOptions.Inline = false;
-  CustomAll.AllowShortFunctionsOnASingleLineOptions.All = true;
+  CustomAll.AllowShortFunctionsOnASingleLineOptions.Other = true;
 
   // All functions should be on a single line if they fit
   verifyFormat("int f() { return 42; }", CustomAll);
@@ -15209,7 +15212,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
   CustomMixed.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
   CustomMixed.AllowShortFunctionsOnASingleLineOptions.Empty = true;
   CustomMixed.AllowShortFunctionsOnASingleLineOptions.Inline = true;
-  CustomMixed.AllowShortFunctionsOnASingleLineOptions.All = false;
+  CustomMixed.AllowShortFunctionsOnASingleLineOptions.Other = false;
 
   // Empty functions should be on a single line
   verifyFormat("int f() {}", CustomMixed);

>From b1fd41217c49400248780ba6fb7a2ac0a355937c Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Mon, 7 Apr 2025 21:05:17 -0700
Subject: [PATCH 3/8] Updated configuration with new suggestion - reuse
 existing option

---
 clang/docs/ClangFormatStyleOptions.rst        |  51 ++----
 clang/include/clang/Format/Format.h           | 152 ++++++++----------
 clang/lib/Format/Format.cpp                   | 120 +++++++-------
 clang/lib/Format/TokenAnnotator.cpp           |   7 +-
 clang/lib/Format/UnwrappedLineFormatter.cpp   |   8 +-
 clang/unittests/Format/ConfigParseTest.cpp    |  38 +++--
 .../Format/DefinitionBlockSeparatorTest.cpp   |   4 +-
 clang/unittests/Format/FormatTest.cpp         | 124 +++++++++-----
 clang/unittests/Format/FormatTestCSharp.cpp   |   5 +-
 clang/unittests/Format/FormatTestJS.cpp       |  27 +++-
 clang/unittests/Format/FormatTestJava.cpp     |   5 +-
 11 files changed, 289 insertions(+), 252 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index c0529dd138f59..6f3b9f798093f 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1905,12 +1905,16 @@ the configuration (without a prefix: ``Auto``).
   Dependent on the value, ``int f() { return 0; }`` can be put on a
   single line.
 
-  Possible values:
+  Nested configuration flags:
+
+  Different styles for merging short functions containing at most one
+  statement.
 
-  * ``SFS_None`` (in configuration: ``None``)
+  They can be read as a whole for compatibility. The choices are:
+  * ``None``
     Never merge functions into a single line.
 
-  * ``SFS_InlineOnly`` (in configuration: ``InlineOnly``)
+  * ``InlineOnly``
     Only merge functions defined inside a class. Same as ``inline``,
     except it does not implies ``empty``: i.e. top level empty functions
     are not merged either.
@@ -1926,7 +1930,7 @@ the configuration (without a prefix: ``Auto``).
       void f() {
       }
 
-  * ``SFS_Empty`` (in configuration: ``Empty``)
+  * ``Empty``
     Only merge empty functions.
 
     .. code-block:: c++
@@ -1936,7 +1940,7 @@ the configuration (without a prefix: ``Auto``).
         bar2();
       }
 
-  * ``SFS_Inline`` (in configuration: ``Inline``)
+  * ``Inline``
     Only merge functions defined inside a class. Implies ``empty``.
 
     .. code-block:: c++
@@ -1949,7 +1953,7 @@ the configuration (without a prefix: ``Auto``).
       }
       void f() {}
 
-  * ``SFS_All`` (in configuration: ``All``)
+  * ``All``
     Merge all functions fitting on a single line.
 
     .. code-block:: c++
@@ -1959,37 +1963,15 @@ the configuration (without a prefix: ``Auto``).
       };
       void f() { bar(); }
 
-  * ``SFS_Custom`` (in configuration: ``Custom``)
-    Configure merge behavior using AllowShortFunctionsOnASingleLineOptions
-
+  Also can be specified as a nested configuration flag:
 
-
-.. _AllowShortFunctionsOnASingleLineOptions:
-
-**AllowShortFunctionsOnASingleLineOptions** (``ShortFunctionMergeFlags``) 
:versionbadge:`clang-format 21` :ref:`¶ 
<AllowShortFunctionsOnASingleLineOptions>`
-  Precise control over merging short functions
-
-  If ``AllowShortFunctionsOnASingleLine`` is set to ``Custom``, use this to
-  specify behavior in different situations.
-
-  .. code-block:: yaml
+  .. code-block:: c++
 
     # Example of usage:
-    AllowShortFunctionsOnASingleLine: Custom
-    AllowShortFunctionsOnASingleLineOptions:
-      Empty: false
-      Inline: true
-      All: false
-
-  Nested configuration flags:
-
-  Precise control over merging short functions
+    AllowShortFunctionsOnASingleLine: InlineOnly
 
-  .. code-block:: c++
-
-    # Should be declared this way:
-    AllowShortFunctionsOnASingleLine: Custom
-    AllowShortFunctionsOnASingleLineOptions:
+    # or more granular control:
+    AllowShortFunctionsOnASingleLine:
       Empty: false
       Inline: true
       All: false
@@ -2018,7 +2000,8 @@ the configuration (without a prefix: ``Auto``).
       void f() {
       }
 
-  * ``bool Other`` Merge all functions fitting on a single line.
+  * ``bool Other`` Merge all functions fitting on a single line. Please note 
that this
+    control does not include Empty
 
     .. code-block:: c++
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 971b978adc2c7..2278bf3966296 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -827,69 +827,68 @@ struct FormatStyle {
 
   /// Different styles for merging short functions containing at most one
   /// statement.
-  enum ShortFunctionStyle : int8_t {
-    /// Never merge functions into a single line.
-    SFS_None,
-    /// Only merge functions defined inside a class. Same as ``inline``,
-    /// except it does not implies ``empty``: i.e. top level empty functions
-    /// are not merged either.
-    /// \code
-    ///   class Foo {
-    ///     void f() { foo(); }
-    ///   };
-    ///   void f() {
-    ///     foo();
-    ///   }
-    ///   void f() {
-    ///   }
-    /// \endcode
-    SFS_InlineOnly,
-    /// Only merge empty functions.
-    /// \code
-    ///   void f() {}
-    ///   void f2() {
-    ///     bar2();
-    ///   }
-    /// \endcode
-    SFS_Empty,
-    /// Only merge functions defined inside a class. Implies ``empty``.
-    /// \code
-    ///   class Foo {
-    ///     void f() { foo(); }
-    ///   };
-    ///   void f() {
-    ///     foo();
-    ///   }
-    ///   void f() {}
-    /// \endcode
-    SFS_Inline,
-    /// Merge all functions fitting on a single line.
-    /// \code
-    ///   class Foo {
-    ///     void f() { foo(); }
-    ///   };
-    ///   void f() { bar(); }
-    /// \endcode
-    SFS_All,
-    /// Configure merge behavior using AllowShortFunctionsOnASingleLineOptions
-    SFS_Custom,
-  };
-
-  /// Dependent on the value, ``int f() { return 0; }`` can be put on a
-  /// single line.
-  /// \version 3.5
-  ShortFunctionStyle AllowShortFunctionsOnASingleLine;
-
-  /// Precise control over merging short functions
+  ///
+  /// They can be read as a whole for compatibility. The choices are:
+  /// * ``None``
+  ///   Never merge functions into a single line.
+  ///
+  /// * ``InlineOnly``
+  ///   Only merge functions defined inside a class. Same as ``inline``,
+  ///   except it does not implies ``empty``: i.e. top level empty functions
+  ///   are not merged either.
+  ///   \code
+  ///     class Foo {
+  ///       void f() { foo(); }
+  ///     };
+  ///     void f() {
+  ///       foo();
+  ///     }
+  ///     void f() {
+  ///     }
+  ///   \endcode
+  ///
+  /// * ``Empty``
+  ///   Only merge empty functions.
+  ///   \code
+  ///     void f() {}
+  ///     void f2() {
+  ///       bar2();
+  ///     }
+  ///   \endcode
+  ///
+  /// * ``Inline``
+  ///   Only merge functions defined inside a class. Implies ``empty``.
+  ///   \code
+  ///     class Foo {
+  ///       void f() { foo(); }
+  ///     };
+  ///     void f() {
+  ///       foo();
+  ///     }
+  ///     void f() {}
+  ///   \endcode
+  ///
+  /// * ``All``
+  ///   Merge all functions fitting on a single line.
+  ///   \code
+  ///     class Foo {
+  ///       void f() { foo(); }
+  ///     };
+  ///     void f() { bar(); }
+  ///   \endcode
+  ///
+  /// Also can be specified as a nested configuration flag:
   /// \code
-  ///   # Should be declared this way:
-  ///   AllowShortFunctionsOnASingleLine: Custom
-  ///   AllowShortFunctionsOnASingleLineOptions:
+  ///   # Example of usage:
+  ///   AllowShortFunctionsOnASingleLine: InlineOnly
+  ///
+  ///   # or more granular control:
+  ///   AllowShortFunctionsOnASingleLine:
   ///     Empty: false
   ///     Inline: true
   ///     All: false
   /// \endcode
-  struct ShortFunctionMergeFlags {
+  struct ShortFunctionStyle {
     /// Merge top-level empty functions.
     /// \code
     ///   void f() {}
@@ -912,7 +911,8 @@ struct FormatStyle {
     ///   }
     /// \endcode
     bool Inline;
-    /// Merge all functions fitting on a single line.
+    /// Merge all functions fitting on a single line. Please note that this
+    /// control does not include Empty
     /// \code
     ///   class Foo {
     ///     void f() { foo(); }
@@ -921,33 +921,19 @@ struct FormatStyle {
     /// \endcode
     bool Other;
 
-    ShortFunctionMergeFlags() : Empty(false), Inline(false), Other(false) {}
-
-    ShortFunctionMergeFlags(bool Empty, bool Inline, bool All)
-        : Empty(Empty), Inline(Inline), Other(All) {}
-
-    bool operator==(const ShortFunctionMergeFlags &R) const {
+    bool operator==(const ShortFunctionStyle &R) const {
       return Empty == R.Empty && Inline == R.Inline && Other == R.Other;
     }
-    bool operator!=(const ShortFunctionMergeFlags &R) const {
-      return !(*this == R);
-    }
+    bool operator!=(const ShortFunctionStyle &R) const { return !(*this == R); 
}
+    ShortFunctionStyle() : Empty(false), Inline(false), Other(false) {}
+    ShortFunctionStyle(bool Empty, bool Inline, bool Other)
+        : Empty(Empty), Inline(Inline), Other(Other) {}
   };
 
-  /// Precise control over merging short functions
-  ///
-  /// If ``AllowShortFunctionsOnASingleLine`` is set to ``Custom``, use this to
-  /// specify behavior in different situations.
-  /// \code{.yaml}
-  ///   # Example of usage:
-  ///   AllowShortFunctionsOnASingleLine: Custom
-  ///   AllowShortFunctionsOnASingleLineOptions:
-  ///     Empty: false
-  ///     Inline: true
-  ///     All: false
-  /// \endcode
-  /// \version 21
-  ShortFunctionMergeFlags AllowShortFunctionsOnASingleLineOptions;
+  /// Dependent on the value, ``int f() { return 0; }`` can be put on a
+  /// single line.
+  /// \version 3.5
+  ShortFunctionStyle AllowShortFunctionsOnASingleLine;
 
   /// Different styles for handling short if statements.
   enum ShortIfStyle : int8_t {
@@ -5352,8 +5338,6 @@ struct FormatStyle {
            AllowShortEnumsOnASingleLine == R.AllowShortEnumsOnASingleLine &&
            AllowShortFunctionsOnASingleLine ==
                R.AllowShortFunctionsOnASingleLine &&
-           AllowShortFunctionsOnASingleLineOptions ==
-               R.AllowShortFunctionsOnASingleLineOptions &&
            AllowShortIfStatementsOnASingleLine ==
                R.AllowShortIfStatementsOnASingleLine &&
            AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine 
&&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index aff38f56f05e3..c1a7a0a034a22 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -613,21 +613,35 @@ template <> struct 
ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
   }
 };
 
-template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
-  static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
-    IO.enumCase(Value, "None", FormatStyle::SFS_None);
-    IO.enumCase(Value, "false", FormatStyle::SFS_None);
-    IO.enumCase(Value, "All", FormatStyle::SFS_All);
-    IO.enumCase(Value, "true", FormatStyle::SFS_All);
-    IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
-    IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
-    IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
-    IO.enumCase(Value, "Custom", FormatStyle::SFS_Custom);
+template <> struct MappingTraits<FormatStyle::ShortFunctionStyle> {
+  static void enumInput(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
+    IO.enumCase(Value, "None", FormatStyle::ShortFunctionStyle({}));
+    IO.enumCase(Value, "Empty",
+                FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                                 /*Inline=*/false,
+                                                 /*Other=*/false}));
+    IO.enumCase(Value, "Inline",
+                FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                                 /*Inline=*/true,
+                                                 /*Other=*/false}));
+    IO.enumCase(Value, "InlineOnly",
+                FormatStyle::ShortFunctionStyle({/*Empty=*/false,
+                                                 /*Inline=*/true,
+                                                 /*Other=*/false}));
+    IO.enumCase(Value, "All",
+                FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                                 /*Inline=*/true,
+                                                 /*Other=*/true}));
+
+    // For backward compatibility.
+    IO.enumCase(Value, "true",
+                FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                                 /*Inline=*/true,
+                                                 /*Other=*/true}));
+    IO.enumCase(Value, "false", FormatStyle::ShortFunctionStyle({}));
   }
-};
 
-template <> struct MappingTraits<FormatStyle::ShortFunctionMergeFlags> {
-  static void mapping(IO &IO, FormatStyle::ShortFunctionMergeFlags &Value) {
+  static void mapping(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
     IO.mapOptional("Empty", Value.Empty);
     IO.mapOptional("Inline", Value.Inline);
     IO.mapOptional("Other", Value.Other);
@@ -991,8 +1005,6 @@ template <> struct MappingTraits<FormatStyle> {
                    Style.AllowShortEnumsOnASingleLine);
     IO.mapOptional("AllowShortFunctionsOnASingleLine",
                    Style.AllowShortFunctionsOnASingleLine);
-    IO.mapOptional("AllowShortFunctionsOnASingleLineOptions",
-                   Style.AllowShortFunctionsOnASingleLineOptions);
     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
                    Style.AllowShortIfStatementsOnASingleLine);
     IO.mapOptional("AllowShortLambdasOnASingleLine",
@@ -1483,30 +1495,6 @@ static void expandPresetsSpacesInParens(FormatStyle 
&Expanded) {
   Expanded.SpacesInParensOptions = {};
 }
 
-static void expandPresetsShortFunctionsOnSingleLine(FormatStyle &Expanded) {
-  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Custom)
-    return;
-  // Reset all flags
-  Expanded.AllowShortFunctionsOnASingleLineOptions = {};
-
-  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None)
-    return;
-
-  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||
-      Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline) {
-    Expanded.AllowShortFunctionsOnASingleLineOptions.Empty = true;
-  }
-
-  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline ||
-      Expanded.AllowShortFunctionsOnASingleLine ==
-          FormatStyle::SFS_InlineOnly) {
-    Expanded.AllowShortFunctionsOnASingleLineOptions.Inline = true;
-  }
-
-  if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
-    Expanded.AllowShortFunctionsOnASingleLineOptions.Other = true;
-}
-
 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   FormatStyle LLVMStyle;
   LLVMStyle.AccessModifierOffset = -2;
@@ -1535,9 +1523,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
   LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
   LLVMStyle.AllowShortEnumsOnASingleLine = true;
-  LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
-  LLVMStyle.AllowShortFunctionsOnASingleLineOptions = {};
-  LLVMStyle.AllowShortFunctionsOnASingleLineOptions.Other = true;
+  LLVMStyle.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
   LLVMStyle.AllowShortLoopsOnASingleLine = false;
@@ -1824,9 +1813,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
     GoogleStyle.AlignTrailingComments = {};
     GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
-    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
+    GoogleStyle.AllowShortFunctionsOnASingleLine =
+        FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                         /*Inline=*/false,
+                                         /*Other=*/false});
     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
@@ -1836,9 +1826,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
   } else if (Language == FormatStyle::LK_JavaScript) {
     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
-    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
+    GoogleStyle.AllowShortFunctionsOnASingleLine =
+        FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                         /*Inline=*/false,
+                                         /*Other=*/false});
     // TODO: still under discussion whether to switch to SLS_All.
     GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
@@ -1855,9 +1846,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
     GoogleStyle.SpacesInContainerLiterals = false;
   } else if (Language == FormatStyle::LK_Proto) {
-    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
+    GoogleStyle.AllowShortFunctionsOnASingleLine =
+        FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                         /*Inline=*/false,
+                                         /*Other=*/false});
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
     // This affects protocol buffer options specifications and text protos.
     // Text protos are currently mostly formatted inside C++ raw string 
literals
@@ -1876,9 +1868,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
     GoogleStyle.IncludeStyle.IncludeBlocks =
         tooling::IncludeStyle::IBS_Preserve;
   } else if (Language == FormatStyle::LK_CSharp) {
-    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {};
-    GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true;
+    GoogleStyle.AllowShortFunctionsOnASingleLine =
+        FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                         /*Inline=*/false,
+                                         /*Other=*/false});
     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     GoogleStyle.BreakStringLiterals = false;
     GoogleStyle.ColumnLimit = 100;
@@ -1937,9 +1930,10 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind 
Language) {
     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
   } else {
     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
-    ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
-    ChromiumStyle.AllowShortFunctionsOnASingleLineOptions = {};
-    ChromiumStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true;
+    ChromiumStyle.AllowShortFunctionsOnASingleLine =
+        FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                         /*Inline=*/true,
+                                         /*Other=*/false});
     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
     ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
@@ -1953,9 +1947,10 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind 
Language) {
 FormatStyle getMozillaStyle() {
   FormatStyle MozillaStyle = getLLVMStyle();
   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
-  MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
-  MozillaStyle.AllowShortFunctionsOnASingleLineOptions = {};
-  MozillaStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true;
+  MozillaStyle.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
       FormatStyle::DRTBS_TopLevel;
   MozillaStyle.BinPackArguments = false;
@@ -2037,8 +2032,7 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind 
Language) {
   Style.BraceWrapping.BeforeWhile = false;
   Style.PenaltyReturnTypeOnItsOwnLine = 1000;
   Style.AllowShortEnumsOnASingleLine = false;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
-  Style.AllowShortFunctionsOnASingleLineOptions = {};
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   Style.AllowShortCaseLabelsOnASingleLine = false;
   Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
   Style.AllowShortLoopsOnASingleLine = false;
@@ -2210,7 +2204,6 @@ std::string configurationAsText(const FormatStyle &Style) 
{
   expandPresetsBraceWrapping(NonConstStyle);
   expandPresetsSpaceBeforeParens(NonConstStyle);
   expandPresetsSpacesInParens(NonConstStyle);
-  expandPresetsShortFunctionsOnSingleLine(NonConstStyle);
   Output << NonConstStyle;
 
   return Stream.str();
@@ -3773,7 +3766,6 @@ reformat(const FormatStyle &Style, StringRef Code,
   expandPresetsBraceWrapping(Expanded);
   expandPresetsSpaceBeforeParens(Expanded);
   expandPresetsSpacesInParens(Expanded);
-  expandPresetsShortFunctionsOnSingleLine(Expanded);
   Expanded.InsertBraces = false;
   Expanded.RemoveBracesLLVM = false;
   Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index cdf46f65e8b52..db2f8766f8d40 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5687,10 +5687,11 @@ bool TokenAnnotator::mustBreakBefore(const 
AnnotatedLine &Line,
     if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
         !Left.Children.empty()) {
       // Support AllowShortFunctionsOnASingleLine for JavaScript.
-      return (!Style.AllowShortFunctionsOnASingleLineOptions.Inline &&
-              !Style.AllowShortFunctionsOnASingleLineOptions.Other) ||
+      return (!Style.AllowShortFunctionsOnASingleLine.Inline &&
+              !Style.AllowShortFunctionsOnASingleLine.Other) ||
              (Left.NestingLevel == 0 && Line.Level == 0 &&
-              Style.AllowShortFunctionsOnASingleLineOptions.Inline);
+              Style.AllowShortFunctionsOnASingleLine.Inline &&
+              !Style.AllowShortFunctionsOnASingleLine.Other);
     }
   } else if (Style.Language == FormatStyle::LK_Java) {
     if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight &&
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 6f30bbc8a9e5f..fdec849cf363a 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -293,14 +293,14 @@ class LineJoiner {
 
     auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine,
                                       TheLine]() {
-      if (Style.AllowShortFunctionsOnASingleLineOptions.Other)
+      if (Style.AllowShortFunctionsOnASingleLine.Other)
         return true;
-      if (Style.AllowShortFunctionsOnASingleLineOptions.Empty &&
+      if (Style.AllowShortFunctionsOnASingleLine.Empty &&
           NextLine.First->is(tok::r_brace)) {
         return true;
       }
 
-      if (Style.AllowShortFunctionsOnASingleLineOptions.Inline) {
+      if (Style.AllowShortFunctionsOnASingleLine.Inline) {
         // Just checking TheLine->Level != 0 is not enough, because it
         // provokes treating functions inside indented namespaces as short.
         if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
@@ -550,7 +550,7 @@ class LineJoiner {
 
       unsigned MergedLines = 0;
       if (MergeShortFunctions ||
-          (Style.AllowShortFunctionsOnASingleLineOptions.Empty &&
+          (Style.AllowShortFunctionsOnASingleLine.Empty &&
            NextLine.First == NextLine.Last && I + 2 != E &&
            I[2]->First->is(tok::r_brace))) {
         MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index 16ab406c9cade..c022db94cdb6a 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -256,9 +256,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements);
   CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses);
   CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, Other);
-  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Empty);
-  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Inline);
-  CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Other);
 }
 
 #undef CHECK_PARSE_BOOL
@@ -614,23 +611,40 @@ TEST(ConfigParseTest, ParsesConfiguration) {
   CHECK_PARSE("AllowShortBlocksOnASingleLine: true",
               AllowShortBlocksOnASingleLine, FormatStyle::SBS_Always);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  // Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: None",
-              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None);
+              AllowShortFunctionsOnASingleLine,
+              FormatStyle::ShortFunctionStyle({}));
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: Inline",
-              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Inline);
+              AllowShortFunctionsOnASingleLine,
+              FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                               /*Inline=*/true,
+                                               /*Other=*/false}));
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: Empty",
-              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Empty);
+              AllowShortFunctionsOnASingleLine,
+              FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                               /*Inline=*/false,
+                                               /*Other=*/false}));
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: All",
-              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All);
-  CHECK_PARSE("AllowShortFunctionsOnASingleLine: Custom",
-              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Custom);
+              AllowShortFunctionsOnASingleLine,
+              FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                               /*Inline=*/true,
+                                               /*Other=*/true}));
+  CHECK_PARSE("AllowShortFunctionsOnASingleLine: InlineOnly",
+              AllowShortFunctionsOnASingleLine,
+              FormatStyle::ShortFunctionStyle({/*Empty=*/false,
+                                               /*Inline=*/true,
+                                               /*Other=*/false}));
 
   // For backward compatibility:
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: false",
-              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None);
+              AllowShortFunctionsOnASingleLine,
+              FormatStyle::ShortFunctionStyle({}));
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: true",
-              AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All);
+              AllowShortFunctionsOnASingleLine,
+              FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                               /*Inline=*/true,
+                                               /*Other=*/true}));
 
   Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
   CHECK_PARSE("AllowShortLambdasOnASingleLine: None",
diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp 
b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
index b26b9f4f4ff62..d3d0a0b56b5a0 100644
--- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
+++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
@@ -540,7 +540,7 @@ TEST_F(DefinitionBlockSeparatorTest, Leave) {
 TEST_F(DefinitionBlockSeparatorTest, CSharp) {
   FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp);
   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   Style.AllowShortEnumsOnASingleLine = false;
   verifyFormat("namespace {\r\n"
                "public class SomeTinyClass {\r\n"
@@ -581,7 +581,7 @@ TEST_F(DefinitionBlockSeparatorTest, CSharp) {
 TEST_F(DefinitionBlockSeparatorTest, JavaScript) {
   FormatStyle Style = getLLVMStyle(FormatStyle::LK_JavaScript);
   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   Style.AllowShortEnumsOnASingleLine = false;
   verifyFormat("export const enum Foo {\n"
                "  A = 1,\n"
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 79ee1230eb6a7..382e9e855b622 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -388,7 +388,10 @@ TEST_F(FormatTest, RemovesEmptyLines) {
                "}  // namespace");
 
   FormatStyle Style = getLLVMStyle();
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   Style.MaxEmptyLinesToKeep = 2;
   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
   Style.BraceWrapping.AfterClass = true;
@@ -3377,13 +3380,16 @@ TEST_F(FormatTest, MultiLineControlStatements) {
   Style.BraceWrapping.AfterFunction = true;
   Style.BraceWrapping.AfterStruct = false;
   Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_MultiLine;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   Style.ColumnLimit = 80;
   verifyFormat("void shortfunction() { bar(); }", Style);
   verifyFormat("struct T shortfunction() { return bar(); }", Style);
   verifyFormat("struct T {};", Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   verifyFormat("void shortfunction()\n"
                "{\n"
                "  bar();\n"
@@ -3398,7 +3404,10 @@ TEST_F(FormatTest, MultiLineControlStatements) {
 
   Style.BraceWrapping.AfterFunction = false;
   Style.BraceWrapping.AfterStruct = true;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   verifyFormat("void shortfunction() { bar(); }", Style);
   verifyFormat("struct T shortfunction() { return bar(); }", Style);
   verifyFormat("struct T\n"
@@ -3406,7 +3415,7 @@ TEST_F(FormatTest, MultiLineControlStatements) {
                "};",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   verifyFormat("void shortfunction() {\n"
                "  bar();\n"
                "}",
@@ -4201,7 +4210,9 @@ TEST_F(FormatTest, FormatsNamespaces) {
   FormatStyle ShortInlineFunctions = getLLVMStyle();
   ShortInlineFunctions.NamespaceIndentation = FormatStyle::NI_All;
   ShortInlineFunctions.AllowShortFunctionsOnASingleLine =
-      FormatStyle::SFS_Inline;
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("namespace {\n"
                "  void f() {\n"
                "    return;\n"
@@ -8326,7 +8337,7 @@ TEST_F(FormatTest, 
BreakConstructorInitializersAfterColon) {
                "};",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   verifyNoChange("SomeClass::Constructor() :\n"
                  "    a(a), b(b), c(c) {\n"
                  "}",
@@ -8337,7 +8348,10 @@ TEST_F(FormatTest, 
BreakConstructorInitializersAfterColon) {
                  Style);
 
   Style.ColumnLimit = 80;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   Style.ConstructorInitializerIndentWidth = 2;
   verifyFormat("SomeClass::Constructor() : a(a), b(b), c(c) {}", Style);
   verifyFormat("SomeClass::Constructor() :\n"
@@ -12671,7 +12685,8 @@ TEST_F(FormatTest, UnderstandsAttributes) {
   verifyFormat("__attr1(nodebug) ::qualified_type f();", CustomAttrs);
 
   // Check that these are not parsed as function declarations:
-  CustomAttrs.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  CustomAttrs.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({});
   CustomAttrs.BreakBeforeBraces = FormatStyle::BS_Allman;
   verifyFormat("SomeType s(InitValue);", CustomAttrs);
   verifyFormat("SomeType s{InitValue};", CustomAttrs);
@@ -12772,7 +12787,8 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) {
 
   // Make sure we do not parse attributes as lambda introducers.
   FormatStyle MultiLineFunctions = getLLVMStyle();
-  MultiLineFunctions.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  MultiLineFunctions.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({});
   verifyFormat("[[unused]] int b() {\n"
                "  return 42;\n"
                "}",
@@ -14870,7 +14886,8 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) {
 
 TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
   FormatStyle DoNotMerge = getLLVMStyle();
-  DoNotMerge.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  DoNotMerge.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({});
 
   verifyFormat("void f() { return 42; }");
   verifyFormat("void f() {\n"
@@ -14941,7 +14958,7 @@ TEST_F(FormatTest, 
PullTrivialFunctionDefinitionsIntoSingleLine) {
 
   FormatStyle DoNotMergeNoColumnLimit = NoColumnLimit;
   DoNotMergeNoColumnLimit.AllowShortFunctionsOnASingleLine =
-      FormatStyle::SFS_None;
+      FormatStyle::ShortFunctionStyle({});
   verifyFormat("A() : b(0) {\n"
                "}",
                DoNotMergeNoColumnLimit);
@@ -14989,7 +15006,10 @@ TEST_F(FormatTest, 
PullTrivialFunctionDefinitionsIntoSingleLine) {
 
 TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) {
   FormatStyle MergeEmptyOnly = getLLVMStyle();
-  MergeEmptyOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+  MergeEmptyOnly.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/false,
+                                       /*Other=*/false});
   verifyFormat("class C {\n"
                "  int f() {}\n"
                "};",
@@ -15018,7 +15038,10 @@ TEST_F(FormatTest, 
PullEmptyFunctionDefinitionsIntoSingleLine) {
 
 TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) {
   FormatStyle MergeInlineOnly = getLLVMStyle();
-  MergeInlineOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  MergeInlineOnly.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("class C {\n"
                "  int f() { return 42; }\n"
                "};",
@@ -15122,10 +15145,10 @@ TEST_F(FormatTest, 
PullInlineFunctionDefinitionsIntoSingleLine) {
 
 TEST_F(FormatTest, CustomShortFunctionOptions) {
   FormatStyle CustomEmpty = getLLVMStyle();
-  CustomEmpty.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
-  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Empty = true;
-  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Inline = false;
-  CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Other = false;
+  CustomEmpty.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/false,
+                                       /*Other=*/false});
 
   // Empty functions should be on a single line
   verifyFormat("int f() {}", CustomEmpty);
@@ -15161,10 +15184,10 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
 
   // Test with Inline = true, All = false
   FormatStyle CustomInline = getLLVMStyle();
-  CustomInline.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
-  CustomInline.AllowShortFunctionsOnASingleLineOptions.Empty = false;
-  CustomInline.AllowShortFunctionsOnASingleLineOptions.Inline = true;
-  CustomInline.AllowShortFunctionsOnASingleLineOptions.Other = false;
+  CustomInline.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/false,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
 
   verifyFormat("class C {\n"
                "  int f() {}\n"
@@ -15188,10 +15211,10 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
 
   // Test with All = true
   FormatStyle CustomAll = getLLVMStyle();
-  CustomAll.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
-  CustomAll.AllowShortFunctionsOnASingleLineOptions.Empty = false;
-  CustomAll.AllowShortFunctionsOnASingleLineOptions.Inline = false;
-  CustomAll.AllowShortFunctionsOnASingleLineOptions.Other = true;
+  CustomAll.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
 
   // All functions should be on a single line if they fit
   verifyFormat("int f() { return 42; }", CustomAll);
@@ -15209,10 +15232,10 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
 
   // Test various combinations
   FormatStyle CustomMixed = getLLVMStyle();
-  CustomMixed.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom;
-  CustomMixed.AllowShortFunctionsOnASingleLineOptions.Empty = true;
-  CustomMixed.AllowShortFunctionsOnASingleLineOptions.Inline = true;
-  CustomMixed.AllowShortFunctionsOnASingleLineOptions.Other = false;
+  CustomMixed.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
 
   // Empty functions should be on a single line
   verifyFormat("int f() {}", CustomMixed);
@@ -15237,7 +15260,9 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
 TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) {
   FormatStyle MergeInlineOnly = getLLVMStyle();
   MergeInlineOnly.AllowShortFunctionsOnASingleLine =
-      FormatStyle::SFS_InlineOnly;
+      FormatStyle::ShortFunctionStyle({/*Empty=*/false,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("class C {\n"
                "  int f() { return 42; }\n"
                "};",
@@ -15282,7 +15307,7 @@ TEST_F(FormatTest, 
PullInlineOnlyFunctionDefinitionsIntoSingleLine) {
 
 TEST_F(FormatTest, SplitEmptyFunction) {
   FormatStyle Style = getLLVMStyleWithColumns(40);
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
   Style.BraceWrapping.AfterFunction = true;
   Style.BraceWrapping.SplitEmptyFunction = false;
@@ -15301,7 +15326,10 @@ TEST_F(FormatTest, SplitEmptyFunction) {
                "}",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/false,
+                                       /*Other=*/false});
   verifyFormat("int f() {}", Style);
   verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n"
                "{}",
@@ -15312,7 +15340,10 @@ TEST_F(FormatTest, SplitEmptyFunction) {
                "}",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("class Foo {\n"
                "  int f() {}\n"
                "};",
@@ -15334,7 +15365,10 @@ TEST_F(FormatTest, SplitEmptyFunction) {
                "};",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   verifyFormat("int f() {}", Style);
   verifyFormat("int f() { return 0; }", Style);
   verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n"
@@ -15349,7 +15383,7 @@ TEST_F(FormatTest, SplitEmptyFunction) {
 
 TEST_F(FormatTest, SplitEmptyFunctionButNotRecord) {
   FormatStyle Style = getLLVMStyleWithColumns(40);
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
   Style.BraceWrapping.AfterFunction = true;
   Style.BraceWrapping.SplitEmptyFunction = true;
@@ -15379,7 +15413,10 @@ TEST_F(FormatTest, SplitEmptyFunctionButNotRecord) {
 
 TEST_F(FormatTest, KeepShortFunctionAfterPPElse) {
   FormatStyle Style = getLLVMStyle();
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   verifyFormat("#ifdef A\n"
                "int f() {}\n"
                "#else\n"
@@ -21492,7 +21529,9 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) {
 
   // Make a few changes to the style for testing purposes
   WhitesmithsBraceStyle.AllowShortFunctionsOnASingleLine =
-      FormatStyle::SFS_Empty;
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/false,
+                                       /*Other=*/false});
   WhitesmithsBraceStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
 
   // FIXME: this test case can't decide whether there should be a blank line
@@ -23038,7 +23077,7 @@ TEST_F(FormatTest, 
BreakConstructorInitializersBeforeComma) {
                "}",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   verifyFormat("SomeClass::Constructor()\n"
                "    : a(a)\n"
                "    , b(b)\n"
@@ -23049,7 +23088,10 @@ TEST_F(FormatTest, 
BreakConstructorInitializersBeforeComma) {
                Style);
 
   Style.ColumnLimit = 80;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   Style.ConstructorInitializerIndentWidth = 2;
   verifyFormat("SomeClass::Constructor()\n"
                "  : a(a)\n"
@@ -27198,7 +27240,7 @@ TEST_F(FormatTest, FormatDecayCopy) {
 TEST_F(FormatTest, Cpp20ModulesSupport) {
   FormatStyle Style = getLLVMStyle();
   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
 
   verifyFormat("export import foo;", Style);
   verifyFormat("export import foo:bar;", Style);
diff --git a/clang/unittests/Format/FormatTestCSharp.cpp 
b/clang/unittests/Format/FormatTestCSharp.cpp
index 151f7072e0c65..22c757509f5fb 100644
--- a/clang/unittests/Format/FormatTestCSharp.cpp
+++ b/clang/unittests/Format/FormatTestCSharp.cpp
@@ -1660,7 +1660,10 @@ TEST_F(FormatTestCSharp, EmptyShortBlock) {
 TEST_F(FormatTestCSharp, ShortFunctions) {
   FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp);
   Style.NamespaceIndentation = FormatStyle::NI_All;
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("interface Interface {\n"
                "  void f() { return; }\n"
                "};",
diff --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index 78c9f887a159b..2108bb21f192e 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -1010,7 +1010,10 @@ TEST_F(FormatTestJS, TrailingCommaInsertion) {
 
 TEST_F(FormatTestJS, FunctionLiterals) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("doFoo(function() {});");
   verifyFormat("doFoo(function() { return 1; });", Style);
   verifyFormat("var func = function() {\n"
@@ -1123,7 +1126,10 @@ TEST_F(FormatTestJS, DontWrapEmptyLiterals) {
 
 TEST_F(FormatTestJS, InliningFunctionLiterals) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("var func = function() {\n"
                "  return 1;\n"
                "};",
@@ -1138,7 +1144,10 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) {
                "}",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   verifyFormat("var func = function() { return 1; };", Style);
   verifyFormat("var func = doSomething(function() { return 1; });", Style);
   verifyFormat(
@@ -1149,7 +1158,7 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) {
                "}",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({});
   verifyFormat("var func = function() {\n"
                "  return 1;\n"
                "};",
@@ -1171,7 +1180,10 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) {
                "}",
                Style);
 
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/false,
+                                       /*Other=*/false});
   verifyFormat("var func = function() {\n"
                "  return 1;\n"
                "};",
@@ -1180,7 +1192,10 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) {
 
 TEST_F(FormatTestJS, MultipleFunctionLiterals) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/true});
   verifyFormat("promise.then(\n"
                "    function success() {\n"
                "      doFoo();\n"
diff --git a/clang/unittests/Format/FormatTestJava.cpp 
b/clang/unittests/Format/FormatTestJava.cpp
index 33998bc7ff858..bba6541395171 100644
--- a/clang/unittests/Format/FormatTestJava.cpp
+++ b/clang/unittests/Format/FormatTestJava.cpp
@@ -594,7 +594,10 @@ TEST_F(FormatTestJava, RetainsLogicalShifts) {
 
 TEST_F(FormatTestJava, ShortFunctions) {
   FormatStyle Style = getLLVMStyle(FormatStyle::LK_Java);
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+  Style.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/true,
+                                       /*Inline=*/true,
+                                       /*Other=*/false});
   verifyFormat("enum Enum {\n"
                "  E1,\n"
                "  E2;\n"

>From 7f80e4adcac43f3b2c393a499627a1ca4d0beaef Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Tue, 8 Apr 2025 21:13:35 -0700
Subject: [PATCH 4/8] fixed documentation error

---
 clang/docs/ClangFormatStyleOptions.rst | 1 +
 clang/include/clang/Format/Format.h    | 1 +
 2 files changed, 2 insertions(+)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 6f3b9f798093f..1c55b74395062 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1911,6 +1911,7 @@ the configuration (without a prefix: ``Auto``).
   statement.
 
   They can be read as a whole for compatibility. The choices are:
+
   * ``None``
     Never merge functions into a single line.
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 2278bf3966296..e5c031c7b249f 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -829,6 +829,7 @@ struct FormatStyle {
   /// statement.
   ///
   /// They can be read as a whole for compatibility. The choices are:
+  ///
   /// * ``None``
   ///   Never merge functions into a single line.
   ///

>From bbe22735987f4f24d278e73df74e59ad9b246d95 Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Wed, 9 Apr 2025 19:27:10 -0700
Subject: [PATCH 5/8] Fixed PR comments

---
 clang/docs/ClangFormatStyleOptions.rst     | 2 +-
 clang/include/clang/Format/Format.h        | 2 +-
 clang/lib/Format/TokenAnnotator.cpp        | 8 +++-----
 clang/unittests/Format/ConfigParseTest.cpp | 1 -
 4 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 1c55b74395062..d67c8891a4506 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1975,7 +1975,7 @@ the configuration (without a prefix: ``Auto``).
     AllowShortFunctionsOnASingleLine:
       Empty: false
       Inline: true
-      All: false
+      Other: false
 
   * ``bool Empty`` Merge top-level empty functions.
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index e5c031c7b249f..7836fa91b20a8 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -887,7 +887,7 @@ struct FormatStyle {
   ///   AllowShortFunctionsOnASingleLine:
   ///     Empty: false
   ///     Inline: true
-  ///     All: false
+  ///     Other: false
   /// \endcode
   struct ShortFunctionStyle {
     /// Merge top-level empty functions.
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index db2f8766f8d40..f85ddbe2f0523 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5687,11 +5687,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine 
&Line,
     if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
         !Left.Children.empty()) {
       // Support AllowShortFunctionsOnASingleLine for JavaScript.
-      return (!Style.AllowShortFunctionsOnASingleLine.Inline &&
-              !Style.AllowShortFunctionsOnASingleLine.Other) ||
-             (Left.NestingLevel == 0 && Line.Level == 0 &&
-              Style.AllowShortFunctionsOnASingleLine.Inline &&
-              !Style.AllowShortFunctionsOnASingleLine.Other);
+      return !(Left.NestingLevel == 0 && Line.Level == 0
+                   ? Style.AllowShortFunctionsOnASingleLine.Other
+                   : Style.AllowShortFunctionsOnASingleLine.Inline);
     }
   } else if (Style.Language == FormatStyle::LK_Java) {
     if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight &&
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index c022db94cdb6a..b48dd0a737eea 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -611,7 +611,6 @@ TEST(ConfigParseTest, ParsesConfiguration) {
   CHECK_PARSE("AllowShortBlocksOnASingleLine: true",
               AllowShortBlocksOnASingleLine, FormatStyle::SBS_Always);
 
-  // Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
   CHECK_PARSE("AllowShortFunctionsOnASingleLine: None",
               AllowShortFunctionsOnASingleLine,
               FormatStyle::ShortFunctionStyle({}));

>From 5ff5810b53308fb2df457b339743991b1fcc9695 Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Sun, 13 Apr 2025 15:14:16 -0700
Subject: [PATCH 6/8] marked options as deprecated

---
 clang/docs/ClangFormatStyleOptions.rst | 11 ++++++++---
 clang/include/clang/Format/Format.h    | 11 ++++++++---
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index d67c8891a4506..a01b9baf482e3 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1918,7 +1918,8 @@ the configuration (without a prefix: ``Auto``).
   * ``InlineOnly``
     Only merge functions defined inside a class. Same as ``inline``,
     except it does not implies ``empty``: i.e. top level empty functions
-    are not merged either.
+    are not merged either. This option is **deprecated** and is retained
+    for backwards compatibility. See ``Inline`` of ``ShortFunctionStyle``.
 
     .. code-block:: c++
 
@@ -1932,7 +1933,9 @@ the configuration (without a prefix: ``Auto``).
       }
 
   * ``Empty``
-    Only merge empty functions.
+    Only merge empty functions. This option is **deprecated** and is
+    retained for backwards compatibility. See ``Empty`` of
+    ``ShortFunctionStyle``.
 
     .. code-block:: c++
 
@@ -1942,7 +1945,9 @@ the configuration (without a prefix: ``Auto``).
       }
 
   * ``Inline``
-    Only merge functions defined inside a class. Implies ``empty``.
+    Only merge functions defined inside a class. Implies ``empty``. This
+    option is **deprecated** and is retained for backwards compatibility.
+    See ``Inline`` and ``Empty`` of ``ShortFunctionStyle``.
 
     .. code-block:: c++
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 7836fa91b20a8..448e8d0f2eb77 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -836,7 +836,8 @@ struct FormatStyle {
   /// * ``InlineOnly``
   ///   Only merge functions defined inside a class. Same as ``inline``,
   ///   except it does not implies ``empty``: i.e. top level empty functions
-  ///   are not merged either.
+  ///   are not merged either. This option is **deprecated** and is retained
+  ///   for backwards compatibility. See ``Inline`` of ``ShortFunctionStyle``.
   ///   \code
   ///     class Foo {
   ///       void f() { foo(); }
@@ -849,7 +850,9 @@ struct FormatStyle {
   ///   \endcode
   ///
   /// * ``Empty``
-  ///   Only merge empty functions.
+  ///   Only merge empty functions. This option is **deprecated** and is
+  ///   retained for backwards compatibility. See ``Empty`` of
+  ///   ``ShortFunctionStyle``.
   ///   \code
   ///     void f() {}
   ///     void f2() {
@@ -858,7 +861,9 @@ struct FormatStyle {
   ///   \endcode
   ///
   /// * ``Inline``
-  ///   Only merge functions defined inside a class. Implies ``empty``.
+  ///   Only merge functions defined inside a class. Implies ``empty``. This
+  ///   option is **deprecated** and is retained for backwards compatibility.
+  ///   See ``Inline`` and ``Empty`` of ``ShortFunctionStyle``.
   ///   \code
   ///     class Foo {
   ///       void f() { foo(); }

>From 70eafeabdff7f1f3e765f7dae29eec9c202170c8 Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Tue, 15 Apr 2025 20:38:36 -0700
Subject: [PATCH 7/8] fixed PR comments

---
 clang/include/clang/Format/Format.h         | 3 +++
 clang/lib/Format/TokenAnnotator.cpp         | 2 +-
 clang/lib/Format/UnwrappedLineFormatter.cpp | 5 +++--
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 448e8d0f2eb77..b56806ca2ccfa 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -934,6 +934,9 @@ struct FormatStyle {
     ShortFunctionStyle() : Empty(false), Inline(false), Other(false) {}
     ShortFunctionStyle(bool Empty, bool Inline, bool Other)
         : Empty(Empty), Inline(Inline), Other(Other) {}
+    bool isAll() const {
+      return Empty && Inline && Other;
+    }
   };
 
   /// Dependent on the value, ``int f() { return 0; }`` can be put on a
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index f85ddbe2f0523..73ff1c537d1e8 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5688,7 +5688,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine 
&Line,
         !Left.Children.empty()) {
       // Support AllowShortFunctionsOnASingleLine for JavaScript.
       return !(Left.NestingLevel == 0 && Line.Level == 0
-                   ? Style.AllowShortFunctionsOnASingleLine.Other
+                   ? Style.AllowShortFunctionsOnASingleLine.isAll()
                    : Style.AllowShortFunctionsOnASingleLine.Inline);
     }
   } else if (Style.Language == FormatStyle::LK_Java) {
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index fdec849cf363a..c6b9ad02a22b5 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -293,14 +293,15 @@ class LineJoiner {
 
     auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine,
                                       TheLine]() {
-      if (Style.AllowShortFunctionsOnASingleLine.Other)
+      if (Style.AllowShortFunctionsOnASingleLine.isAll())
         return true;
       if (Style.AllowShortFunctionsOnASingleLine.Empty &&
           NextLine.First->is(tok::r_brace)) {
         return true;
       }
 
-      if (Style.AllowShortFunctionsOnASingleLine.Inline) {
+      if (Style.AllowShortFunctionsOnASingleLine.Inline &&
+          !Style.AllowShortFunctionsOnASingleLine.isAll()) {
         // Just checking TheLine->Level != 0 is not enough, because it
         // provokes treating functions inside indented namespaces as short.
         if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))

>From dd6493d703237cc0a1c9a8e61696482cd91edb92 Mon Sep 17 00:00:00 2001
From: Ivan Rymarchyk <>
Date: Tue, 15 Apr 2025 21:42:01 -0700
Subject: [PATCH 8/8] added usage of 'other'

---
 clang/include/clang/Format/Format.h         |  4 +-
 clang/lib/Format/UnwrappedLineFormatter.cpp | 63 +++++++++++----------
 clang/unittests/Format/FormatTest.cpp       | 20 +++++++
 3 files changed, 55 insertions(+), 32 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index b56806ca2ccfa..38b68651e0322 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -934,9 +934,7 @@ struct FormatStyle {
     ShortFunctionStyle() : Empty(false), Inline(false), Other(false) {}
     ShortFunctionStyle(bool Empty, bool Inline, bool Other)
         : Empty(Empty), Inline(Inline), Other(Other) {}
-    bool isAll() const {
-      return Empty && Inline && Other;
-    }
+    bool isAll() const { return Empty && Inline && Other; }
   };
 
   /// Dependent on the value, ``int f() { return 0; }`` can be put on a
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index c6b9ad02a22b5..71d53c1c60c58 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -295,47 +295,52 @@ class LineJoiner {
                                       TheLine]() {
       if (Style.AllowShortFunctionsOnASingleLine.isAll())
         return true;
-      if (Style.AllowShortFunctionsOnASingleLine.Empty &&
-          NextLine.First->is(tok::r_brace)) {
+
+      // there might be a case where empty function is in class, so need to
+      // check inline later
+      bool empty_function = NextLine.First->is(tok::r_brace);
+      if (Style.AllowShortFunctionsOnASingleLine.Empty && empty_function)
         return true;
-      }
 
-      if (Style.AllowShortFunctionsOnASingleLine.Inline &&
-          !Style.AllowShortFunctionsOnASingleLine.isAll()) {
+      if (TheLine->Level != 0) {
+        if (!Style.AllowShortFunctionsOnASingleLine.Inline)
+          return false;
+
         // Just checking TheLine->Level != 0 is not enough, because it
         // provokes treating functions inside indented namespaces as short.
         if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
           return true;
 
-        if (TheLine->Level != 0) {
-          if (!PreviousLine)
-            return false;
-
-          // TODO: Use IndentTracker to avoid loop?
-          // Find the last line with lower level.
-          const AnnotatedLine *Line = nullptr;
-          for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
-            assert(*J);
-            if (!(*J)->InPPDirective && !(*J)->isComment() &&
-                (*J)->Level < TheLine->Level) {
-              Line = *J;
-              break;
-            }
+        if (!PreviousLine)
+          return false;
+
+        // TODO: Use IndentTracker to avoid loop?
+        // Find the last line with lower level.
+        const AnnotatedLine *Line = nullptr;
+        for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
+          assert(*J);
+          if (!(*J)->InPPDirective && !(*J)->isComment() &&
+              (*J)->Level < TheLine->Level) {
+            Line = *J;
+            break;
           }
+        }
 
-          if (!Line)
-            return false;
+        if (!Line)
+          return false;
 
-          // Check if the found line starts a record.
-          const auto *LastNonComment = Line->getLastNonComment();
-          // There must be another token (usually `{`), because we chose a
-          // non-PPDirective and non-comment line that has a smaller level.
-          assert(LastNonComment);
-          return isRecordLBrace(*LastNonComment);
-        }
+        // Check if the found line starts a record.
+        const auto *LastNonComment = Line->getLastNonComment();
+        // There must be another token (usually `{`), because we chose a
+        // non-PPDirective and non-comment line that has a smaller level.
+        assert(LastNonComment);
+        return isRecordLBrace(*LastNonComment);
       }
 
-      return false;
+      if (empty_function && !Style.AllowShortFunctionsOnASingleLine.Empty)
+        return false;
+
+      return Style.AllowShortFunctionsOnASingleLine.Other;
     };
 
     bool MergeShortFunctions = ShouldMergeShortFunctions();
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 382e9e855b622..b780dee7660ae 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -15255,6 +15255,26 @@ TEST_F(FormatTest, CustomShortFunctionOptions) {
                "  return 42;\n"
                "}",
                CustomMixed);
+
+  FormatStyle OnlyOther = getLLVMStyle();
+  OnlyOther.AllowShortFunctionsOnASingleLine =
+      FormatStyle::ShortFunctionStyle({/*Empty=*/false,
+                                       /*Inline=*/false,
+                                       /*Other=*/true});
+  verifyFormat("void topLevelEmpty() {\n"
+               "}",
+               OnlyOther);
+
+  verifyFormat("void topLevelNonEmpty() { return; }", OnlyOther);
+
+  verifyFormat("class C {\n"
+               "  int inlineEmpty() {\n"
+               "  }\n"
+               "  int inlineNonempty() {\n"
+               "    return 42;\n"
+               "  }\n"
+               "};",
+               OnlyOther);
 }
 
 TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) {

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

Reply via email to