Author: zturner Date: Fri Dec 18 16:20:15 2015 New Revision: 256046 URL: http://llvm.org/viewvc/llvm-project?rev=256046&view=rev Log: Support AlwaysBreakAfterReturnType
This changes the behavior of AlwaysBreakAfterDeclarationReturnType so that it supports breaking after declarations, definitions, or both. Differential Revision: http://reviews.llvm.org/D10370 Reviewed By: Daniel Jasper Modified: cfe/trunk/docs/ClangFormatStyleOptions.rst cfe/trunk/include/clang/Format/Format.h cfe/trunk/lib/Format/ContinuationIndenter.cpp cfe/trunk/lib/Format/Format.cpp cfe/trunk/lib/Format/TokenAnnotator.cpp cfe/trunk/lib/Format/TokenAnnotator.h cfe/trunk/unittests/Format/FormatTest.cpp Modified: cfe/trunk/docs/ClangFormatStyleOptions.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ClangFormatStyleOptions.rst?rev=256046&r1=256045&r2=256046&view=diff ============================================================================== --- cfe/trunk/docs/ClangFormatStyleOptions.rst (original) +++ cfe/trunk/docs/ClangFormatStyleOptions.rst Fri Dec 18 16:20:15 2015 @@ -254,7 +254,8 @@ the configuration (without a prefix: ``A single line. **AlwaysBreakAfterDefinitionReturnType** (``DefinitionReturnTypeBreakingStyle``) - The function definition return type breaking style to use. + The function definition return type breaking style to use. This + option is deprecated and is retained for backwards compatibility. Possible values: @@ -264,7 +265,25 @@ the configuration (without a prefix: ``A * ``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. + Always break after the return types of top-level functions. + + +**AlwaysBreakAfterReturnType** (``ReturnTypeBreakingStyle``) + The function declaration return type breaking style to use. + + Possible values: + + * ``RTBS_None`` (in configuration: ``None``) + Break after return type automatically. + ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. + * ``RTBS_All`` (in configuration: ``All``) + Always break after the return type. + * ``RTBS_TopLevel`` (in configuration: ``TopLevel``) + Always break after the return types of top-level functions. + * ``RTBS_AllDefinitions`` (in configuration: ``AllDefinitions``) + Always break after the return type of function definitions. + * ``RTBS_TopLevelDefinitions`` (in configuration: ``TopLevelDefinitions``) + Always break after the return type of top-level definitions. **AlwaysBreakBeforeMultilineStrings** (``bool``) Modified: cfe/trunk/include/clang/Format/Format.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=256046&r1=256045&r2=256046&view=diff ============================================================================== --- cfe/trunk/include/clang/Format/Format.h (original) +++ cfe/trunk/include/clang/Format/Format.h Fri Dec 18 16:20:15 2015 @@ -156,13 +156,33 @@ struct FormatStyle { DRTBS_None, /// Always break after the return type. DRTBS_All, - /// Always break after the return types of top level functions. + /// Always break after the return types of top-level functions. DRTBS_TopLevel, }; - /// \brief The function definition return type breaking style to use. + /// \brief Different ways to break after the function definition or + /// declaration return type. + enum ReturnTypeBreakingStyle { + /// Break after return type automatically. + /// \c PenaltyReturnTypeOnItsOwnLine is taken into account. + RTBS_None, + /// Always break after the return type. + RTBS_All, + /// Always break after the return types of top-level functions. + RTBS_TopLevel, + /// Always break after the return type of function definitions. + RTBS_AllDefinitions, + /// Always break after the return type of top-level definitions. + RTBS_TopLevelDefinitions, + }; + + /// \brief The function definition return type breaking style to use. This + /// option is deprecated and is retained for backwards compatibility. DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType; + /// \brief The function declaration return type breaking style to use. + ReturnTypeBreakingStyle AlwaysBreakAfterReturnType; + /// \brief If \c true, always break before multiline string literals. /// /// This flag is mean to make cases where there are multiple multiline strings @@ -584,8 +604,7 @@ struct FormatStyle { AllowShortIfStatementsOnASingleLine == R.AllowShortIfStatementsOnASingleLine && AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine && - AlwaysBreakAfterDefinitionReturnType == - R.AlwaysBreakAfterDefinitionReturnType && + AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType && AlwaysBreakBeforeMultilineStrings == R.AlwaysBreakBeforeMultilineStrings && AlwaysBreakTemplateDeclarations == Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=256046&r1=256045&r2=256046&view=diff ============================================================================== --- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original) +++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Fri Dec 18 16:20:15 2015 @@ -125,10 +125,10 @@ bool ContinuationIndenter::canBreak(cons // Don't break after very short return types (e.g. "void") as that is often // unexpected. - if (Current.is(TT_FunctionDeclarationName) && - Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_None && - State.Column < 6) - return false; + if (Current.is(TT_FunctionDeclarationName) && State.Column < 6) { + if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) + return false; + } return !State.Stack.back().NoLineBreak; } Modified: cfe/trunk/lib/Format/Format.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=256046&r1=256045&r2=256046&view=diff ============================================================================== --- cfe/trunk/lib/Format/Format.cpp (original) +++ cfe/trunk/lib/Format/Format.cpp Fri Dec 18 16:20:15 2015 @@ -105,6 +105,18 @@ template <> struct ScalarEnumerationTrai }; template <> +struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { + static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::RTBS_None); + IO.enumCase(Value, "All", FormatStyle::RTBS_All); + IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); + IO.enumCase(Value, "TopLevelDefinitions", + FormatStyle::RTBS_TopLevelDefinitions); + IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { static void enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { @@ -233,6 +245,21 @@ template <> struct MappingTraits<FormatS Style.AllowShortLoopsOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); + IO.mapOptional("AlwaysBreakAfterReturnType", + Style.AlwaysBreakAfterReturnType); + // If AlwaysBreakAfterDefinitionReturnType was specified but + // AlwaysBreakAfterReturnType was not, initialize the latter from the + // former for backwards compatibility. + if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && + Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) { + if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All) + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; + else if (Style.AlwaysBreakAfterDefinitionReturnType == + FormatStyle::DRTBS_TopLevel) + Style.AlwaysBreakAfterReturnType = + FormatStyle::RTBS_TopLevelDefinitions; + } + IO.mapOptional("AlwaysBreakBeforeMultilineStrings", Style.AlwaysBreakBeforeMultilineStrings); IO.mapOptional("AlwaysBreakTemplateDeclarations", @@ -449,6 +476,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortIfStatementsOnASingleLine = false; LLVMStyle.AllowShortLoopsOnASingleLine = false; + LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AlwaysBreakTemplateDeclarations = false; @@ -585,6 +613,8 @@ FormatStyle getMozillaStyle() { FormatStyle MozillaStyle = getLLVMStyle(); MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + MozillaStyle.AlwaysBreakAfterReturnType = + FormatStyle::RTBS_TopLevelDefinitions; MozillaStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel; MozillaStyle.AlwaysBreakTemplateDeclarations = true; @@ -624,6 +654,7 @@ FormatStyle getWebKitStyle() { FormatStyle getGNUStyle() { FormatStyle Style = getLLVMStyle(); Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; Style.BreakBeforeBraces = FormatStyle::BS_GNU; Style.BreakBeforeTernaryOperators = true; Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=256046&r1=256045&r2=256046&view=diff ============================================================================== --- cfe/trunk/lib/Format/TokenAnnotator.cpp (original) +++ cfe/trunk/lib/Format/TokenAnnotator.cpp Fri Dec 18 16:20:15 2015 @@ -1562,6 +1562,29 @@ static bool isFunctionDeclarationName(co return false; } +bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const { + assert(Line.MightBeFunctionDecl); + + if ((Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_TopLevel || + Style.AlwaysBreakAfterReturnType == + FormatStyle::RTBS_TopLevelDefinitions) && + Line.Level > 0) + return false; + + switch (Style.AlwaysBreakAfterReturnType) { + case FormatStyle::RTBS_None: + return false; + case FormatStyle::RTBS_All: + case FormatStyle::RTBS_TopLevel: + return true; + case FormatStyle::RTBS_AllDefinitions: + case FormatStyle::RTBS_TopLevelDefinitions: + return Line.mightBeFunctionDefinition(); + } + + return false; +} + void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) { for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(), E = Line.Children.end(); @@ -1613,15 +1636,9 @@ void TokenAnnotator::calculateFormatting 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. - // FIXME: Line.Last points to other characters than tok::semi - // and tok::lbrace. - Current->MustBreakBefore = true; + if (!Current->MustBreakBefore && InFunctionDecl && + Current->is(TT_FunctionDeclarationName)) + Current->MustBreakBefore = mustBreakForReturnType(Line); Current->CanBreakBefore = Current->MustBreakBefore || canBreakBefore(Line, *Current); Modified: cfe/trunk/lib/Format/TokenAnnotator.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.h?rev=256046&r1=256045&r2=256046&view=diff ============================================================================== --- cfe/trunk/lib/Format/TokenAnnotator.h (original) +++ cfe/trunk/lib/Format/TokenAnnotator.h Fri Dec 18 16:20:15 2015 @@ -86,6 +86,15 @@ public: return startsWith(First, Tokens...); } + /// \c true if this line looks like a function definition instead of a + /// function declaration. Asserts MightBeFunctionDecl. + bool mightBeFunctionDefinition() const { + assert(MightBeFunctionDecl); + // FIXME: Line.Last points to other characters than tok::semi + // and tok::lbrace. + return !Last->isOneOf(tok::semi, tok::comment); + } + FormatToken *First; FormatToken *Last; @@ -156,6 +165,8 @@ private: bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right); + bool mustBreakForReturnType(const AnnotatedLine &Line) const; + void printDebugInfo(const AnnotatedLine &Line); void calculateUnbreakableTailLengths(AnnotatedLine &Line); Modified: cfe/trunk/unittests/Format/FormatTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=256046&r1=256045&r2=256046&view=diff ============================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp (original) +++ cfe/trunk/unittests/Format/FormatTest.cpp Fri Dec 18 16:20:15 2015 @@ -4732,28 +4732,82 @@ TEST_F(FormatTest, AlignsStringLiterals) " \"c\";"); } -TEST_F(FormatTest, DefinitionReturnTypeBreakingStyle) { +TEST_F(FormatTest, ReturnTypeBreakingStyle) { FormatStyle Style = getLLVMStyle(); - Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel; - verifyFormat("class C {\n" + // 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" + "};\n" + "int f() { return 1; }\n" + "int g();\n", + Style); + + // All declarations and definitions should have the return type moved to its + // own + // line. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All; + verifyFormat("class E {\n" + " int\n" + " f() {\n" + " return 1;\n" + " }\n" + " int\n" + " g();\n" "};\n" "int\n" "f() {\n" " return 1;\n" - "}", + "}\n" + "int\n" + "g();\n", Style); - Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; + + // Top-level definitions, and no kinds of declarations should have the + // return type moved to its own line. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions; + verifyFormat("class B {\n" + " int f() { return 1; }\n" + " int g();\n" + "};\n" + "int\n" + "f() {\n" + " return 1;\n" + "}\n" + "int g();\n", + Style); + + // Top-level definitions and declarations should have the return type moved + // to its own line. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; verifyFormat("class C {\n" + " int f() { return 1; }\n" + " int g();\n" + "};\n" + "int\n" + "f() {\n" + " return 1;\n" + "}\n" + "int\n" + "g();\n", + Style); + + // All definitions should have the return type moved to its own line, but no + // kinds of declarations. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; + verifyFormat("class D {\n" " int\n" " f() {\n" " return 1;\n" " }\n" + " int g();\n" "};\n" "int\n" "f() {\n" " return 1;\n" - "}", + "}\n" + "int g();\n", Style); verifyFormat("const char *\n" "f(void) {\n" // Break here. @@ -5688,7 +5742,7 @@ TEST_F(FormatTest, UnderstandsAttributes verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa __attribute__((unused))\n" "aaaaaaaaaaaaaaaaaaaaaaa(int i);"); FormatStyle AfterType = getLLVMStyle(); - AfterType.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; + AfterType.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; verifyFormat("__attribute__((nodebug)) void\n" "foo() {}\n", AfterType); @@ -9829,6 +9883,19 @@ TEST_F(FormatTest, ParsesConfiguration) CHECK_PARSE("BreakBeforeBraces: Custom", BreakBeforeBraces, FormatStyle::BS_Custom); + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All; + CHECK_PARSE("AlwaysBreakAfterReturnType: None", AlwaysBreakAfterReturnType, + FormatStyle::RTBS_None); + CHECK_PARSE("AlwaysBreakAfterReturnType: All", AlwaysBreakAfterReturnType, + FormatStyle::RTBS_All); + CHECK_PARSE("AlwaysBreakAfterReturnType: TopLevel", + AlwaysBreakAfterReturnType, FormatStyle::DRTBS_TopLevel); + CHECK_PARSE("AlwaysBreakAfterReturnType: AllDefinitions", + AlwaysBreakAfterReturnType, FormatStyle::RTBS_AllDefinitions); + CHECK_PARSE("AlwaysBreakAfterReturnType: TopLevelDefinitions", + AlwaysBreakAfterReturnType, + FormatStyle::RTBS_TopLevelDefinitions); + Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None", AlwaysBreakAfterDefinitionReturnType, FormatStyle::DRTBS_None); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits