[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-29 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From de78cfbdefd90ce2427b552c941c613f93c9fd9a Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Fri, 29 Nov 2024 21:35:06 -0600
Subject: [PATCH] BreakBeforeTemplateClose

---
 clang/docs/ClangFormatStyleOptions.rst | 23 +++
 clang/include/clang/Format/Format.h| 19 ++
 clang/lib/Format/ContinuationIndenter.cpp  | 18 +
 clang/lib/Format/Format.cpp|  1 +
 clang/unittests/Format/ConfigParseTest.cpp |  1 +
 clang/unittests/Format/FormatTest.cpp  | 79 ++
 6 files changed, 141 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:`¶ `
+  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:`¶ `
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 056fad2cc0ff8c..7a8b8ca72e494f 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2248,6 +2248,24 @@ struct FormatStyle {
   /// \version 16
   BreakBeforeInlineASMColonStyle BreakBeforeInlineASMColon;
 
+  /// If ``true``, a line break will be placed before the ``>`` in a multiline
+  /// template declaration.
+  /// \code
+  ///true:
+  ///template <
+  ///typename Foo,
+  ///typename Bar,
+  ///typename Baz
+  ///>
+  ///
+  ///false:
+  ///template <
+  ///typename Foo,
+  ///typename Bar,
+  ///typename Baz>
+  /// \endcode
+  bool BreakBeforeTemplateClose{};
+
   /// If ``true``, ternary operators will be placed after line breaks.
   /// \code
   ///true:
@@ -5184,6 +5202,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..0c77c18b3e7f48 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -382,10 +382,25 @@ 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 +1294,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const 
LineState &State) {
   FormatToken &Current = *State.NextToken;
   const auto &CurrentState = State.Stack.back();
 
+  if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose)
+return CurrentState.Indent - Style.ContinuationIndentWidth;
+
   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..3523f843d86b50 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1000,6 +1000,7 @@ template <> struct MappingTraits {
 IO.mapOptional("Bre

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-29 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From de78cfbdefd90ce2427b552c941c613f93c9fd9a Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Fri, 29 Nov 2024 21:35:06 -0600
Subject: [PATCH] BreakBeforeTemplateClose

---
 clang/docs/ClangFormatStyleOptions.rst | 23 +++
 clang/include/clang/Format/Format.h| 19 ++
 clang/lib/Format/ContinuationIndenter.cpp  | 18 +
 clang/lib/Format/Format.cpp|  1 +
 clang/unittests/Format/ConfigParseTest.cpp |  1 +
 clang/unittests/Format/FormatTest.cpp  | 79 ++
 6 files changed, 141 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:`¶ `
+  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:`¶ `
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 056fad2cc0ff8c..7a8b8ca72e494f 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2248,6 +2248,24 @@ struct FormatStyle {
   /// \version 16
   BreakBeforeInlineASMColonStyle BreakBeforeInlineASMColon;
 
+  /// If ``true``, a line break will be placed before the ``>`` in a multiline
+  /// template declaration.
+  /// \code
+  ///true:
+  ///template <
+  ///typename Foo,
+  ///typename Bar,
+  ///typename Baz
+  ///>
+  ///
+  ///false:
+  ///template <
+  ///typename Foo,
+  ///typename Bar,
+  ///typename Baz>
+  /// \endcode
+  bool BreakBeforeTemplateClose{};
+
   /// If ``true``, ternary operators will be placed after line breaks.
   /// \code
   ///true:
@@ -5184,6 +5202,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..0c77c18b3e7f48 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -382,10 +382,25 @@ 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 +1294,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const 
LineState &State) {
   FormatToken &Current = *State.NextToken;
   const auto &CurrentState = State.Stack.back();
 
+  if (Current.ClosesTemplateDeclaration && Style.BreakBeforeTemplateClose)
+return CurrentState.Indent - Style.ContinuationIndentWidth;
+
   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..3523f843d86b50 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1000,6 +1000,7 @@ template <> struct MappingTraits {
 IO.mapOptional("Bre

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-29 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH 01/10] 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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernar

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-29 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH 1/9] 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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-29 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH 1/8] 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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-29 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH 1/7] 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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-29 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH 1/5] 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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH 1/3] 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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

https://github.com/leijurv edited 
https://github.com/llvm/llvm-project/pull/118046
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

https://github.com/leijurv edited 
https://github.com/llvm/llvm-project/pull/118046
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

https://github.com/leijurv updated 
https://github.com/llvm/llvm-project/pull/118046

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH 1/2] 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:`¶ `
+  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:`¶ `
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 {
 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
 IO.mapOptional("BreakBeforeInlineASMColon",
Style.BreakBeforeInlineASMColon);
+IO.mapOptional("BreakBeforeTemplateClose",
+   Style.BreakBeforeTemplateClose);
 IO.mapOptional("BreakBeforeTernaryO

[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

github-actions[bot] wrote:



Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write 
permissions for the repository. In which case you can instead tag reviewers by 
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a 
review by "ping"ing the PR by adding a comment “Ping”. The common courtesy 
"ping" rate is once a week. Please remember that you are asking for valuable 
time from other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/118046
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] BreakBeforeTemplateClose (PR #118046)

2024-11-28 Thread via cfe-commits

https://github.com/leijurv created 
https://github.com/llvm/llvm-project/pull/118046

In clang-format, multiline templates have the `>` on the same line as the last 
parameter:

```c++
template<
typename Foo,
typename Bar,
typename Baz>
void foo() {
```

I would like to add an option to put the `>` on the next line, like this:

```c++
template<
typename Foo,
typename Bar,
typename Baz
>
void foo() {
```

My reasoning is that it rubs me the wrong way and reminds me of this style of 
braces:

```c++
if (foo()) {
bar();}
```

Most people agree this is better:

```c++
if (foo()) {
bar();
}
```

>From b9886635c250fe765bf35c6b0e785f55b0749d52 Mon Sep 17 00:00:00 2001
From: Leijurv 
Date: Thu, 28 Nov 2024 21:44:50 -0600
Subject: [PATCH] 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:`¶ `
+  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:`¶ `
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