Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -184,9 +184,23 @@ enum ShortFunctionStyle { /// \brief Never merge functions into a single line. SFS_None, + /// \brief 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, /// \brief Only merge empty functions. /// \code - /// void f() { bar(); } + /// void f() {} /// void f2() { /// bar2(); /// } @@ -197,6 +211,10 @@ /// class Foo { /// void f() { foo(); } /// }; + /// void f() { + /// foo(); + /// } + /// void f() {} /// \endcode SFS_Inline, /// \brief Merge all functions fitting on a single line. @@ -213,6 +231,15 @@ /// single line. ShortFunctionStyle AllowShortFunctionsOnASingleLine; + bool allowEmptyFunctionsOnASingleLine() const { + return AllowShortFunctionsOnASingleLine >= ShortFunctionStyle::SFS_Empty; + } + + bool allowShortInlineFunctionsOnASingleLine() const { + return AllowShortFunctionsOnASingleLine == ShortFunctionStyle::SFS_Inline || + AllowShortFunctionsOnASingleLine == ShortFunctionStyle::SFS_InlineOnly; + } + /// \brief If ``true``, ``if (a) return;`` can be put on a single line. bool AllowShortIfStatementsOnASingleLine; Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -96,6 +96,7 @@ 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); } }; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -2480,8 +2480,7 @@ return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None || Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty || (Left.NestingLevel == 0 && Line.Level == 0 && - Style.AllowShortFunctionsOnASingleLine == - FormatStyle::SFS_Inline); + Style.allowShortInlineFunctionsOnASingleLine()); } else if (Style.Language == FormatStyle::LK_Java) { if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next && Right.Next->is(tok::string_literal)) Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -224,9 +224,9 @@ // If necessary, change to something smarter. bool MergeShortFunctions = Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All || - (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + (Style.allowEmptyFunctionsOnASingleLine() && I[1]->First->is(tok::r_brace)) || - (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline && + (Style.allowShortInlineFunctionsOnASingleLine() && TheLine->Level != 0); if (Style.CompactNamespaces) { @@ -282,7 +282,7 @@ unsigned MergedLines = 0; if (MergeShortFunctions || - (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + (Style.allowEmptyFunctionsOnASingleLine() && I[1]->First == I[1]->Last && I + 2 != E && I[2]->First->is(tok::r_brace))) { MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -6509,6 +6509,49 @@ MergeInlineOnly); } +TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) { + FormatStyle MergeInlineOnly = getLLVMStyle(); + MergeInlineOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_InlineOnly; + verifyFormat("class C {\n" + " int f() { return 42; }\n" + "};", + MergeInlineOnly); + verifyFormat("int f() {\n" + " return 42;\n" + "}", + MergeInlineOnly); + + // SFS_InlineOnly does not imply SFS_Empty + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeInlineOnly); + verifyFormat("int f() {\n" + "}", MergeInlineOnly); + + // Also verify behavior when BraceWrapping.AfterFunction = true + MergeInlineOnly.BreakBeforeBraces = FormatStyle::BS_Custom; + MergeInlineOnly.BraceWrapping.AfterFunction = true; + verifyFormat("class C {\n" + " int f() { return 42; }\n" + "};", + MergeInlineOnly); + verifyFormat("int f()\n" + "{\n" + " return 42;\n" + "}", + MergeInlineOnly); + + // SFS_InlineOnly does not imply SFS_Empty + verifyFormat("int f()\n" + "{\n" + "}", MergeInlineOnly); + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeInlineOnly); +} + TEST_F(FormatTest, SplitEmptyFunctionBody) { FormatStyle Style = getLLVMStyle(); Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;