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/6] 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/6] 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/6] 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/6] 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:

>From 9918f3eb4f190aad045030998f6138fb58c4dd76 Mon Sep 17 00:00:00 2001
From: Leijurv <leij...@gmail.com>
Date: Thu, 28 Nov 2024 22:25:28 -0600
Subject: [PATCH 5/6] init

---
 clang/include/clang/Format/Format.h   | 2 +-
 clang/unittests/Format/FormatTest.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index d9cc6959d064f6..6904fb6707b62c 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2250,7 +2250,7 @@ struct FormatStyle {
 
   /// If ``true``, a line break will be placed before the ``>`` in a multiline
   /// template declaration.
-  bool BreakBeforeTemplateClose;
+  bool BreakBeforeTemplateClose{};
 
   /// If ``true``, ternary operators will be placed after line breaks.
   /// \code
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 51c25424d7ae77..e04372502e53ad 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -11079,7 +11079,7 @@ TEST_F(FormatTest, 
WrapsTemplateDeclarationsWithComments) {
 
 TEST_F(FormatTest, BreakBeforeTemplateClose) {
   FormatStyle Style = getLLVMStyle();
-  Style.BreakTemplateDeclarations = FormatStyle::BTDS_Leave;
+  Style.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
   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 386afc00316d2b28046b5c15522951b2815dc633 Mon Sep 17 00:00:00 2001
From: Leijurv <leij...@gmail.com>
Date: Fri, 29 Nov 2024 20:55:29 -0600
Subject: [PATCH 6/6] hmm

---
 clang/unittests/Format/FormatTest.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index e04372502e53ad..75ce27095df388 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -11078,13 +11078,14 @@ TEST_F(FormatTest, 
WrapsTemplateDeclarationsWithComments) {
 }
 
 TEST_F(FormatTest, BreakBeforeTemplateClose) {
-  FormatStyle Style = getLLVMStyle();
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
   Style.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
+  Style.ColumnLimit = 0;
   verifyFormat("template <typename Foo>\nvoid foo() {}", Style);
-  verifyFormat("template <\n    typename Foo>\nvoid foo() {}", Style);
+  verifyFormat("template <\n    typename Foo,\n    typename Bar>\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);
+  verifyFormat("template <\n    typename Foo,\n    typename Bar>\nvoid foo() 
{}",
+               "template <\n    typename Foo,\n    typename Bar\n>\nvoid foo() 
{}", Style);
   Style.BreakBeforeTemplateClose = true;
   // BreakBeforeTemplateClose should NOT force multiline templates
   verifyFormat("template <typename Foo>\nvoid foo() {}", Style);
@@ -11095,11 +11096,11 @@ TEST_F(FormatTest, BreakBeforeTemplateClose) {
       "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>\nvoid foo() {}",
+               "template <\n    typename Foo>\nvoid foo() {}", Style);
   verifyFormat(
-      "template <\n    typename Foo,\n    typename Bar>\nvoid foo() {}",
       "template <\n    typename Foo,\n    typename Bar\n>\nvoid foo() {}",
+      "template <\n    typename Foo,\n    typename Bar>\nvoid foo() {}",
       Style);
 }
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to