Index: docs/ClangFormatStyleOptions.rst =================================================================== --- docs/ClangFormatStyleOptions.rst +++ docs/ClangFormatStyleOptions.rst @@ -218,7 +218,21 @@ If ``true``, ``while (true) continue;`` can be put on a single line. -**AlwaysBreakAfterDefinitionReturnType** (``DefinitionReturnTypeBreakingStyle``) +**AlwaysBreakAfterDeclarationReturnType** (``ReturnTypeBreakingStyle``) + The function declaration return type breaking style to use. + + Possible values: + + * ``DRTBS_None`` (in configuration: ``None``) + Break after return type automatically. + ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. + * ``DRTBS_All`` (in configuration: ``All``) + Always break after the return type. + * ``DRTBS_TopLevel`` (in configuration: ``TopLevel``) + Always break after the return types of top level functions. + + +**AlwaysBreakAfterDefinitionReturnType** (``ReturnTypeBreakingStyle``) The function definition return type breaking style to use. Possible values: Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -112,8 +112,9 @@ /// single line. bool AllowShortLoopsOnASingleLine; - /// \brief Different ways to break after the function definition return type. - enum DefinitionReturnTypeBreakingStyle { + /// \brief Different ways to break after the function declaration or + /// definition return type. + enum ReturnTypeBreakingStyle { /// Break after return type automatically. /// \c PenaltyReturnTypeOnItsOwnLine is taken into account. DRTBS_None, @@ -123,8 +124,11 @@ DRTBS_TopLevel, }; + /// \brief The function declaration return type breaking style to use. + ReturnTypeBreakingStyle AlwaysBreakAfterDeclarationReturnType; + /// \brief The function definition return type breaking style to use. - DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType; + ReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType; /// \brief If \c true, always break before multiline string literals. /// @@ -448,6 +452,8 @@ AllowShortIfStatementsOnASingleLine == R.AllowShortIfStatementsOnASingleLine && AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine && + AlwaysBreakAfterDeclarationReturnType == + R.AlwaysBreakAfterDeclarationReturnType && AlwaysBreakAfterDefinitionReturnType == R.AlwaysBreakAfterDefinitionReturnType && AlwaysBreakBeforeMultilineStrings == Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -127,6 +127,7 @@ // unexpected. if (Current.is(TT_FunctionDeclarationName) && Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_None && + Style.AlwaysBreakAfterDeclarationReturnType == FormatStyle::DRTBS_None && State.Column < 6) return false; Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -99,8 +99,8 @@ } }; -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { IO.enumCase(Value, "None", FormatStyle::DRTBS_None); IO.enumCase(Value, "All", FormatStyle::DRTBS_All); IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); @@ -210,6 +210,8 @@ Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); + IO.mapOptional("AlwaysBreakAfterDeclarationReturnType", + Style.AlwaysBreakAfterDeclarationReturnType); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", @@ -350,6 +352,7 @@ LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortIfStatementsOnASingleLine = false; LLVMStyle.AllowShortLoopsOnASingleLine = false; + LLVMStyle.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AlwaysBreakTemplateDeclarations = false; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -1539,15 +1539,18 @@ Current->MustBreakBefore = Current->MustBreakBefore || mustBreakBefore(Line, *Current); - if ((Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All || - (Style.AlwaysBreakAfterDefinitionReturnType == - FormatStyle::DRTBS_TopLevel && - Line.Level == 0)) && - InFunctionDecl && Current->is(TT_FunctionDeclarationName) && - !Line.Last->isOneOf(tok::semi, tok::comment)) // Only for definitions. + if (!Current->MustBreakBefore && InFunctionDecl && + Current->is(TT_FunctionDeclarationName)) { // FIXME: Line.Last points to other characters than tok::semi // and tok::lbrace. - Current->MustBreakBefore = true; + bool IsDefinition = !Line.Last->isOneOf(tok::semi, tok::comment); + FormatStyle::ReturnTypeBreakingStyle BreakStyle = + IsDefinition ? Style.AlwaysBreakAfterDefinitionReturnType + : Style.AlwaysBreakAfterDeclarationReturnType; + if ((BreakStyle == FormatStyle::DRTBS_All || + (BreakStyle == FormatStyle::DRTBS_TopLevel && Line.Level == 0))) + Current->MustBreakBefore = true; + } Current->CanBreakBefore = Current->MustBreakBefore || canBreakBefore(Line, *Current); Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -4642,6 +4642,44 @@ " \"c\";"); } +TEST_F(FormatTest, DeclarationReturnTypeBreakingStyle) { + FormatStyle Style = getLLVMStyle(); + Style.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_TopLevel; + verifyFormat("class C {\n" + " int f();\n" + "};\n" + "int\n" + "f();", + Style); + Style.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_All; + verifyFormat("class C {\n" + " int\n" + " f();\n" + "};\n" + "int\n" + "f();", + Style); + verifyFormat("const char *f(void) { return \"\"; }\n" + "const char *\n" + "bar(void);\n", + Style); + verifyFormat("template T *f(T &c) { return NULL; }\n" + "template \n" + "T *\n" + "f(T &c);\n", + Style); + Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup; + verifyFormat("const char *f(void) { return \"\"; }\n" + "const char *\n" + "bar(void);\n", + Style); + verifyFormat("template T *f(T &c) { return NULL; }\n" + "template \n" + "T *\n" + "f(T &c);\n", + Style); +} + TEST_F(FormatTest, DefinitionReturnTypeBreakingStyle) { FormatStyle Style = getLLVMStyle(); Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel; @@ -4696,6 +4734,46 @@ Style); } +TEST_F(FormatTest, AlwaysBreakAfterDeclarationAndDefinitionReturnTypeMixed) { + FormatStyle AfterType = getLLVMStyle(); + AfterType.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_None; + AfterType.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; + verifyFormat("void f(void) {\n" // No break here. + " f();\n" + " f();\n" + "}\n" + "void bar(void);\n", // No break here. + AfterType); + AfterType.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_All; + AfterType.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; + verifyFormat("void f(void) {\n" // No break here. + " f();\n" + " f();\n" + "}\n" + "void\n" + "bar(void);\n", // Break here. + AfterType); + AfterType.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_None; + AfterType.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; + verifyFormat("void\n" + "f(void) {\n" // Break here. + " f();\n" + " f();\n" + "}\n" + "void bar(void);\n", // No break here. + AfterType); + AfterType.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_All; + AfterType.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; + verifyFormat("void\n" + "f(void) {\n" // Break here. + " f();\n" + " f();\n" + "}\n" + "void\n" + "bar(void);\n", // Break here. + AfterType); +} + TEST_F(FormatTest, AlwaysBreakBeforeMultilineStrings) { FormatStyle NoBreak = getLLVMStyle(); NoBreak.AlwaysBreakBeforeMultilineStrings = false; @@ -9246,6 +9324,15 @@ FormatStyle::BS_Allman); CHECK_PARSE("BreakBeforeBraces: GNU", BreakBeforeBraces, FormatStyle::BS_GNU); + Style.AlwaysBreakAfterDeclarationReturnType = FormatStyle::DRTBS_All; + CHECK_PARSE("AlwaysBreakAfterDeclarationReturnType: None", + AlwaysBreakAfterDeclarationReturnType, FormatStyle::DRTBS_None); + CHECK_PARSE("AlwaysBreakAfterDeclarationReturnType: All", + AlwaysBreakAfterDeclarationReturnType, FormatStyle::DRTBS_All); + CHECK_PARSE("AlwaysBreakAfterDeclarationReturnType: TopLevel", + AlwaysBreakAfterDeclarationReturnType, + FormatStyle::DRTBS_TopLevel); + Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None", AlwaysBreakAfterDefinitionReturnType, FormatStyle::DRTBS_None);