diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 4dc0de3a90f26..33fd6c0286783 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1537,8 +1537,10 @@ the configuration (without a prefix: ``Auto``). Possible values: * ``RTBS_None`` (in configuration: ``None``) - Break after return type automatically. - ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. + This is **deprecated**. See ``Automatic`` below. + + * ``RTBS_Automatic`` (in configuration: ``Automatic``) + Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``. .. code-block:: c++ @@ -1547,6 +1549,22 @@ the configuration (without a prefix: ``Auto``). }; int f(); int f() { return 1; } + int + LongName::AnotherLongName(); + + * ``RTBS_ExceptShortType`` (in configuration: ``ExceptShortType``) + Same as ``Automatic`` above, except that there is no break after short + return types. + + .. code-block:: c++ + + class A { + int f() { return 0; }; + }; + int f(); + int f() { return 1; } + int LongName:: + AnotherLongName(); * ``RTBS_All`` (in configuration: ``All``) Always break after the return type. @@ -1565,6 +1583,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); * ``RTBS_TopLevel`` (in configuration: ``TopLevel``) Always break after the return types of top-level functions. @@ -1580,6 +1600,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); * ``RTBS_AllDefinitions`` (in configuration: ``AllDefinitions``) Always break after the return type of function definitions. @@ -1597,6 +1619,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); * ``RTBS_TopLevelDefinitions`` (in configuration: ``TopLevelDefinitions``) Always break after the return type of top-level definitions. @@ -1611,6 +1635,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index bc9eecd42f9eb..0e710a69b1002 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -914,16 +914,31 @@ struct FormatStyle { /// Different ways to break after the function definition or /// declaration return type. enum ReturnTypeBreakingStyle : int8_t { - /// Break after return type automatically. - /// ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. + /// This is **deprecated**. See ``Automatic`` below. + RTBS_None, + /// Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``. /// \code /// class A { /// int f() { return 0; }; /// }; /// int f(); /// int f() { return 1; } + /// int + /// LongName::AnotherLongName(); /// \endcode - RTBS_None, + RTBS_Automatic, + /// Same as ``Automatic`` above, except that there is no break after short + /// return types. + /// \code + /// class A { + /// int f() { return 0; }; + /// }; + /// int f(); + /// int f() { return 1; } + /// int LongName:: + /// AnotherLongName(); + /// \endcode + RTBS_ExceptShortType, /// Always break after the return type. /// \code /// class A { @@ -938,6 +953,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_All, /// Always break after the return types of top-level functions. @@ -951,6 +968,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_TopLevel, /// Always break after the return type of function definitions. @@ -966,6 +985,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_AllDefinitions, /// Always break after the return type of top-level definitions. @@ -978,6 +999,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_TopLevelDefinitions, }; diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index a3eb9138b2183..a3aca4a725311 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -328,9 +328,17 @@ bool ContinuationIndenter::canBreak(const LineState &State) { // Don't break after very short return types (e.g. "void") as that is often // unexpected. - if (Current.is(TT_FunctionDeclarationName) && State.Column < 6) { - if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) + if (Current.is(TT_FunctionDeclarationName)) { + if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None && + State.Column < 6) { return false; + } + + if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_ExceptShortType) { + assert(State.Column >= State.FirstIndent); + if (State.Column - State.FirstIndent < 6) + return false; + } } // If binary operators are moved to the next line (including commas for some @@ -587,7 +595,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { !State.Line->ReturnTypeWrapped && // Don't break before a C# function when no break after return type. (!Style.isCSharp() || - Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) && + Style.AlwaysBreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) && // Don't always break between a JavaScript `function` and the function // name. !Style.isJavaScript() && Previous.isNot(tok::kw_template) && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index ff326dc784783..b4718f9e96e33 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -574,6 +574,8 @@ template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { IO.enumCase(Value, "None", FormatStyle::RTBS_None); + IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic); + IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType); IO.enumCase(Value, "All", FormatStyle::RTBS_All); IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); IO.enumCase(Value, "TopLevelDefinitions", diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 25fcceb878643..73ce3860993e9 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3432,6 +3432,8 @@ bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const { switch (Style.AlwaysBreakAfterReturnType) { case FormatStyle::RTBS_None: + case FormatStyle::RTBS_Automatic: + case FormatStyle::RTBS_ExceptShortType: return false; case FormatStyle::RTBS_All: case FormatStyle::RTBS_TopLevel: diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 2a8d79359a49b..3ebf1f3861fbf 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -697,6 +697,10 @@ TEST(ConfigParseTest, ParsesConfiguration) { Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All; CHECK_PARSE("AlwaysBreakAfterReturnType: None", AlwaysBreakAfterReturnType, FormatStyle::RTBS_None); + CHECK_PARSE("AlwaysBreakAfterReturnType: Automatic", + AlwaysBreakAfterReturnType, FormatStyle::RTBS_Automatic); + CHECK_PARSE("AlwaysBreakAfterReturnType: ExceptShortType", + AlwaysBreakAfterReturnType, FormatStyle::RTBS_ExceptShortType); CHECK_PARSE("AlwaysBreakAfterReturnType: All", AlwaysBreakAfterReturnType, FormatStyle::RTBS_All); CHECK_PARSE("AlwaysBreakAfterReturnType: TopLevel", diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index e5e763edf5b5b..49d12551863e6 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -9867,14 +9867,48 @@ TEST_F(FormatTest, AlignsStringLiterals) { TEST_F(FormatTest, ReturnTypeBreakingStyle) { FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 60; + // No declarations or definitions should be moved to own line. Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; verifyFormat("class A {\n" " int f() { return 1; }\n" " int g();\n" + " long\n" + " foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaar();\n" "};\n" "int f() { return 1; }\n" - "int g();", + "int g();\n" + "int foooooooooooooooooooooooooooo::\n" + " baaaaaaaaaaaaaaaaaaaaar();", + Style); + + // It is now allowed to break after a short return type if necessary. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_Automatic; + verifyFormat("class A {\n" + " int f() { return 1; }\n" + " int g();\n" + " long\n" + " foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaar();\n" + "};\n" + "int f() { return 1; }\n" + "int g();\n" + "int\n" + "foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaaar();", + Style); + + // It now must never break after a short return type. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_ExceptShortType; + verifyFormat("class A {\n" + " int f() { return 1; }\n" + " int g();\n" + " long foooooooooooooooooooooooooooo::\n" + " baaaaaaaaaaaaaaaaaaaar();\n" + "};\n" + "int f() { return 1; }\n" + "int g();\n" + "int foooooooooooooooooooooooooooo::\n" + " baaaaaaaaaaaaaaaaaaaaar();", Style); // All declarations and definitions should have the return type moved to its @@ -9891,13 +9925,17 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) { " }\n" " int\n" " g();\n" + " long\n" + " foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaar();\n" "};\n" "int\n" "f() {\n" " return 1;\n" "}\n" "int\n" - "g();", + "g();\n" + "int\n" + "foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaaar();", Style); // Top-level definitions, and no kinds of declarations should have the @@ -9926,7 +9964,9 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) { " return 1;\n" "}\n" "int\n" - "g();", + "g();\n" + "int\n" + "foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaaar();", Style); // All definitions should have the return type moved to its own line, but no