summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/clang/Format/Format.h12
-rw-r--r--lib/Format/Format.cpp8
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp11
-rw-r--r--unittests/Format/FormatTest.cpp125
4 files changed, 152 insertions, 4 deletions
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 7ec3e22ca4..4081e2131c 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -688,6 +688,18 @@ struct FormatStyle {
bool BeforeElse;
/// \brief Indent the wrapped braces themselves.
bool IndentBraces;
+ /// \brief If ``false``, 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. the `AfterFunction` brace wrapping mode is
+ /// set, and the function could/should not be put on a single line (as per
+ /// `AllowShortFunctionsOnASingleLine` and constructor formatting options).
+ /// \code
+ /// int f() vs. inf f()
+ /// {} {
+ /// }
+ /// \endcode
+ ///
+ bool SplitEmptyFunctionBody;
};
/// \brief Control of individual brace wrapping cases.
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 2ef6516e02..0eaf44d204 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -410,6 +410,7 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
+ IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody);
}
};
@@ -485,7 +486,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
return Style;
FormatStyle Expanded = Style;
Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false};
+ false, false, false, false, false, true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -498,6 +499,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterStruct = true;
Expanded.BraceWrapping.AfterUnion = true;
+ Expanded.BraceWrapping.SplitEmptyFunctionBody = false;
break;
case FormatStyle::BS_Stroustrup:
Expanded.BraceWrapping.AfterFunction = true;
@@ -517,7 +519,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
break;
case FormatStyle::BS_GNU:
Expanded.BraceWrapping = {true, true, true, true, true, true,
- true, true, true, true, true};
+ true, true, true, true, true, true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -554,7 +556,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false};
+ false, false, false, false, false, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false;
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 01504da0a2..eb8de6598e 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -186,6 +186,12 @@ private:
? 0
: Limit - TheLine->Last->TotalLength;
+ if (TheLine->Last->is(TT_FunctionLBrace) &&
+ TheLine->First == TheLine->Last &&
+ !Style.BraceWrapping.SplitEmptyFunctionBody &&
+ I[1]->First->is(tok::r_brace))
+ return tryMergeSimpleBlock(I, E, Limit);
+
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
// If necessary, change to something smarter.
bool MergeShortFunctions =
@@ -215,7 +221,10 @@ private:
Limit -= 2;
unsigned MergedLines = 0;
- if (MergeShortFunctions) {
+ if (MergeShortFunctions ||
+ (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
+ I[1]->First == I[1]->Last && I + 2 != E &&
+ I[2]->First->is(tok::r_brace))) {
MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
// If we managed to merge the block, count the function header, which is
// on a separate line.
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 64e963db4c..783fe45042 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -6239,6 +6239,35 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
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);
+
+ // Also verify behavior when BraceWrapping.AfterFunction = true
+ MergeEmptyOnly.BreakBeforeBraces = FormatStyle::BS_Custom;
+ MergeEmptyOnly.BraceWrapping.AfterFunction = true;
+ verifyFormat("int f() {}", MergeEmptyOnly);
+ verifyFormat("class C {\n"
+ " int f() {}\n"
+ "};",
+ MergeEmptyOnly);
+}
+
TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) {
FormatStyle MergeInlineOnly = getLLVMStyle();
MergeInlineOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
@@ -6250,6 +6279,101 @@ TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) {
" return 42;\n"
"}",
MergeInlineOnly);
+
+ // SFS_Inline implies SFS_Empty
+ verifyFormat("class C {\n"
+ " int f() {}\n"
+ "};",
+ MergeInlineOnly);
+ verifyFormat("int f() {}", 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_Inline implies SFS_Empty
+ verifyFormat("int f() {}", MergeInlineOnly);
+ verifyFormat("class C {\n"
+ " int f() {}\n"
+ "};",
+ MergeInlineOnly);
+}
+
+TEST_F(FormatTest, SplitEmptyFunctionBody) {
+ FormatStyle Style = getLLVMStyle();
+ Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterFunction = true;
+ Style.BraceWrapping.SplitEmptyFunctionBody = false;
+ 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);
+ 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) {
@@ -8960,6 +9084,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunctionBody);
}
#undef CHECK_PARSE_BOOL