https://github.com/leijurv updated https://github.com/llvm/llvm-project/pull/118046
>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001 From: Leijurv <leij...@gmail.com> Date: Thu, 28 Nov 2024 21:44:50 -0600 Subject: [PATCH 1/4] BreakBeforeTemplateClose --- clang/docs/ClangFormatStyleOptions.rst | 23 ++++++++++++++++++++++ clang/include/clang/Format/Format.h | 4 ++++ clang/lib/Format/ContinuationIndenter.cpp | 22 +++++++++++++++++++++ clang/lib/Format/Format.cpp | 2 ++ clang/unittests/Format/ConfigParseTest.cpp | 1 + clang/unittests/Format/FormatTest.cpp | 21 ++++++++++++++++++++ 6 files changed, 73 insertions(+) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index dc34094b5053a9..b40507b289049d 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3416,6 +3416,29 @@ the configuration (without a prefix: ``Auto``). + +.. _BreakBeforeTemplateClose: + +**BreakBeforeTemplateClose** (``Boolean``) :ref:`¶ <BreakBeforeTemplateClose>` + If ``true``, a line break will be placed before the ``>`` in a multiline template declaration. + + .. code-block:: c++ + + true: + template < + typename Foo, + typename Bar, + typename Baz + > + + false: + template < + typename Foo, + typename Bar, + typename Baz> + + + .. _BreakBeforeTernaryOperators: **BreakBeforeTernaryOperators** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <BreakBeforeTernaryOperators>` diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 056fad2cc0ff8c..a8478060828072 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2248,6 +2248,9 @@ struct FormatStyle { /// \version 16 BreakBeforeInlineASMColonStyle BreakBeforeInlineASMColon; + /// If ``true``, a line break will be placed before the ``>`` in a multiline template declaration. + bool BreakBeforeTemplateClose; + /// If ``true``, ternary operators will be placed after line breaks. /// \code /// true: @@ -5184,6 +5187,7 @@ struct FormatStyle { BreakBeforeBraces == R.BreakBeforeBraces && BreakBeforeConceptDeclarations == R.BreakBeforeConceptDeclarations && BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon && + BreakBeforeTemplateClose == R.BreakBeforeTemplateClose && BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && BreakBinaryOperations == R.BreakBinaryOperations && BreakConstructorInitializers == R.BreakConstructorInitializers && diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index aed86c1fb99551..5887e9cef9011d 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -382,10 +382,28 @@ bool ContinuationIndenter::canBreak(const LineState &State) { return !State.NoLineBreak && !CurrentState.NoLineBreak; } +bool isMatchingBraceOnSameLine(const FormatToken* Token) { + if (!Token->MatchingParen) { + return false; + } + const FormatToken* Matching = Token->MatchingParen; + const FormatToken* Current = Token; + while (Current && Current != Matching) { + if (Current->NewlinesBefore > 0) { + return false; + } + Current = Current->Previous; + } + return true; +} + bool ContinuationIndenter::mustBreak(const LineState &State) { const FormatToken &Current = *State.NextToken; const FormatToken &Previous = *Current.Previous; const auto &CurrentState = State.Stack.back(); + if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose) { + return !isMatchingBraceOnSameLine(State.NextToken); + } if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore && Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) { auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack); @@ -1279,6 +1297,10 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { FormatToken &Current = *State.NextToken; const auto &CurrentState = State.Stack.back(); + if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose) { + return 0; + } + if (CurrentState.IsCSharpGenericTypeConstraint && Current.isNot(TT_CSharpGenericTypeConstraint)) { return CurrentState.ColonPos + 2; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index ee52972ce66f4a..a957129bbcf440 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1000,6 +1000,8 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); IO.mapOptional("BreakBeforeInlineASMColon", Style.BreakBeforeInlineASMColon); + IO.mapOptional("BreakBeforeTemplateClose", + Style.BreakBeforeTemplateClose); IO.mapOptional("BreakBeforeTernaryOperators", Style.BreakBeforeTernaryOperators); IO.mapOptional("BreakBinaryOperations", Style.BreakBinaryOperations); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 7fc7492271668b..39f4ea49719600 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -162,6 +162,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(BinPackArguments); CHECK_PARSE_BOOL(BreakAdjacentStringLiterals); CHECK_PARSE_BOOL(BreakAfterJavaFieldAnnotations); + CHECK_PARSE_BOOL(BreakBeforeTemplateClose); CHECK_PARSE_BOOL(BreakBeforeTernaryOperators); CHECK_PARSE_BOOL(BreakStringLiterals); CHECK_PARSE_BOOL(CompactNamespaces); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 250e51b5421664..3cd2e5d292e0f5 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -11077,6 +11077,27 @@ TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) { Style); } +TEST_F(FormatTest, BreakBeforeTemplateClose) { + FromatStyle Style = getLLVMStyle(); + verifyFormat("template <typename Foo>\nvoid foo() {}", Style); + verifyFormat("template <\n typename Foo>\nvoid foo() {}", Style); + // when BreakBeforeTemplateClose is off, this line break is removed: + verifyFormat("template <\n typename Foo\n>\nvoid foo() {}", + "template <\n typename Foo>\nvoid foo() {}", Style); + Style.BreakBeforeTemplateClose = true; + // BreakBeforeTemplateClose should NOT force multiline templates + verifyFormat("template <typename Foo>\nvoid foo() {}", Style); + verifyFormat("template <typename Foo, typename Bar>\nvoid foo() {}", Style); + // it should allow a line break: + verifyFormat("template <\n typename Foo\n>\nvoid foo() {}", Style); + verifyFormat("template <\n typename Foo,\n typename Bar\n>\nvoid foo() {}", Style); + // it should add a line break if not already present: + verifyFormat("template <\n typename Foo>\nvoid foo() {}", + "template <\n typename Foo\n>\nvoid foo() {}", Style); + verifyFormat("template <\n typename Foo,\n typename Bar>\nvoid foo() {}", + "template <\n typename Foo,\n typename Bar\n>\nvoid foo() {}", Style); +} + TEST_F(FormatTest, WrapsTemplateParameters) { FormatStyle Style = getLLVMStyle(); Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; >From 08f32c688238ae7c5a007c20f84f1eb3b1b49c1b Mon Sep 17 00:00:00 2001 From: Leijurv <leij...@gmail.com> Date: Thu, 28 Nov 2024 21:59:53 -0600 Subject: [PATCH 2/4] typo --- clang/unittests/Format/FormatTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 3cd2e5d292e0f5..afadf1eb5e9137 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -11078,7 +11078,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) { } TEST_F(FormatTest, BreakBeforeTemplateClose) { - FromatStyle Style = getLLVMStyle(); + FormatStyle Style = getLLVMStyle(); verifyFormat("template <typename Foo>\nvoid foo() {}", Style); verifyFormat("template <\n typename Foo>\nvoid foo() {}", Style); // when BreakBeforeTemplateClose is off, this line break is removed: >From 16e08d6904e89f6c14d3c74ad0cd9ff39420bbc8 Mon Sep 17 00:00:00 2001 From: Leijurv <leij...@gmail.com> Date: Thu, 28 Nov 2024 22:06:37 -0600 Subject: [PATCH 3/4] format --- clang/include/clang/Format/Format.h | 3 ++- clang/lib/Format/ContinuationIndenter.cpp | 18 +++++++----------- clang/lib/Format/Format.cpp | 3 +-- clang/unittests/Format/FormatTest.cpp | 14 +++++++++----- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index a8478060828072..d9cc6959d064f6 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2248,7 +2248,8 @@ struct FormatStyle { /// \version 16 BreakBeforeInlineASMColonStyle BreakBeforeInlineASMColon; - /// If ``true``, a line break will be placed before the ``>`` in a multiline template declaration. + /// If ``true``, a line break will be placed before the ``>`` in a multiline + /// template declaration. bool BreakBeforeTemplateClose; /// If ``true``, ternary operators will be placed after line breaks. diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 5887e9cef9011d..3d78647ada0f62 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -382,16 +382,14 @@ bool ContinuationIndenter::canBreak(const LineState &State) { return !State.NoLineBreak && !CurrentState.NoLineBreak; } -bool isMatchingBraceOnSameLine(const FormatToken* Token) { - if (!Token->MatchingParen) { +bool isMatchingBraceOnSameLine(const FormatToken *Token) { + if (!Token->MatchingParen) return false; - } - const FormatToken* Matching = Token->MatchingParen; - const FormatToken* Current = Token; + const FormatToken *Matching = Token->MatchingParen; + const FormatToken *Current = Token; while (Current && Current != Matching) { - if (Current->NewlinesBefore > 0) { + if (Current->NewlinesBefore > 0) return false; - } Current = Current->Previous; } return true; @@ -401,9 +399,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { const FormatToken &Current = *State.NextToken; const FormatToken &Previous = *Current.Previous; const auto &CurrentState = State.Stack.back(); - if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose) { + if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose) return !isMatchingBraceOnSameLine(State.NextToken); - } if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore && Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) { auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack); @@ -1297,9 +1294,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { FormatToken &Current = *State.NextToken; const auto &CurrentState = State.Stack.back(); - if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose) { + if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose) return 0; - } if (CurrentState.IsCSharpGenericTypeConstraint && Current.isNot(TT_CSharpGenericTypeConstraint)) { diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index a957129bbcf440..3523f843d86b50 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1000,8 +1000,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); IO.mapOptional("BreakBeforeInlineASMColon", Style.BreakBeforeInlineASMColon); - IO.mapOptional("BreakBeforeTemplateClose", - Style.BreakBeforeTemplateClose); + IO.mapOptional("BreakBeforeTemplateClose", Style.BreakBeforeTemplateClose); IO.mapOptional("BreakBeforeTernaryOperators", Style.BreakBeforeTernaryOperators); IO.mapOptional("BreakBinaryOperations", Style.BreakBinaryOperations); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index afadf1eb5e9137..12a934d5c0fe90 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -11083,19 +11083,23 @@ TEST_F(FormatTest, BreakBeforeTemplateClose) { verifyFormat("template <\n typename Foo>\nvoid foo() {}", Style); // when BreakBeforeTemplateClose is off, this line break is removed: verifyFormat("template <\n typename Foo\n>\nvoid foo() {}", - "template <\n typename Foo>\nvoid foo() {}", Style); + "template <\n typename Foo>\nvoid foo() {}", Style); Style.BreakBeforeTemplateClose = true; // BreakBeforeTemplateClose should NOT force multiline templates verifyFormat("template <typename Foo>\nvoid foo() {}", Style); verifyFormat("template <typename Foo, typename Bar>\nvoid foo() {}", Style); // it should allow a line break: verifyFormat("template <\n typename Foo\n>\nvoid foo() {}", Style); - verifyFormat("template <\n typename Foo,\n typename Bar\n>\nvoid foo() {}", Style); + verifyFormat( + "template <\n typename Foo,\n typename Bar\n>\nvoid foo() {}", + Style); // it should add a line break if not already present: verifyFormat("template <\n typename Foo>\nvoid foo() {}", - "template <\n typename Foo\n>\nvoid foo() {}", Style); - verifyFormat("template <\n typename Foo,\n typename Bar>\nvoid foo() {}", - "template <\n typename Foo,\n typename Bar\n>\nvoid foo() {}", Style); + "template <\n typename Foo\n>\nvoid foo() {}", Style); + verifyFormat( + "template <\n typename Foo,\n typename Bar>\nvoid foo() {}", + "template <\n typename Foo,\n typename Bar\n>\nvoid foo() {}", + Style); } TEST_F(FormatTest, WrapsTemplateParameters) { >From 0e15e8a9cf308ba6a8e215c9a403e5af42a98e7f Mon Sep 17 00:00:00 2001 From: Leijurv <leij...@gmail.com> Date: Thu, 28 Nov 2024 22:15:05 -0600 Subject: [PATCH 4/4] fix --- clang/unittests/Format/FormatTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 12a934d5c0fe90..51c25424d7ae77 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -11079,6 +11079,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) { TEST_F(FormatTest, BreakBeforeTemplateClose) { FormatStyle Style = getLLVMStyle(); + Style.BreakTemplateDeclarations = FormatStyle::BTDS_Leave; verifyFormat("template <typename Foo>\nvoid foo() {}", Style); verifyFormat("template <\n typename Foo>\nvoid foo() {}", Style); // when BreakBeforeTemplateClose is off, this line break is removed: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits