Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -144,6 +144,19 @@ /// \endcode bool AllowAllParametersOfDeclarationOnNextLine; + /// \brief If ``true``, empty function body can be put on a single line. + /// This option is used only if the opening brace of the function has already + /// been wrapped, i.e. if clang-format failed to put the function on a single + /// line (as per `AllowShortFunctionsOnASingleLine`) and if `AfterFunction` + /// brace wrapping mode is set. + /// \code + /// int f() vs. inf f() + /// {} { + /// } + /// \endcode + /// + bool AllowEmptyFunctionBodyOnASingleLine; + /// \brief Allows contracting simple braced statements to a single line. /// /// E.g., this allows ``if (a) { return; }`` to be put on a single line. @@ -1352,6 +1365,8 @@ AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == R.AllowAllParametersOfDeclarationOnNextLine && + AllowEmptyFunctionBodyOnASingleLine == + R.AllowEmptyFunctionBodyOnASingleLine && AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine && AllowShortCaseLabelsOnASingleLine == R.AllowShortCaseLabelsOnASingleLine && Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -252,6 +252,8 @@ IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); + IO.mapOptional("AllowEmptyFunctionBodyOnASingleLine", + Style.AllowEmptyFunctionBodyOnASingleLine); IO.mapOptional("AllowShortBlocksOnASingleLine", Style.AllowShortBlocksOnASingleLine); IO.mapOptional("AllowShortCaseLabelsOnASingleLine", @@ -505,6 +507,7 @@ LLVMStyle.AlignConsecutiveAssignments = false; LLVMStyle.AlignConsecutiveDeclarations = false; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; + LLVMStyle.AllowEmptyFunctionBodyOnASingleLine = false; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortBlocksOnASingleLine = false; LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -178,6 +178,12 @@ if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit) return 0; + if (TheLine->Last->is(TT_FunctionLBrace) && + TheLine->First == TheLine->Last && + Style.AllowEmptyFunctionBodyOnASingleLine && + I[1]->First->is(tok::r_brace)) + return tryMergeSimpleBlock(I, E, 1); + unsigned Limit = Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent; // If we already exceed the column limit, we set 'Limit' to 0. The different Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -6006,6 +6006,32 @@ getLLVMStyleWithColumns(23)); } +TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) { + FormatStyle MergeEmptyOnly = getLLVMStyle(); + MergeEmptyOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeEmptyOnly); + verifyFormat("class C {\n" + " int f() {\n" + " return 42;\n" + " }\n" + "};", + MergeEmptyOnly); + verifyFormat("int f() {}", + MergeEmptyOnly); + verifyFormat("int f() {\n" + " return 42;\n" + "}", + MergeEmptyOnly); + + //TODO: this case does not work, not sure if there is reason... + MergeEmptyOnly.BreakBeforeBraces = FormatStyle::BS_Custom; + MergeEmptyOnly.BraceWrapping.AfterFunction = true; + verifyFormat("int f() {}", MergeEmptyOnly); +} + TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { FormatStyle MergeInlineOnly = getLLVMStyle(); MergeInlineOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; @@ -6017,6 +6043,84 @@ " return 42;\n" "}", MergeInlineOnly); + + // SFS_Inline implies SFS_Empty + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeInlineOnly); + verifyFormat("int f() {}", + MergeInlineOnly); +} + +TEST_F(FormatTest, AllowEmptyFunctionBodyOnASingleLine) { + FormatStyle Style = getLLVMStyle(); + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowEmptyFunctionBodyOnASingleLine = true; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterFunction = true; + Style.ColumnLimit = 40; + + verifyFormat("int f()\n" + "{}", + Style); + verifyFormat("int f()\n" + "{\n" + " return 42;\n" + "}", + Style); + verifyFormat("int f()\n" + "{\n" + " // some comment\n" + "}", + Style); + + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + //verifyFormat("int f() {}", Style); //TODO: re-enable once PullEmptyFunctionDefinitionsIntoSingleLine is fixed + verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + "{}", + Style); + verifyFormat("int f()\n" + "{\n" + " return 0;\n" + "}", + Style); + + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + verifyFormat("class Foo {\n" + " int f() {}\n" + "};\n", + Style); + verifyFormat("class Foo {\n" + " int f() { return 0; }\n" + "};\n", + Style); + verifyFormat("class Foo {\n" + " int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + " {}\n" + "};\n", + Style); + verifyFormat("class Foo {\n" + " int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + " {\n" + " return 0;\n" + " }\n" + "};\n", + Style); + + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + verifyFormat("int f() {}", + Style); + verifyFormat("int f() { return 0; }", + Style); + verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + "{}", + Style); + verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + "{\n" + " return 0;\n" + "}", + Style); } TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {