[clang] 9c422ab - [clang-format] Add option for aligning requires clause body

2022-10-21 Thread Emilia Dreamer via cfe-commits

Author: Danil Sidoruk
Date: 2022-10-21T10:42:45+03:00
New Revision: 9c422ab7ce82ec13155629f1e5e4e11d608fe1de

URL: 
https://github.com/llvm/llvm-project/commit/9c422ab7ce82ec13155629f1e5e4e11d608fe1de
DIFF: 
https://github.com/llvm/llvm-project/commit/9c422ab7ce82ec13155629f1e5e4e11d608fe1de.diff

LOG: [clang-format] Add option for aligning requires clause body

Adds an option whether requires clause body should be aligned with
the `requires` keyword.
This option is now the default, both without configuration and in LLVM
style.

Fixes https://github.com/llvm/llvm-project/issues/56283

Differential Revision: https://reviews.llvm.org/D129443

Co-authored-by: Emilia Dreamer 

Added: 


Modified: 
clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Format/Format.h
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index cdbc23ae43eb8..b52cf49ef5636 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3861,6 +3861,35 @@ the configuration (without a prefix: ``Auto``).
 
 
 
+**RequiresExpressionIndentation** (``RequiresExpressionIndentationKind``) 
:versionbadge:`clang-format 16`
+  The indentation used for requires expression bodies.
+
+  Possible values:
+
+  * ``REI_OuterScope`` (in configuration: ``OuterScope``)
+Align requires expression body relative to the indentation level of the
+outer scope the requires expression resides in.
+This is the default.
+
+.. code-block:: c++
+
+   template 
+   concept C = requires(T t) {
+ ...
+   }
+
+  * ``REI_Keyword`` (in configuration: ``Keyword``)
+Align requires expression body relative to the `requires` keyword.
+
+.. code-block:: c++
+
+   template 
+   concept C = requires(T t) {
+ ...
+   }
+
+
+
 **SeparateDefinitionBlocks** (``SeparateDefinitionStyle``) 
:versionbadge:`clang-format 14`
   Specifies the use of empty lines to separate definition blocks, including
   classes, structs, enums, and functions.

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8198d62bc8d5f..e87a4eea552df 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -629,7 +629,10 @@ AST Matchers
 
 clang-format
 
-- Add `RemoveSemicolon` option for removing `;` after a non-empty function 
definition.
+- Add ``RemoveSemicolon`` option for removing ``;`` after a non-empty function 
definition.
+- Add ``RequiresExpressionIndentation`` option for configuring the alignment 
of requires-expressions.
+  The default value of this option is ``OuterScope``, which 
diff ers in behavior from clang-format 15.
+  To match the default behavior of clang-format 15, use the ``Keyword`` value.
 
 clang-extdef-mapping
 

diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 7c1721064727c..3205b502ac195 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3153,6 +3153,32 @@ struct FormatStyle {
   /// \version 15
   RequiresClausePositionStyle RequiresClausePosition;
 
+  /// Indentation logic for requires expression bodies.
+  enum RequiresExpressionIndentationKind : int8_t {
+/// Align requires expression body relative to the indentation level of the
+/// outer scope the requires expression resides in.
+/// This is the default.
+/// \code
+///template 
+///concept C = requires(T t) {
+///  ...
+///}
+/// \endcode
+REI_OuterScope,
+/// Align requires expression body relative to the `requires` keyword.
+/// \code
+///template 
+///concept C = requires(T t) {
+///  ...
+///}
+/// \endcode
+REI_Keyword,
+  };
+
+  /// The indentation used for requires expression bodies.
+  /// \version 16
+  RequiresExpressionIndentationKind RequiresExpressionIndentation;
+
   /// \brief The style if definition blocks should be separated.
   enum SeparateDefinitionStyle : int8_t {
 /// Leave definition blocks as they are.
@@ -3988,6 +4014,7 @@ struct FormatStyle {
RemoveBracesLLVM == R.RemoveBracesLLVM &&
RemoveSemicolon == R.RemoveSemicolon &&
RequiresClausePosition == R.RequiresClausePosition &&
+   RequiresExpressionIndentation == R.RequiresExpressionIndentation &&
SeparateDefinitionBlocks == R.SeparateDefinitionBlocks &&
ShortNamespaceLines == R.ShortNamespaceLines &&
SortIncludes == R.SortIncludes &&

diff  --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 00a9

[clang] dce5bb9 - [clang-format] Correctly annotate UDLs as OverloadedOperator

2022-10-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-10-25T20:11:52+03:00
New Revision: dce5bb9a6f89b18366c6f27aeb435a6e48e85639

URL: 
https://github.com/llvm/llvm-project/commit/dce5bb9a6f89b18366c6f27aeb435a6e48e85639
DIFF: 
https://github.com/llvm/llvm-project/commit/dce5bb9a6f89b18366c6f27aeb435a6e48e85639.diff

LOG: [clang-format] Correctly annotate UDLs as OverloadedOperator

While the opening parenthesis of an user-defined literal operator was
correctly annotated as OverloadedOperatorLParen, the "" and its suffix
wasn't annotated as OverloadedOperator.

Fixes https://github.com/llvm/llvm-project/issues/58035

Differential Revision: https://reviews.llvm.org/D134853

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index da6e21c488140..4901c5ce71066 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1177,13 +1177,17 @@ class AnnotatingParser {
 if (CurrentToken->isOneOf(tok::star, tok::amp))
   CurrentToken->setType(TT_PointerOrReference);
 consumeToken();
-if (CurrentToken && CurrentToken->is(tok::comma) &&
+if (!CurrentToken)
+  continue;
+if (CurrentToken->is(tok::comma) &&
 CurrentToken->Previous->isNot(tok::kw_operator)) {
   break;
 }
-if (CurrentToken && CurrentToken->Previous->isOneOf(
-TT_BinaryOperator, TT_UnaryOperator, 
tok::comma,
-tok::star, tok::arrow, tok::amp, tok::ampamp)) 
{
+if (CurrentToken->Previous->isOneOf(TT_BinaryOperator, 
TT_UnaryOperator,
+tok::comma, tok::star, tok::arrow,
+tok::amp, tok::ampamp) ||
+// User defined literal.
+CurrentToken->Previous->TokenText.startswith("\"\"")) {
   CurrentToken->Previous->setType(TT_OverloadedOperator);
 }
   }
@@ -2114,6 +2118,9 @@ class AnnotatingParser {
 if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
   return false;
 
+if (Tok.MatchingParen->is(TT_OverloadedOperatorLParen))
+  return false;
+
 FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
 if (LeftOfParens) {
   // If there is a closing parenthesis left of the current

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 00803cd3a230f..fa26ba0954026 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -10153,6 +10153,14 @@ TEST_F(FormatTest, UnderstandsOverloadedOperators) {
   // verifyFormat("void f() { operator*(a & a); }");
   // verifyFormat("void f() { operator&(a, b * b); }");
 
+  verifyFormat("void f() { return operator()(x) * b; }");
+  verifyFormat("void f() { return operator[](x) * b; }");
+  verifyFormat("void f() { return operator\"\"_a(x) * b; }");
+  verifyFormat("void f() { return operator\"\" _a(x) * b; }");
+  verifyFormat("void f() { return operator\"\"s(x) * b; }");
+  verifyFormat("void f() { return operator\"\" s(x) * b; }");
+  verifyFormat("void f() { return operator\"\"if(x) * b; }");
+
   verifyFormat("::operator delete(foo);");
   verifyFormat("::operator new(n * sizeof(foo));");
   verifyFormat("foo() { ::operator delete(foo); }");

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 999feca0913d6..b4e27d35bc369 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -390,6 +390,55 @@ TEST_F(TokenAnnotatorTest, 
UnderstandsFunctionRefQualifiers) {
   EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference);
 }
 
+TEST_F(TokenAnnotatorTest, UnderstandsOverloadedOperators) {
+  auto Tokens = annotate("x.operator+()");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::plus, TT_OverloadedOperator);
+  EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
+  Tokens = annotate("x.operator=()");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::equal, TT_OverloadedOperator);
+  EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
+  Tokens = annotate("x.operator+=()");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::plusequal, TT_OverloadedOperator);
+  EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
+  Tokens = annotate("x.operator,()");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::comma, TT_OverloadedOperator);
+  EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
+  Tokens = annotate("x.opera

[clang] 0bf63f0 - [clang-format] Disallow trailing return arrows to be operators

2022-09-18 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-09-19T04:04:31+03:00
New Revision: 0bf63f0d1b6b860a7134d668d3a28104c5c9afc1

URL: 
https://github.com/llvm/llvm-project/commit/0bf63f0d1b6b860a7134d668d3a28104c5c9afc1
DIFF: 
https://github.com/llvm/llvm-project/commit/0bf63f0d1b6b860a7134d668d3a28104c5c9afc1.diff

LOG: [clang-format] Disallow trailing return arrows to be operators

In the following construction:
`template  requires Foo || Bar auto func() -> int;`

The `->` of the trailing return type was actually considered as an
operator as part of the binary operation in the requires clause, with
the precedence level of `PrecedenceArrowAndPeriod`, leading to fake
parens being inserted in strange locations, that would never be closed.

Fixes one part of https://github.com/llvm/llvm-project/issues/56213
(the rest will probably be in a separate patch)

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D134049

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index d18adc308efb0..a81bbb99f5d9e 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2611,8 +2611,10 @@ class ExpressionParser {
   }
   if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
 return Current->getPrecedence();
-  if (Current->isOneOf(tok::period, tok::arrow))
+  if (Current->isOneOf(tok::period, tok::arrow) &&
+  Current->isNot(TT_TrailingReturnArrow)) {
 return PrecedenceArrowAndPeriod;
+  }
   if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
   Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
Keywords.kw_throws)) {

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 1fe8bece722c4..f3007f85e91b0 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -440,6 +440,15 @@ TEST_F(TokenAnnotatorTest, 
UnderstandsRequiresClausesAndConcepts) {
   ASSERT_EQ(Tokens.size(), 18u) << Tokens;
   EXPECT_TOKEN(Tokens[11], tok::kw_requires, TT_RequiresClause);
 
+  Tokens = annotate("template \n"
+"requires Bar || Baz\n"
+"auto foo(T) -> int;");
+  ASSERT_EQ(Tokens.size(), 24u) << Tokens;
+  EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);
+  EXPECT_EQ(Tokens[11]->FakeLParens.size(), 0u);
+  EXPECT_TRUE(Tokens[14]->ClosesRequiresClause);
+  EXPECT_TOKEN(Tokens[20], tok::arrow, TT_TrailingReturnArrow);
+
   Tokens = annotate("template \n"
 "struct S {\n"
 "  void foo() const requires Bar;\n"



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


[clang] 8dab452 - [clang-format] Disallow requires clauses to become function declarations

2022-09-18 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-09-19T04:04:31+03:00
New Revision: 8dab452740007e03c963b349e716068eac2b25a0

URL: 
https://github.com/llvm/llvm-project/commit/8dab452740007e03c963b349e716068eac2b25a0
DIFF: 
https://github.com/llvm/llvm-project/commit/8dab452740007e03c963b349e716068eac2b25a0.diff

LOG: [clang-format] Disallow requires clauses to become function declarations

There already exists logic to disallow requires *expressions* to be
treated as function declarations, but this expands it to include
requires *clauses*, when they happen to also be parenthesized.

Previously, in the following case:

```
template 
  requires(Foo)
T foo();
```

The line with the requires clause was actually being considered as the
line with the function declaration due to the parentheses, and the
*real* function declaration on the next line became a trailing
annotation

(Together with https://reviews.llvm.org/D134049) Fixes 
https://github.com/llvm/llvm-project/issues/56213

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D134052

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index a81bbb99f5d9e..e530120fa4454 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1110,7 +1110,7 @@ class AnnotatingParser {
   !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
   !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen) 
&&
   (!Tok->Previous ||
-   !Tok->Previous->isOneOf(tok::kw___attribute,
+   !Tok->Previous->isOneOf(tok::kw___attribute, TT_RequiresClause,
TT_LeadingJavaAnnotation))) {
 Line.MightBeFunctionDecl = true;
   }

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index f3007f85e91b0..d27c176415c83 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -737,6 +737,16 @@ TEST_F(TokenAnnotatorTest, 
RequiresDoesNotChangeParsingOfTheRest) {
   BaseTokenCount = 26;
   TestRequires(__LINE__);
 
+  BaseCode = "template\n"
+ "T foo();";
+  ConstrainedCode = "template\n"
+"  requires(Foo)\n"
+"T foo();";
+  BaseTokenCount = 11;
+  RequiresTokenCount = 7;
+  PrefixTokenCount = 5;
+  TestRequires(__LINE__);
+
   BaseCode = "template\n"
  "Bar(T) -> Bar;";
   ConstrainedCode = "template\n"



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


[clang] 39e6077 - [clang-format] Look ahead before consuming `bool` in requires clause.

2022-09-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-09-25T20:30:21+03:00
New Revision: 39e6077d97238ec13c9ed1b9dbae1e6408e5aba3

URL: 
https://github.com/llvm/llvm-project/commit/39e6077d97238ec13c9ed1b9dbae1e6408e5aba3
DIFF: 
https://github.com/llvm/llvm-project/commit/39e6077d97238ec13c9ed1b9dbae1e6408e5aba3.diff

LOG: [clang-format] Look ahead before consuming `bool` in requires clause.

The comment handling the bool case says:
"bool is only allowed if it is directly followed by a paren for a cast"

This change more closely follows this directive by looking ahead for
the paren before consuming the bool keyword itself. Without a following
paren, the bool would be part of something else, such as a return type
for a function declaration

Fixes https://github.com/llvm/llvm-project/issues/57538

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D134325

Added: 


Modified: 
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 87a0e43f8730e..3919bc0ef0b35 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -3530,9 +3530,9 @@ void UnwrappedLineParser::parseConstraintExpression() {
   // concept C = bool(...);
   // and bool is the only type, all other types as cast must be inside a
   // cast to bool an thus are handled by the other cases.
-  nextToken();
-  if (FormatTok->isNot(tok::l_paren))
+  if (Tokens->peekNextToken()->isNot(tok::l_paren))
 return;
+  nextToken();
   parseParens();
   break;
 

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 6bc295c41798c..c8de8a2a2abe4 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -449,6 +449,14 @@ TEST_F(TokenAnnotatorTest, 
UnderstandsRequiresClausesAndConcepts) {
   EXPECT_TRUE(Tokens[14]->ClosesRequiresClause);
   EXPECT_TOKEN(Tokens[20], tok::arrow, TT_TrailingReturnArrow);
 
+  Tokens = annotate("template \n"
+"requires Bar\n"
+"bool foo(T) { return false; }");
+  ASSERT_EQ(Tokens.size(), 21u) << Tokens;
+  EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);
+  EXPECT_TRUE(Tokens[9]->ClosesRequiresClause);
+  EXPECT_TOKEN(Tokens[11], tok::identifier, TT_FunctionDeclarationName);
+
   Tokens = annotate("template \n"
 "struct S {\n"
 "  void foo() const requires Bar;\n"



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


[clang] 7847225 - [clang-format] Correctly annotate static and consteval lambdas

2022-09-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-09-25T20:29:55+03:00
New Revision: 7847225576d571fb7101463de56330e1f0e84856

URL: 
https://github.com/llvm/llvm-project/commit/7847225576d571fb7101463de56330e1f0e84856
DIFF: 
https://github.com/llvm/llvm-project/commit/7847225576d571fb7101463de56330e1f0e84856.diff

LOG: [clang-format] Correctly annotate static and consteval lambdas

`P1169` "static operator()" (https://wg21.link/P1169) is accepted to
C++23 and while clang itself doesn't exactly support it yet,
clang-format could quite easily.

This simply allows the keyword `static` to be a part of lambdas as
specified by the addition to [expr.prim.lambda.general]

While adding this, I noticed `consteval` lambdas also aren't handled,
so that keyword is now allowed to be a part of lambdas as well

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D134587

Added: 


Modified: 
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 4fd4fd4f7c27c..87a0e43f8730e 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2230,6 +2230,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
 case tok::star:
 case tok::kw_const:
 case tok::kw_constexpr:
+case tok::kw_consteval:
 case tok::comma:
 case tok::greater:
 case tok::identifier:
@@ -2237,6 +2238,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
 case tok::coloncolon:
 case tok::kw_mutable:
 case tok::kw_noexcept:
+case tok::kw_static:
   nextToken();
   break;
 // Specialization of a template with an integer parameter can contain

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index d27c176415c83..6bc295c41798c 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -837,6 +837,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
   EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
   EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);
 
+  Tokens = annotate("[]() consteval {}");
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
+  EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);
+
+  Tokens = annotate("[]() mutable {}");
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
+  EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);
+
+  Tokens = annotate("[]() static {}");
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
+  EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);
+
   Tokens = annotate("[]() -> auto {}");
   ASSERT_EQ(Tokens.size(), 9u) << Tokens;
   EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);



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


[clang] 1fa115b - [clang-format] Correctly indent closing brace of compound requires

2022-09-30 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-10-01T08:16:57+03:00
New Revision: 1fa115b569797f64988f3d8ddd8baa05574aafa3

URL: 
https://github.com/llvm/llvm-project/commit/1fa115b569797f64988f3d8ddd8baa05574aafa3
DIFF: 
https://github.com/llvm/llvm-project/commit/1fa115b569797f64988f3d8ddd8baa05574aafa3.diff

LOG: [clang-format] Correctly indent closing brace of compound requires

When a compound requirement is too long to fit onto a single line, the
braces are split apart onto separate lines, and the contained expression
is indented. However, this indentation would also apply to the closing
brace and the trailing return type requirement thereof.
This was because the indentation level was being restored after all
trailing things were already read

With this change, the initial level of the opening brace is set before
attempting to read any trailing return type requirements

Fixes https://github.com/llvm/llvm-project/issues/57108

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D134626

Added: 


Modified: 
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index ead3f7f1c7d46..f39c107e5269e 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -964,6 +964,8 @@ FormatToken *UnwrappedLineParser::parseBlock(
   if (MacroBlock && FormatTok->is(tok::l_paren))
 parseParens();
 
+  Line->Level = InitialLevel;
+
   if (FormatTok->is(tok::kw_noexcept)) {
 // A noexcept in a requires expression.
 nextToken();
@@ -979,8 +981,6 @@ FormatToken *UnwrappedLineParser::parseBlock(
   if (MunchSemi && FormatTok->is(tok::semi))
 nextToken();
 
-  Line->Level = InitialLevel;
-
   if (PPStartHash == PPEndHash) {
 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
 if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 9a1396b196ffe..fd567befec974 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -24510,6 +24510,16 @@ TEST_F(FormatTest, Concepts) {
   "  { x * 1 } -> std::convertible_to;\n"
   "};");
 
+  verifyFormat("template \n"
+   "concept C = requires(T x) {\n"
+   "  {\n"
+   "long_long_long_function_call(1, 2, 3, 4, 5)\n"
+   "  } -> long_long_concept_name;\n"
+   "  {\n"
+   "long_long_long_function_call(1, 2, 3, 4, 5)\n"
+   "  } noexcept -> long_long_concept_name;\n"
+   "};");
+
   verifyFormat(
   "template \n"
   "concept Swappable = requires(T &&t, U &&u) {\n"



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


[clang-tools-extra] 2d149d1 - [clang-tidy] Fix crashes on `if consteval` in readability checks

2022-10-05 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-10-05T09:38:05+03:00
New Revision: 2d149d17f069e671e064a000cb038590f4fc5303

URL: 
https://github.com/llvm/llvm-project/commit/2d149d17f069e671e064a000cb038590f4fc5303
DIFF: 
https://github.com/llvm/llvm-project/commit/2d149d17f069e671e064a000cb038590f4fc5303.diff

LOG: [clang-tidy] Fix crashes on `if consteval` in readability checks

The `readability-braces-around-statements` check tries to look at the
closing parens of the if condition to determine where to insert braces,
however, "consteval if" statements don't have a condition, and always
have braces regardless, so the skip can be checked.

The `readability-simplify-boolean-expr` check looks at the condition
of the if statement to determine what could be simplified, but as
"consteval if" statements do not have a condition that could be
simplified, they can also be skipped here.

There may still be more checks that try to look at the conditions of
`if`s that aren't included here

Fixes https://github.com/llvm/llvm-project/issues/57568

Reviewed By: njames93, aaron.ballman

Differential Revision: https://reviews.llvm.org/D133413

Added: 

clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements-consteval-if.cpp

clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-cxx23.cpp

Modified: 
clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
index 07e962a07e843..d6f4d920b5e93 100644
--- a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
@@ -131,6 +131,10 @@ void BracesAroundStatementsCheck::check(
   return;
 checkStmt(Result, S->getBody(), StartLoc);
   } else if (const auto *S = Result.Nodes.getNodeAs("if")) {
+// "if consteval" always has braces.
+if (S->isConsteval())
+  return;
+
 SourceLocation StartLoc = findRParenLoc(S, SM, Context);
 if (StartLoc.isInvalid())
   return;

diff  --git 
a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
index afb4a1044a79a..9369f73371223 100644
--- a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
@@ -354,8 +354,9 @@ class SimplifyBooleanExprCheck::Visitor : public 
RecursiveASTVisitor {
   }
 
   bool VisitIfStmt(IfStmt *If) {
-// Skip any if's that have a condition var or an init statement.
-if (If->hasInitStorage() || If->hasVarStorage())
+// Skip any if's that have a condition var or an init statement, or are
+// "if consteval" statements.
+if (If->hasInitStorage() || If->hasVarStorage() || If->isConsteval())
   return true;
 /*
  * if (true) ThenStmt(); -> ThenStmt();
@@ -467,7 +468,8 @@ class SimplifyBooleanExprCheck::Visitor : public 
RecursiveASTVisitor {
  * if (Cond) return false; return true; -> return !Cond;
  */
 auto *If = cast(*First);
-if (!If->hasInitStorage() && !If->hasVarStorage()) {
+if (!If->hasInitStorage() && !If->hasVarStorage() &&
+!If->isConsteval()) {
   ExprAndBool ThenReturnBool =
   checkSingleStatement(If->getThen(), parseReturnLiteralBool);
   if (ThenReturnBool &&
@@ -491,7 +493,7 @@ class SimplifyBooleanExprCheck::Visitor : public 
RecursiveASTVisitor {
 : cast(*First)->getSubStmt();
 auto *SubIf = dyn_cast(SubStmt);
 if (SubIf && !SubIf->getElse() && !SubIf->hasInitStorage() &&
-!SubIf->hasVarStorage()) {
+!SubIf->hasVarStorage() && !SubIf->isConsteval()) {
   ExprAndBool ThenReturnBool =
   checkSingleStatement(SubIf->getThen(), parseReturnLiteralBool);
   if (ThenReturnBool &&

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 199f46ae14334..4082a2b0bce2c 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -159,6 +159,11 @@ Changes in existing checks
   ` to not
   warn about `const` value parameters of declarations inside macros.
 
+- Fixed crashes in :doc:`readability-braces-around-statements
+  ` and
+  :doc:`readability-simplify-boolean-expr 
`
+  when using a C++23 ``if consteval`` statement.
+
 Removed checks
 ^^
 

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements-consteval-if.cpp
 
b/clang-tools-extra/

[clang] 231fc00 - [clang-format][docs][NFC] Fix invalid syntax in ShortLambdaStyle examples.

2022-10-10 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-10-10T21:13:07+03:00
New Revision: 231fc00cebc127badb6df6e8902727e893335a58

URL: 
https://github.com/llvm/llvm-project/commit/231fc00cebc127badb6df6e8902727e893335a58
DIFF: 
https://github.com/llvm/llvm-project/commit/231fc00cebc127badb6df6e8902727e893335a58.diff

LOG: [clang-format][docs][NFC] Fix invalid syntax in ShortLambdaStyle examples.

Added: 


Modified: 
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h

Removed: 




diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index ec53c3eef8540..cdbc23ae43eb8 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -,7 +,7 @@ the configuration (without a prefix: ``Auto``).
 
 .. code-block:: c++
 
-  auto lambda = [](int a) {}
+  auto lambda = [](int a) {};
   auto lambda2 = [](int a) {
   return a;
   };
@@ -1124,14 +1124,14 @@ the configuration (without a prefix: ``Auto``).
   auto lambda = [](int a) {
   return a;
   };
-  sort(a.begin(), a.end(), ()[] { return x < y; })
+  sort(a.begin(), a.end(), []() { return x < y; });
 
   * ``SLS_All`` (in configuration: ``All``)
 Merge all lambdas fitting on a single line.
 
 .. code-block:: c++
 
-  auto lambda = [](int a) {}
+  auto lambda = [](int a) {};
   auto lambda2 = [](int a) { return a; };
 
 

diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index ee1863a63bc9a..7c1721064727c 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -610,7 +610,7 @@ struct FormatStyle {
 SLS_None,
 /// Only merge empty lambdas.
 /// \code
-///   auto lambda = [](int a) {}
+///   auto lambda = [](int a) {};
 ///   auto lambda2 = [](int a) {
 ///   return a;
 ///   };
@@ -621,12 +621,12 @@ struct FormatStyle {
 ///   auto lambda = [](int a) {
 ///   return a;
 ///   };
-///   sort(a.begin(), a.end(), ()[] { return x < y; })
+///   sort(a.begin(), a.end(), []() { return x < y; });
 /// \endcode
 SLS_Inline,
 /// Merge all lambdas fitting on a single line.
 /// \code
-///   auto lambda = [](int a) {}
+///   auto lambda = [](int a) {};
 ///   auto lambda2 = [](int a) { return a; };
 /// \endcode
 SLS_All,



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


[clang] 94215d2 - [clang-format] Correctly annotate star/amp in function pointer params

2022-10-17 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-10-18T08:17:23+03:00
New Revision: 94215d2b2103c5ad74596dd51704836f92afec89

URL: 
https://github.com/llvm/llvm-project/commit/94215d2b2103c5ad74596dd51704836f92afec89
DIFF: 
https://github.com/llvm/llvm-project/commit/94215d2b2103c5ad74596dd51704836f92afec89.diff

LOG: [clang-format] Correctly annotate star/amp in function pointer params

Inside the arguments part of a function pointer declaration,
`determineStarAmpUsage` results in a binary operator rather than
pointers, because said parens are assumed to be an expression.

This patch correctly marks the argument parens of a function
pointer type as not an expression. Note that this fix already
existed for Objective-C blocks as part of 
f1f267b447f60528440d2c066b29ab014ae7f90f.
As Objective-C blocks and C/C++ function pointers share a lot
of the same logic, that fix also makes sense here.

Fixes https://github.com/llvm/llvm-project/issues/31659

Differential Revision: https://reviews.llvm.org/D135707

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 597d7b64625f3..8eef2be404d18 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -302,7 +302,8 @@ class AnnotatingParser {
   Contexts.back().ContextType = Context::ForEachMacro;
   Contexts.back().IsExpression = false;
 } else if (OpeningParen.Previous && OpeningParen.Previous->MatchingParen &&
-   OpeningParen.Previous->MatchingParen->is(TT_ObjCBlockLParen)) {
+   OpeningParen.Previous->MatchingParen->isOneOf(
+   TT_ObjCBlockLParen, TT_FunctionTypeLParen)) {
   Contexts.back().IsExpression = false;
 } else if (!Line.MustBeDeclaration && !Line.InPPDirective) {
   bool IsForOrCatch =

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index a777382e762a0..e9f5d66d8c566 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -10459,6 +10459,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
   verifyFormat("#define MACRO() [](A *a) { return 1; }");
   verifyFormat("Constructor() : member([](A *a, B *b) {}) {}");
   verifyIndependentOfContext("typedef void (*f)(int *a);");
+  verifyIndependentOfContext("typedef void (*f)(Type *a);");
   verifyIndependentOfContext("int i{a * b};");
   verifyIndependentOfContext("aaa && aaa->f();");
   verifyIndependentOfContext("int x = ~*p;");

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index c8de8a2a2abe4..14918c7e6ff96 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -131,6 +131,20 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
   Tokens = annotate("delete[] *(ptr);");
   EXPECT_EQ(Tokens.size(), 9u) << Tokens;
   EXPECT_TOKEN(Tokens[3], tok::star, TT_UnaryOperator);
+
+  Tokens = annotate("void f() { void (*fnptr)(char* foo); }");
+  EXPECT_EQ(Tokens.size(), 18u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_FunctionTypeLParen);
+  // FIXME: The star of a function pointer probably makes more sense as
+  // TT_PointerOrReference.
+  EXPECT_TOKEN(Tokens[7], tok::star, TT_UnaryOperator);
+  EXPECT_TOKEN(Tokens[12], tok::star, TT_PointerOrReference);
+
+  Tokens = annotate("void f() { void (*fnptr)(t* foo); }");
+  EXPECT_EQ(Tokens.size(), 18u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_FunctionTypeLParen);
+  EXPECT_TOKEN(Tokens[7], tok::star, TT_UnaryOperator);
+  EXPECT_TOKEN(Tokens[12], tok::star, TT_PointerOrReference);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {



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


[clang] ba4caec - [clang-format][docs] Fix invalid CSS syntax in versionbadge

2022-12-22 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-12-23T02:15:48+02:00
New Revision: ba4caec64fec457b4ab20876a809b45162b048f4

URL: 
https://github.com/llvm/llvm-project/commit/ba4caec64fec457b4ab20876a809b45162b048f4
DIFF: 
https://github.com/llvm/llvm-project/commit/ba4caec64fec457b4ab20876a809b45162b048f4.diff

LOG: [clang-format][docs] Fix invalid CSS syntax in versionbadge

CSS uses colons, not the equals sign. The final semicolon is optional,
but preferred to be included. Really, the font property doesn't really
need to be there, but I suppose it was put there for a reason.

It's surprising how lenient browsers are when parsing

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D138441

Added: 


Modified: 
clang/docs/ClangFormatStyleOptions.rst

Removed: 




diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 27e93ff504d8..cac0afe0bffc 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1,7 +1,7 @@
 .. raw:: html
 
   
-.versionbadge { background-color: #1c913d; height: 20px; display: 
inline-block; width: 120px; text-align: center; border-radius: 5px; color: 
#FF; font-family="Verdana,Geneva,DejaVu Sans,sans-serif" }
+.versionbadge { background-color: #1c913d; height: 20px; display: 
inline-block; width: 120px; text-align: center; border-radius: 5px; color: 
#FF; font-family: "Verdana,Geneva,DejaVu Sans,sans-serif"; }
   
 
 .. role:: versionbadge



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


[clang] 0ebed86 - [clang-format] Set requires expression params as not an expression

2022-12-22 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-12-23T02:22:48+02:00
New Revision: 0ebed862d82134e7a8e42d8dc7944afe765445ba

URL: 
https://github.com/llvm/llvm-project/commit/0ebed862d82134e7a8e42d8dc7944afe765445ba
DIFF: 
https://github.com/llvm/llvm-project/commit/0ebed862d82134e7a8e42d8dc7944afe765445ba.diff

LOG: [clang-format] Set requires expression params as not an expression

Previously, the parens of a requires expression's "parameters" were not
explicitly set, meaning they ended up as whatever the outer scope was.
This is a problem in some cases though, since the process of determining
star/amp checks if the token is inside of an expression context

This patch always makes sure the context between those parens are always
set to not be an expression

Fixes https://github.com/llvm/llvm-project/issues/59600

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D140330

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 1fdceabbabc8..52314a19a883 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -321,6 +321,8 @@ class AnnotatingParser {
 } else if (isLambdaParameterList(&OpeningParen)) {
   // This is a parameter list of a lambda expression.
   Contexts.back().IsExpression = false;
+} else if (OpeningParen.is(TT_RequiresExpressionLParen)) {
+  Contexts.back().IsExpression = false;
 } else if (Line.InPPDirective &&
(!OpeningParen.Previous ||
 !OpeningParen.Previous->is(tok::identifier))) {

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 2e3bbd7e60b5..806c75d1e813 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -711,19 +711,50 @@ TEST_F(TokenAnnotatorTest, 
UnderstandsRequiresExpressions) {
   ASSERT_EQ(Tokens.size(), 15u) << Tokens;
   EXPECT_TOKEN(Tokens[2], tok::kw_requires, TT_RequiresExpression);
   EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_RequiresExpressionLParen);
+  EXPECT_TOKEN(Tokens[6], tok::star, TT_PointerOrReference);
   EXPECT_TOKEN(Tokens[10], tok::l_brace, TT_RequiresExpressionLBrace);
 
   Tokens = annotate("foo(requires(T const* volatile t) {});");
   ASSERT_EQ(Tokens.size(), 15u) << Tokens;
   EXPECT_TOKEN(Tokens[2], tok::kw_requires, TT_RequiresExpression);
   EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_RequiresExpressionLParen);
+  EXPECT_TOKEN(Tokens[6], tok::star, TT_PointerOrReference);
   EXPECT_TOKEN(Tokens[10], tok::l_brace, TT_RequiresExpressionLBrace);
 
+  Tokens = annotate("foo(requires(T& t) {});");
+  ASSERT_EQ(Tokens.size(), 13u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_requires, TT_RequiresExpression);
+  EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_RequiresExpressionLParen);
+  EXPECT_TOKEN(Tokens[5], tok::amp, TT_PointerOrReference);
+  EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_RequiresExpressionLBrace);
+
+  Tokens = annotate("foo(requires(T&& t) {});");
+  ASSERT_EQ(Tokens.size(), 13u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_requires, TT_RequiresExpression);
+  EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_RequiresExpressionLParen);
+  EXPECT_TOKEN(Tokens[5], tok::ampamp, TT_PointerOrReference);
+  EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_RequiresExpressionLBrace);
+
+  Tokens = annotate("bool foo = requires(T& t) {};");
+  ASSERT_EQ(Tokens.size(), 13u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::kw_requires, TT_RequiresExpression);
+  EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_RequiresExpressionLParen);
+  EXPECT_TOKEN(Tokens[6], tok::amp, TT_PointerOrReference);
+  EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_RequiresExpressionLBrace);
+
+  Tokens = annotate("bool foo = requires(T&& t) {};");
+  ASSERT_EQ(Tokens.size(), 13u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::kw_requires, TT_RequiresExpression);
+  EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_RequiresExpressionLParen);
+  EXPECT_TOKEN(Tokens[6], tok::ampamp, TT_PointerOrReference);
+  EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_RequiresExpressionLBrace);
+
   Tokens =
   annotate("foo(requires(const typename Outer::Inner * const t) {});");
   ASSERT_EQ(Tokens.size(), 21u) << Tokens;
   EXPECT_TOKEN(Tokens[2], tok::kw_requires, TT_RequiresExpression);
   EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_RequiresExpressionLParen);
+  EXPECT_TOKEN(Tokens[12], tok::star, TT_PointerOrReference);
   EXPECT_TOKEN(Tokens[16], tok::l_brace, TT_RequiresExpressionLBrace);
 
   Tokens = annotate("template \n"



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


[clang] 54fab18 - [clang-format] Require space before noexcept qualifier

2023-01-05 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-06T05:03:56+02:00
New Revision: 54fab18cedace085344b674ab9de2c93b5fa479b

URL: 
https://github.com/llvm/llvm-project/commit/54fab18cedace085344b674ab9de2c93b5fa479b
DIFF: 
https://github.com/llvm/llvm-project/commit/54fab18cedace085344b674ab9de2c93b5fa479b.diff

LOG: [clang-format] Require space before noexcept qualifier

This brings the noexcept qualifier more visually in line with the other
keyword qualifiers, such as "final" and "override".

Originally reported as https://github.com/llvm/llvm-project/issues/44542,
it was closed as "working by design" and reinforcing tests were added
as part of a218706cba90248be0c60bd6a8f10dbcf0270955. The exact spacing
depended on the `PointerAlignment` option, where the default value of
`Right` would leave no space.

This patch seeks to change this behaviour, regardless of the configured
`PointerAlignment` option (matching the previous behaviour of the `Left`
option).

Closes https://github.com/llvm/llvm-project/issues/59729

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D140767

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 3ed0b3d3c6612..35fa8cf91b330 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -3530,7 +3530,8 @@ bool TokenAnnotator::spaceRequiredBetween(const 
AnnotatedLine &Line,
 if (Right.is(TT_BlockComment))
   return true;
 // foo() -> const Bar * override/final
-if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final) &&
+if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final,
+  tok::kw_noexcept) &&
 !Right.is(TT_StartOfName)) {
   return true;
 }

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 2265b03f0868a..843e945aeae5b 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -10566,10 +10566,10 @@ TEST_F(FormatTest, UnderstandsOverloadedOperators) {
 
 TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
   verifyFormat("void A::b() && {}");
-  verifyFormat("void A::b() &&noexcept {}");
+  verifyFormat("void A::b() && noexcept {}");
   verifyFormat("Deleted &operator=(const Deleted &) & = default;");
   verifyFormat("Deleted &operator=(const Deleted &) && = delete;");
-  verifyFormat("Deleted &operator=(const Deleted &) &noexcept = default;");
+  verifyFormat("Deleted &operator=(const Deleted &) & noexcept = default;");
   verifyFormat("SomeType MemberFunction(const Deleted &) & = delete;");
   verifyFormat("SomeType MemberFunction(const Deleted &) && = delete;");
   verifyFormat("Deleted &operator=(const Deleted &) &;");
@@ -10579,16 +10579,16 @@ TEST_F(FormatTest, 
UnderstandsFunctionRefQualification) {
   verifyFormat("SomeType MemberFunction(const Deleted &) && {}");
   verifyFormat("SomeType MemberFunction(const Deleted &) && final {}");
   verifyFormat("SomeType MemberFunction(const Deleted &) && override {}");
-  verifyFormat("SomeType MemberFunction(const Deleted &) &&noexcept {}");
+  verifyFormat("SomeType MemberFunction(const Deleted &) && noexcept {}");
   verifyFormat("void Fn(T const &) const &;");
   verifyFormat("void Fn(T const volatile &&) const volatile &&;");
-  verifyFormat("void Fn(T const volatile &&) const volatile &&noexcept;");
+  verifyFormat("void Fn(T const volatile &&) const volatile && noexcept;");
   verifyFormat("template \n"
"void F(T) && = delete;",
getGoogleStyle());
   verifyFormat("template  void operator=(T) &;");
   verifyFormat("template  void operator=(T) const &;");
-  verifyFormat("template  void operator=(T) &noexcept;");
+  verifyFormat("template  void operator=(T) & noexcept;");
   verifyFormat("template  void operator=(T) & = default;");
   verifyFormat("template  void operator=(T) &&;");
   verifyFormat("template  void operator=(T) && = delete;");
@@ -10678,31 +10678,31 @@ TEST_F(FormatTest, 
UnderstandsFunctionRefQualification) {
 
   verifyFormat("struct f {\n"
"  template \n"
-   "  int &foo(const std::string &str) &noexcept {}\n"
+   "  int &foo(const std::string &str) & noexcept {}\n"
"};",
BreakTemplate);
 
   verifyFormat("struct f {\n"
"  template \n"
-   "  int &foo(const std::string &str) &&noexcept {}\n"
+   "  int &foo(const std::string &str) && noexcept {}\n"
"};",
BreakTemplate);
 
   verifyFormat("struct f {\n"
"  template \n"
-   "  int &foo(const std::string &str) const &noexcept {}\n"
+   "  int &foo(const std::string &str) co

[clang] b1eeec6 - [clang-format] Remove special logic for parsing concept definitions.

2023-01-05 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-06T05:17:58+02:00
New Revision: b1eeec6177fafcc433d98c4f46f353b13c68aca0

URL: 
https://github.com/llvm/llvm-project/commit/b1eeec6177fafcc433d98c4f46f353b13c68aca0
DIFF: 
https://github.com/llvm/llvm-project/commit/b1eeec6177fafcc433d98c4f46f353b13c68aca0.diff

LOG: [clang-format] Remove special logic for parsing concept definitions.

Previously, clang-format relied on a special method to parse concept
definitions, `UnwrappedLineParser::parseConcept()`, which deferred to
`UnwrappedLineParser::parseConstraintExpression()`. This is problematic,
because the C++ grammar treats concepts and requires clauses
differently, causing issues such as 
https://github.com/llvm/llvm-project/issues/55898 and 
https://github.com/llvm/llvm-project/issues/58130.

This patch removes `parseConcept`, letting the formatter parse concept
definitions as more like what they actually are, fancy bool definitions.

NOTE that because of this, some long concept definitions change in their
formatting, as can be seen in the changed tests. This is because of a
change in split penalties, caused by a change in MightBeFunctionDecl on
the concept definition line, which was previously `true` but with this
patch is now `false`.

One might argue that `false` is a more "correct" value for concept
definitions, but I'd be fine with setting it to `true` again to maintain
compatibility with previous versions.

Fixes https://github.com/llvm/llvm-project/issues/58130

Depends on D140330

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D140339

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/lib/Format/UnwrappedLineParser.cpp
clang/lib/Format/UnwrappedLineParser.h
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 35fa8cf91b33..9dd92c9b08f1 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1690,8 +1690,8 @@ class AnnotatingParser {
 if (!Tok)
   return false;
 
-if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_concept,
- tok::kw_struct, tok::kw_using)) {
+if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct,
+ tok::kw_using)) {
   return false;
 }
 

diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 8e1ea0677902..81a6d8ffc0ee 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1818,9 +1818,6 @@ void UnwrappedLineParser::parseStructuralElement(
 break;
   }
   break;
-case tok::kw_concept:
-  parseConcept();
-  return;
 case tok::kw_requires: {
   if (Style.isCpp()) {
 bool ParsedClause = parseRequires();
@@ -3277,26 +3274,6 @@ void UnwrappedLineParser::parseAccessSpecifier() {
   }
 }
 
-/// \brief Parses a concept definition.
-/// \pre The current token has to be the concept keyword.
-///
-/// Returns if either the concept has been completely parsed, or if it detects
-/// that the concept definition is incorrect.
-void UnwrappedLineParser::parseConcept() {
-  assert(FormatTok->is(tok::kw_concept) && "'concept' expected");
-  nextToken();
-  if (!FormatTok->is(tok::identifier))
-return;
-  nextToken();
-  if (!FormatTok->is(tok::equal))
-return;
-  nextToken();
-  parseConstraintExpression();
-  if (FormatTok->is(tok::semi))
-nextToken();
-  addUnwrappedLine();
-}
-
 /// \brief Parses a requires, decides if it is a clause or an expression.
 /// \pre The current token has to be the requires keyword.
 /// \returns true if it parsed a clause.
@@ -3463,6 +3440,8 @@ void UnwrappedLineParser::parseRequiresClause(FormatToken 
*RequiresToken) {
   ? TT_RequiresClauseInARequiresExpression
   : TT_RequiresClause);
 
+  // NOTE: parseConstraintExpression is only ever called from this function.
+  // It could be inlined into here.
   parseConstraintExpression();
 
   if (!InRequiresExpression)
@@ -3496,9 +3475,8 @@ void 
UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) {
 
 /// \brief Parses a constraint expression.
 ///
-/// This is either the definition of a concept, or the body of a requires
-/// clause. It returns, when the parsing is complete, or the expression is
-/// incorrect.
+/// This is the body of a requires clause. It returns, when the parsing is
+/// complete, or the expression is incorrect.
 void UnwrappedLineParser::parseConstraintExpression() {
   // The special handling for lambdas is needed since tryToParseLambda() eats a
   // token and if a requires expression is the last part of a requires clause

diff  --git a/clang/lib/Format/Unwr

[clang] d989950 - [clang-format] Disallow decltype in the middle of constraints

2023-01-05 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-06T05:18:28+02:00
New Revision: d9899501576e7b3b8ec4a3f0f855a6bfe68cef88

URL: 
https://github.com/llvm/llvm-project/commit/d9899501576e7b3b8ec4a3f0f855a6bfe68cef88
DIFF: 
https://github.com/llvm/llvm-project/commit/d9899501576e7b3b8ec4a3f0f855a6bfe68cef88.diff

LOG: [clang-format] Disallow decltype in the middle of constraints

If a function with a `requires` clause as a constraint has a decltype
return type, such as `decltype(auto)`, the decltype was seen to be part
of the constraint clause, rather than as part of the function
declaration, causing it to be placed on the wrong line.

This patch disallows decltype to be a part of these clauses

Fixes https://github.com/llvm/llvm-project/issues/59578

Depends on D140339

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D140312

Added: 


Modified: 
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 81a6d8ffc0ee..c97ecc782120 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -3543,7 +3543,6 @@ void UnwrappedLineParser::parseConstraintExpression() {
 case tok::minus:
 case tok::star:
 case tok::slash:
-case tok::kw_decltype:
   LambdaNextTimeAllowed = true;
   // Just eat them.
   nextToken();

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 21b497bd9568..b2a1e2c57f8c 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -24199,6 +24199,10 @@ TEST_F(FormatTest, RequiresClauses) {
"  }\n"
"};");
 
+  verifyFormat("template \n"
+   "  requires(std::same_as)\n"
+   "decltype(auto) fun() {}");
+
   auto Style = getLLVMStyle();
 
   verifyFormat(

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 806c75d1e813..dba893dfdd50 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -580,6 +580,14 @@ TEST_F(TokenAnnotatorTest, 
UnderstandsRequiresClausesAndConcepts) {
   EXPECT_TRUE(Tokens[9]->ClosesRequiresClause);
   EXPECT_TOKEN(Tokens[11], tok::identifier, TT_FunctionDeclarationName);
 
+  Tokens = annotate("template \n"
+"requires Bar\n"
+"decltype(auto) foo(T) { return false; }");
+  ASSERT_EQ(Tokens.size(), 24u) << Tokens;
+  EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);
+  EXPECT_TRUE(Tokens[9]->ClosesRequiresClause);
+  EXPECT_TOKEN(Tokens[14], tok::identifier, TT_FunctionDeclarationName);
+
   Tokens = annotate("template \n"
 "struct S {\n"
 "  void foo() const requires Bar;\n"



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


[clang] 51ba660 - [clang-format] Inherit RightAlign options across scopes

2023-01-10 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-11T05:59:45+02:00
New Revision: 51ba660a0700e659e1a97f3ca5879b8617ec5c26

URL: 
https://github.com/llvm/llvm-project/commit/51ba660a0700e659e1a97f3ca5879b8617ec5c26
DIFF: 
https://github.com/llvm/llvm-project/commit/51ba660a0700e659e1a97f3ca5879b8617ec5c26.diff

LOG: [clang-format] Inherit RightAlign options across scopes

D119599 added the ability to align compound assignments, right aligning
them in order to line up at the equals sign.
However, that patch didn't account for AlignTokens being called
recursively across scopes, which reset the right justification to be
false in any scope besides the top scope. This meant the compound
assignments were aligned, just not at the right place.
(No tests also ever introduced any scopes)

This patch makes sure to inherit the right justification value, just as
every other parameter is passed on.

Fixes https://github.com/llvm/llvm-project/issues/58029

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D141288

Added: 


Modified: 
clang/lib/Format/WhitespaceManager.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/WhitespaceManager.cpp 
b/clang/lib/Format/WhitespaceManager.cpp
index 99261bdf4519e..9951906b6af01 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -609,7 +609,8 @@ static unsigned AlignTokens(const FormatStyle &Style, F 
&&Matches,
   ++CommasBeforeMatch;
 } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
   // Call AlignTokens recursively, skipping over this scope block.
-  unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
+  unsigned StoppedAt =
+  AlignTokens(Style, Matches, Changes, i, ACS, RightJustify);
   i = StoppedAt - 1;
   continue;
 }

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 550c5a29f75e6..b39cae1ebe3f2 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -17693,6 +17693,20 @@ TEST_F(FormatTest, AlignCompoundAssignments) {
"dvsdsv<<= 5;\n"
"int dsvvdvsdvvv = 123;",
Alignment);
+  verifyFormat("int xxx = 5;\n"
+   "xxx = 5;\n"
+   "{\n"
+   "  int yyy = 6;\n"
+   "  yyy = 6;\n"
+   "}",
+   Alignment);
+  verifyFormat("int xxx = 5;\n"
+   "xxx+= 5;\n"
+   "{\n"
+   "  int yyy = 6;\n"
+   "  yyy+= 6;\n"
+   "}",
+   Alignment);
   // Test that `<=` is not treated as a compound assignment.
   verifyFormat("aa &= 5;\n"
"b <= 10;\n"



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


[clang] 0904e0b - [clang-format] Properly handle the C11 _Generic keyword.

2023-01-10 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-11T06:00:16+02:00
New Revision: 0904e0bac8314249ee7c1b0658f1a1cc92ccd050

URL: 
https://github.com/llvm/llvm-project/commit/0904e0bac8314249ee7c1b0658f1a1cc92ccd050
DIFF: 
https://github.com/llvm/llvm-project/commit/0904e0bac8314249ee7c1b0658f1a1cc92ccd050.diff

LOG: [clang-format] Properly handle the C11 _Generic keyword.

This patch properly recognizes the generic selection expression
introduced in C11, by adding an additional token type for the colons
present in such expressions.

Previously, they would be recognized as
"inline ASM colons" purely by the fact that those are the last thing
checked for.

I tried to avoid adding an addition token type, but since colons by
default like having spaces around them, I chose to add a new type so
that no space is added after the type selector.

Currently, no aspect of the formatting of these expressions in able to
be configured, as I'm not sure what could even be configured here.

One notable thing is that association list is always formatted as
either entirely on one line, if it can fit, or with line breaks
after every comma in the expression (also after the controlling expr.)

This visually makes them more similar to switch statements when long,
matching the behaviour of the selection expression, being that of a sort
of switch on types, but also allows for terseness when only selecting
for a few things.

Fixes https://github.com/llvm/llvm-project/issues/18080

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D139211

Added: 


Modified: 
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/FormatToken.h
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 04244c146827..833b10e3a578 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1538,6 +1538,12 @@ void 
ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
   std::max(State.Column, NewParenState.Indent), 
CurrentState.LastSpace);
 }
 
+// Special case for generic selection expressions, its comma-separated
+// expressions are not aligned to the opening paren like regular calls, but
+// rather continuation-indented relative to the _Generic keyword.
+if (Previous && Previous->endsSequence(tok::l_paren, tok::kw__Generic))
+  NewParenState.Indent = CurrentState.LastSpace;
+
 if (Previous &&
 (Previous->getPrecedence() == prec::Assignment ||
  Previous->isOneOf(tok::kw_return, TT_RequiresClause) ||
@@ -1684,8 +1690,12 @@ void 
ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
 (State.Line->Type != LT_ObjCDecl && Style.BinPackParameters) ||
 (State.Line->Type == LT_ObjCDecl && ObjCBinPackProtocolList);
 
+bool GenericSelection =
+Current.getPreviousNonComment() &&
+Current.getPreviousNonComment()->is(tok::kw__Generic);
+
 AvoidBinPacking =
-(CurrentState.IsCSharpGenericTypeConstraint) ||
+(CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
 (Style.isJavaScript() && EndsInComma) ||
 (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
 (!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||

diff  --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index e8c6cd9a5d4b..6de9dfa383d5 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -70,6 +70,8 @@ namespace format {
   TYPE(FunctionLBrace) 
\
   TYPE(FunctionLikeOrFreestandingMacro)
\
   TYPE(FunctionTypeLParen) 
\
+  /* The colons as part of a C11 _Generic selection */ 
\
+  TYPE(GenericSelectionColon)  
\
   /* The colon at the end of a goto label or a case label. Currently only used 
\
* for Verilog. */   
\
   TYPE(GotoLabelColon) 
\

diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index c081b24d3372..8bd7bcf307db 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -322,6 +322,10 @@ class AnnotatingParser {
   Contexts.back().IsExpression = false;
 } else if (OpeningParen.is(TT_RequiresExpressionLParen)) {
   Contexts.back().IsExpression = false;
+} else if (OpeningParen.Previous &&
+   OpeningParen.Previous->is(tok::kw__Generic)) {
+  Context

[clang] 800f0f1 - [docs] Apply previous sphinx fix to its actual source

2023-01-11 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-11T14:44:36+02:00
New Revision: 800f0f1546b2352ba42a4777149afb13cb874fcd

URL: 
https://github.com/llvm/llvm-project/commit/800f0f1546b2352ba42a4777149afb13cb874fcd
DIFF: 
https://github.com/llvm/llvm-project/commit/800f0f1546b2352ba42a4777149afb13cb874fcd.diff

LOG: [docs] Apply previous sphinx fix to its actual source

This clang-format documentation file is auto-generated from Format.h,
so the fix should be applied there, or else it will be overwritten
whenever Format.h is modified and that file is regenerated.

Added: 


Modified: 
clang/include/clang/Format/Format.h

Removed: 




diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3a90c1fe5be9..f6c8723e4d33 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2501,7 +2501,7 @@ struct FormatStyle {
   /// \endcode
   struct IntegerLiteralSeparatorStyle {
 /// Format separators in binary literals.
-/// \code
+/// \code{.text}
 ///-1: 0b10001101
 /// 0: 0b10011'11'0110'1
 /// 3: 0b100'111'101'101



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


[clang] df6f4b8 - [clang-format] Defer formatting of operator< to honor paren spacing

2022-11-17 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-11-17T11:38:21+02:00
New Revision: df6f4b85138f86be73d58ff3f511df5306cc4b4d

URL: 
https://github.com/llvm/llvm-project/commit/df6f4b85138f86be73d58ff3f511df5306cc4b4d
DIFF: 
https://github.com/llvm/llvm-project/commit/df6f4b85138f86be73d58ff3f511df5306cc4b4d.diff

LOG: [clang-format] Defer formatting of operator< to honor paren spacing

I'm not exactly sure what the intent of that section of
`spaceRequiredBetween` is doing, it seems to handle templates and <<,
but the part which adds spaces before parens is way later, as part
of `spaceRequiredBeforeParens`.

Fixes https://github.com/llvm/llvm-project/issues/58821

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D137474

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 75570552146ce..6c4d908f96c8d 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -3441,7 +3441,9 @@ bool TokenAnnotator::spaceRequiredBetween(const 
AnnotatedLine &Line,
 return false;
   return !Style.Cpp11BracedListStyle;
 }
-return false;
+// Don't attempt to format operator<(), as it is handled later.
+if (Right.isNot(TT_OverloadedOperatorLParen))
+  return false;
   }
   if (Right.is(tok::ellipsis)) {
 return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous 
&&

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 628cb82c863b7..9505fa03d3e85 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -15544,6 +15544,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   Space.SpaceBeforeParens = FormatStyle::SBPO_Always;
 
   verifyFormat("int f ();", Space);
+  verifyFormat("bool operator< ();", Space);
+  verifyFormat("bool operator> ();", Space);
   verifyFormat("void f (int a, T b) {\n"
"  while (true)\n"
"continue;\n"



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


[clang] 48a932e - [clang-format] Remove special case for kw_operator when aligning decls

2022-11-17 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-11-17T11:38:28+02:00
New Revision: 48a932e13e04a21f4422d962bf1bb4667a670e41

URL: 
https://github.com/llvm/llvm-project/commit/48a932e13e04a21f4422d962bf1bb4667a670e41
DIFF: 
https://github.com/llvm/llvm-project/commit/48a932e13e04a21f4422d962bf1bb4667a670e41.diff

LOG: [clang-format] Remove special case for kw_operator when aligning decls

This change breaks no existing tests but does fix the linked issue.
Declarations of operator overloads are annotated with
`TT_FunctionDeclarationName` on the `operator` keyword, which is already
being checked for when aligning, so the extra `kw_operator` doesn't seem
to be necessary. (just for reference, it was added in
rG92b397fb9d55ccdf4632c2b1b15b4a0ee417cf74 / 
92b397fb9d55ccdf4632c2b1b15b4a0ee417cf74)

Fixes https://github.com/llvm/llvm-project/issues/55733

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D137223

Added: 


Modified: 
clang/lib/Format/WhitespaceManager.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/WhitespaceManager.cpp 
b/clang/lib/Format/WhitespaceManager.cpp
index 1f29f7ab917c..cd9773921dae 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -870,9 +870,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
   AlignTokens(
   Style,
   [](Change const &C) {
-// tok::kw_operator is necessary for aligning operator overload
-// definitions.
-if (C.Tok->isOneOf(TT_FunctionDeclarationName, tok::kw_operator))
+if (C.Tok->is(TT_FunctionDeclarationName))
   return true;
 if (C.Tok->isNot(TT_StartOfName))
   return false;

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index adacb9761ca3..2e3bbd7e60b5 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -423,50 +423,80 @@ TEST_F(TokenAnnotatorTest, 
UnderstandsFunctionRefQualifiers) {
 TEST_F(TokenAnnotatorTest, UnderstandsOverloadedOperators) {
   auto Tokens = annotate("x.operator+()");
   ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::plus, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator=()");
   ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::equal, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator+=()");
   ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::plusequal, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator,()");
   ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::comma, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator()()");
   ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[4], tok::r_paren, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator[]()");
   ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   // EXPECT_TOKEN(Tokens[3], tok::l_square, TT_OverloadedOperator);
   // EXPECT_TOKEN(Tokens[4], tok::r_square, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator\"\"_a()");
   ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator\"\" _a()");
   ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  // FIXME
+  // EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
   EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_OverloadedOperatorLParen);
   Tokens = annotate("x.operator\"\"if()");
   ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
   EXPE

[clang] 8a3de13 - [clang-format] Disallow templates to be followed by literal

2023-01-26 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-27T04:01:11+02:00
New Revision: 8a3de13573bdeaee13ec959fa2af0d11f21f5f00

URL: 
https://github.com/llvm/llvm-project/commit/8a3de13573bdeaee13ec959fa2af0d11f21f5f00
DIFF: 
https://github.com/llvm/llvm-project/commit/8a3de13573bdeaee13ec959fa2af0d11f21f5f00.diff

LOG: [clang-format] Disallow templates to be followed by literal

There should not be any cases where the angle brackets of template
parameters are directly followed by a literal. It is more likely that a
comparison is taking place instead.

This patch makes the TokenAnnotator prefer to annotate < and > as
operators when directly followed by a literal. A similar check already
exists for literals directly *before* potential template args.

Fixes https://github.com/llvm/llvm-project/issues/60140

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D142139

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 49c30ca78debf..1b1123fa36456 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -185,6 +185,8 @@ class AnnotatingParser {
 } else {
   CurrentToken->setType(TT_TemplateCloser);
 }
+if (CurrentToken->Next && CurrentToken->Next->Tok.isLiteral())
+  return false;
 next();
 return true;
   }

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 6530e2005e4c4..1d71bc909e8c6 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -10365,6 +10365,7 @@ TEST_F(FormatTest, UnderstandsTemplateParameters) {
 
   // Not template parameters.
   verifyFormat("return a < b && c > d;");
+  verifyFormat("a < 0 ? b : a > 0 ? c : d;");
   verifyFormat("void f() {\n"
"  while (a < b && c > d) {\n"
"  }\n"



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


[clang] 9cddd7a - [clang-format][docs] Add ability to link to specific config options

2023-01-12 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-01-12T21:05:38+02:00
New Revision: 9cddd7a2a1d231bf390679b7bc529c260b4a1e07

URL: 
https://github.com/llvm/llvm-project/commit/9cddd7a2a1d231bf390679b7bc529c260b4a1e07
DIFF: 
https://github.com/llvm/llvm-project/commit/9cddd7a2a1d231bf390679b7bc529c260b4a1e07.diff

LOG: [clang-format][docs] Add ability to link to specific config options

This allows for the creation of permalinks to specific clang-format
options, for better sharing of a specific option and its options.

(I'm adding the usual clang-format reviewers on this patch because
I don't know any other reviewers that well, perhaps someone with
docs experience should be added instead...)

Note that I wanted to make minimal changes to make this happen and thus
landed on an unideal setup, but to me, it seems like the best out of
worse ones.

I could have made every style option a subheading, which would add
automatically the logic for permalinks and the little paragraph icon for
sharing.

However, this meant that the links themselves would be suboptimal, as
they'd include the whole text of the heading, including the type and
versionbadge, which is needless noise and could change, breaking the
concept of a "permalink". The format of the page could be changed to
put the option names on their own in a heading, and the other info below
it in a paragraph.

As Sphinx seems unwilling to fix 
https://github.com/sphinx-doc/sphinx/issues/1961,
there isn't a succinct way to change the "id" html field used for
sections

I could have used an add-on 
(https://github.com/GeeTransit/sphinx-better-subsection),
or made one myself, but I wanted to avoid extra dependencies for no
reason. (plus, I don't know how to make one myself.)

I could have used raw HTML for each heading, but that would immensely
pollute the rst file, which, while it is generated, is currently still
human-readable and it'd be nice for it to stay that way.

Also note that sphinx treats references as case-insensitive, which means
that they will all be lowercased in the resulting HTML. I envisioned
the ability to simply add #OptionName after the URL to get placed right
at the desired config option, which isn't possible without things such
as inline `raw` HTML.

To reconcile that, I added the ¶ paragraph buttons that can be used to
generate the link to the desired section, but since headings are not
actually used, they are faked and literally just a link following each
option, which means they stylistically don't match all other headings.

Also note that this sort-of assumes HTML output. I know Sphinx can
output other formats but I do not know if they are used. A non-html
output could embed unusable ¶ signs everywhere.

I'm okay with this patch being rejected in its current solution, or if
any of the above listed alternatives are better, they could be pursued
instead. In case the downsides of this solution are too much, I will
just create a feature request issue for this and maybe let someone more
experienced with Sphinx handle it, since this is still a feature I would
like to have. (and I do not want to deal with Sphinx at all after
battling with it for a whole day to produce a mediocre result.)

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay, aaron.ballman

Differential Revision: https://reviews.llvm.org/D138446

Added: 


Modified: 
clang/docs/ClangFormatStyleOptions.rst
clang/docs/tools/dump_format_style.py

Removed: 




diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 4bcf3bd0cb8e3..b32ac72987408 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -142,8 +142,9 @@ each option. For enumeration types possible values are 
specified both as a C++
 enumeration member (with a prefix, e.g. ``LS_Auto``), and as a value usable in
 the configuration (without a prefix: ``Auto``).
 
+.. _BasedOnStyle:
 
-**BasedOnStyle** (``String``)
+**BasedOnStyle** (``String``) :ref:`¶ `
   The style used for all options not specifically set in the configuration.
 
   This option is supported only in the :program:`clang-format` configuration
@@ -184,10 +185,14 @@ the configuration (without a prefix: ``Auto``).
 
 .. START_FORMAT_STYLE_OPTIONS
 
-**AccessModifierOffset** (``Integer``) :versionbadge:`clang-format 3.3`
+.. _AccessModifierOffset:
+
+**AccessModifierOffset** (``Integer``) :versionbadge:`clang-format 3.3` 
:ref:`¶ `
   The extra indent or outdent of access modifiers, e.g. ``public:``.
 
-**AlignAfterOpenBracket** (``BracketAlignmentStyle``) 
:versionbadge:`clang-format 3.8`
+.. _AlignAfterOpenBracket:
+
+**AlignAfterOpenBracket** (``BracketAlignmentStyle``) 
:versionbadge:`clang-format 3.8` :ref:`¶ `
   If ``true``, horizontally aligns arguments after an open bracket.
 
   This applies to round brackets (parentheses), angle brackets and square
@@ -238,7 +243,9 @@ the configurat

[clang] 6acdf58 - [clang] Properly parse variable template requires clause in lambda

2023-03-17 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-03-17T22:29:48+02:00
New Revision: 6acdf58919d5e66809555acf5809b12c54ba79dd

URL: 
https://github.com/llvm/llvm-project/commit/6acdf58919d5e66809555acf5809b12c54ba79dd
DIFF: 
https://github.com/llvm/llvm-project/commit/6acdf58919d5e66809555acf5809b12c54ba79dd.diff

LOG: [clang] Properly parse variable template requires clause in lambda

Since P0857, part of C++20, a *lambda-expression* can contain a
*requires-clause* after its *template-parameter-list*.

While support for this was added as part of
eccc734a69c0c012ae3160887b65a535b35ead3e, one specific case isn't
handled properly, where the *requires-clause* consists of an
instantiation of a boolean variable template. This is due to a
diagnostic check which was written with the assumption that a
*requires-clause* can never be followed by a left parenthesis. This
assumption no longer holds for lambdas.

This diagnostic check would then attempt to perform a "recovery", but it
does so in a valid parse state, resulting in an invalid parse state
instead!

This patch adds a special case when parsing requires clauses of lambda
templates, to skip this diagnostic check.

Fixes https://github.com/llvm/llvm-project/issues/61278
Fixes https://github.com/llvm/llvm-project/issues/61387

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D146140

Added: 


Modified: 
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaConcept.cpp
clang/test/SemaTemplate/concepts.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 24f5b622249d8..53001f651ea4b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -80,6 +80,9 @@ C++20 Feature Support
 ^
 - Support for out-of-line definitions of constrained templates has been 
improved.
   This partially fixes `#49620 
`_.
+- Lambda templates with a requires clause directly after the template 
parameters now parse
+  correctly if the requires clause consists of a variable with a dependent 
type.
+  (`#61278 `_)
 
 C++2b Feature Support
 ^

diff  --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 4a795227e6293..4ff86843dacc1 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -105,27 +105,35 @@ bool Sema::CheckConstraintExpression(const Expr 
*ConstraintExpression,
   QualType Type = ConstraintExpression->getType();
 
   auto CheckForNonPrimary = [&] {
-if (PossibleNonPrimary)
-  *PossibleNonPrimary =
-  // We have the following case:
-  // template requires func(0) struct S { };
-  // The user probably isn't aware of the parentheses required around
-  // the function call, and we're only going to parse 'func' as the
-  // primary-expression, and complain that it is of non-bool type.
-  (NextToken.is(tok::l_paren) &&
-   (IsTrailingRequiresClause ||
-(Type->isDependentType() &&
- isa(ConstraintExpression)) ||
-Type->isFunctionType() ||
-Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
-  // We have the following case:
-  // template requires size_ == 0 struct S { };
-  // The user probably isn't aware of the parentheses required around
-  // the binary operator, and we're only going to parse 'func' as the
-  // first operand, and complain that it is of non-bool type.
-  getBinOpPrecedence(NextToken.getKind(),
- /*GreaterThanIsOperator=*/true,
- getLangOpts().CPlusPlus11) > prec::LogicalAnd;
+if (!PossibleNonPrimary)
+  return;
+
+*PossibleNonPrimary =
+// We have the following case:
+// template requires func(0) struct S { };
+// The user probably isn't aware of the parentheses required around
+// the function call, and we're only going to parse 'func' as the
+// primary-expression, and complain that it is of non-bool type.
+//
+// However, if we're in a lambda, this might also be:
+// [] requires var () {};
+// Which also looks like a function call due to the lambda parentheses,
+// but unlike the first case, isn't an error, so this check is skipped.
+(NextToken.is(tok::l_paren) &&
+ (IsTrailingRequiresClause ||
+  (Type->isDependentType() &&
+   isa(ConstraintExpression) &&
+   !dyn_cast_if_present(getCurFunction())) ||
+  Type->isFunctionType() ||
+  Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
+// We have the following case:
+// template requires size_ == 0 struct S { };
+// The user probably isn't aware of the parentheses requ

[clang] ead9644 - [clang-format] Annotate noexcept, explicit specifiers as containing expressions

2023-03-22 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-03-22T20:27:17+02:00
New Revision: ead9644684e85e0611f3b0ff72926820f1277e09

URL: 
https://github.com/llvm/llvm-project/commit/ead9644684e85e0611f3b0ff72926820f1277e09
DIFF: 
https://github.com/llvm/llvm-project/commit/ead9644684e85e0611f3b0ff72926820f1277e09.diff

LOG: [clang-format] Annotate noexcept, explicit specifiers as containing 
expressions

The noexcept specifier and explicit specifier can optionally include a
boolean expression to make these specifiers apply conditionally,
however, clang-format didn't set the context for the parenthesized
content of these specifiers, meaning they inherited the parent context,
which usually isn't an expressions, leading to misannotated binary
operators.

This patch applies expression context to the content of these
specifiers, making them similar to the static_assert keyword.

Fixes https://github.com/llvm/llvm-project/issues/44543

Reviewed By: owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D146284

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index c5644c5bfea16..55be50aec203e 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -318,9 +318,10 @@ class AnnotatingParser {
   // export type X = (...);
   Contexts.back().IsExpression = false;
 } else if (OpeningParen.Previous &&
-   (OpeningParen.Previous->isOneOf(tok::kw_static_assert,
-   tok::kw_while, tok::l_paren,
-   tok::comma, TT_BinaryOperator) 
||
+   (OpeningParen.Previous->isOneOf(
+tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit,
+tok::kw_while, tok::l_paren, tok::comma,
+TT_BinaryOperator) ||
 OpeningParen.Previous->isIf())) {
   // static_assert, if and while usually contain expressions.
   Contexts.back().IsExpression = true;

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 1beb6a75c5225..eeb1234999a10 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -11592,6 +11592,10 @@ TEST_F(FormatTest, UnderstandsRvalueReferences) {
   verifyFormat("template  class A {\n"
"  static_assert(B && C, \"Something is wrong\");\n"
"};");
+  verifyFormat("template  void swap() noexcept(Bar && 
Foo);");
+  verifyFormat("template  struct S {\n"
+   "  explicit(Bar && Foo) S(const S &);\n"
+   "};");
   verifyGoogleFormat("#define IF(a, b, c) if (a && (b == c))");
   verifyGoogleFormat("#define WHILE(a, b, c) while (a && (b == c))");
   verifyFormat("#define A(a, b) (a && b)");

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index bc8f7f36372d2..3a6fb0e9e4b3f 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -242,6 +242,17 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
 "}");
   ASSERT_EQ(Tokens.size(), 12u) << Tokens;
   EXPECT_TOKEN(Tokens[7], tok::amp, TT_BinaryOperator);
+
+  Tokens =
+  annotate("template  void swap() noexcept(Bar && 
Foo);");
+  ASSERT_EQ(Tokens.size(), 23u) << Tokens;
+  EXPECT_TOKEN(Tokens[15], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("template  struct S {\n"
+"  explicit(Bar && Foo) S(const S &);\n"
+"};");
+  ASSERT_EQ(Tokens.size(), 30u) << Tokens;
+  EXPECT_TOKEN(Tokens[14], tok::ampamp, TT_BinaryOperator);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {



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


[clang] c70e360 - [clang-format] Allow trailing return types in macros

2023-03-23 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-03-23T19:37:53+02:00
New Revision: c70e360b355ad30a7dd299435aae0324c5033b3f

URL: 
https://github.com/llvm/llvm-project/commit/c70e360b355ad30a7dd299435aae0324c5033b3f
DIFF: 
https://github.com/llvm/llvm-project/commit/c70e360b355ad30a7dd299435aae0324c5033b3f.diff

LOG: [clang-format] Allow trailing return types in macros

The trailing return type arrow checker verifies that a declaration is
being parsed, however, this isn't true when inside of macros.

It turns out the existence of the auto keyword is enough to make
sure that we're dealing with a trailing return type, and whether we're
in a declaration doesn't matter.

Fixes https://github.com/llvm/llvm-project/issues/47664

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D141811

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 55be50aec203e..5dbda8fbe0719 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1909,7 +1909,8 @@ class AnnotatingParser {
 } else if (Current.is(tok::arrow) &&
Style.Language == FormatStyle::LK_Java) {
   Current.setType(TT_LambdaArrow);
-} else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration &&
+} else if (Current.is(tok::arrow) && AutoFound &&
+   (Line.MustBeDeclaration || Line.InPPDirective) &&
Current.NestingLevel == 0 &&
!Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) {
   // not auto operator->() -> xxx;

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index eeb1234999a10..eb1b563b3d2c3 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -8010,6 +8010,11 @@ TEST_F(FormatTest, TrailingReturnType) {
"auto aa(T t)\n"
"-> decltype(eaaa(t.a).());");
 
+  FormatStyle Style = getLLVMStyleWithColumns(60);
+  verifyFormat("#define MAKE_DEF(NAME) 
\\\n"
+   "  auto NAME() -> int { return 42; }",
+   Style);
+
   // Not trailing return types.
   verifyFormat("void f() { auto a = b->c(); }");
   verifyFormat("auto a = p->foo();");



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


[clang] a8d2bff - [clang-format] Don't wrap struct return types as structs

2023-03-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-03-26T04:38:52+03:00
New Revision: a8d2bff290e1b86b4bca4007493205b4878c4f68

URL: 
https://github.com/llvm/llvm-project/commit/a8d2bff290e1b86b4bca4007493205b4878c4f68
DIFF: 
https://github.com/llvm/llvm-project/commit/a8d2bff290e1b86b4bca4007493205b4878c4f68.diff

LOG: [clang-format] Don't wrap struct return types as structs

When using BraceWrapping.AfterClass or BraceWrapping.AfterStruct, the
token annotator relies on the first token of the line to determine if
we're dealing with a struct or class, however, this check is faulty if
it's actually a function with an elaborated struct/class return type, as
is common in C.

This patch skips the check if the brace is already annotated as
FunctionLBrace, in which case we already know it's a function and should
be treated as such.

Fixes https://github.com/llvm/llvm-project/issues/58527

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D146281

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index d7758e7d068d..dfde6e4e0163 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4916,8 +4916,13 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine 
&Line,
   return true;
 }
 
-return (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) 
||
-   (Line.startsWith(tok::kw_struct) && 
Style.BraceWrapping.AfterStruct);
+// Don't attempt to interpret struct return types as structs.
+if (Right.isNot(TT_FunctionLBrace)) {
+  return (Line.startsWith(tok::kw_class) &&
+  Style.BraceWrapping.AfterClass) ||
+ (Line.startsWith(tok::kw_struct) &&
+  Style.BraceWrapping.AfterStruct);
+}
   }
 
   if (Left.is(TT_ObjCBlockLBrace) &&

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index eb1b563b3d2c..80efa8c4babf 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -3205,10 +3205,13 @@ TEST_F(FormatTest, MultiLineControlStatements) {
 format("try{foo();}catch(...){baz();}", Style));
 
   Style.BraceWrapping.AfterFunction = true;
+  Style.BraceWrapping.AfterStruct = false;
   Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_MultiLine;
   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
   Style.ColumnLimit = 80;
   verifyFormat("void shortfunction() { bar(); }", Style);
+  verifyFormat("struct T shortfunction() { return bar(); }", Style);
+  verifyFormat("struct T {};", Style);
 
   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
   verifyFormat("void shortfunction()\n"
@@ -3216,6 +3219,36 @@ TEST_F(FormatTest, MultiLineControlStatements) {
"  bar();\n"
"}",
Style);
+  verifyFormat("struct T shortfunction()\n"
+   "{\n"
+   "  return bar();\n"
+   "}",
+   Style);
+  verifyFormat("struct T {};", Style);
+
+  Style.BraceWrapping.AfterFunction = false;
+  Style.BraceWrapping.AfterStruct = true;
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+  verifyFormat("void shortfunction() { bar(); }", Style);
+  verifyFormat("struct T shortfunction() { return bar(); }", Style);
+  verifyFormat("struct T\n"
+   "{\n"
+   "};",
+   Style);
+
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+  verifyFormat("void shortfunction() {\n"
+   "  bar();\n"
+   "}",
+   Style);
+  verifyFormat("struct T shortfunction() {\n"
+   "  return bar();\n"
+   "}",
+   Style);
+  verifyFormat("struct T\n"
+   "{\n"
+   "};",
+   Style);
 }
 
 TEST_F(FormatTest, BeforeWhile) {



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


[clang] 5409fb3 - [clang-format] Annotate lambdas with requires clauses.

2023-03-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-03-26T04:38:26+03:00
New Revision: 5409fb38372dbf65a94725ccefab2b993fbb7a9b

URL: 
https://github.com/llvm/llvm-project/commit/5409fb38372dbf65a94725ccefab2b993fbb7a9b
DIFF: 
https://github.com/llvm/llvm-project/commit/5409fb38372dbf65a94725ccefab2b993fbb7a9b.diff

LOG: [clang-format] Annotate lambdas with requires clauses.

The C++ grammar allows lambdas to have a *requires-clause* in two
places, either directly after the *template-parameter-list*, such as:

`[]  requires foo (T t) { ... };`

Or, at the end of the *lambda-declarator* (before the lambda's body):

`[]  (T t) requires foo { ... };`

Previously, these cases weren't handled at all, resulting in weird
results.

Note that this commit only handles token annotation, so the actual
formatting still ends up suboptimal. This is mostly because I do not yet
know how to approach making the requires clause formatting of lambdas
match the formatting for functions.

Fixes https://github.com/llvm/llvm-project/issues/61269

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D145642

Added: 


Modified: 
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index f08a51f93e2f..9b17c28280f1 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2134,7 +2134,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
 case tok::l_brace:
   break;
 case tok::l_paren:
-  parseParens();
+  parseParens(/*AmpAmpTokenType=*/TT_PointerOrReference);
   break;
 case tok::l_square:
   parseSquare();
@@ -2211,6 +2211,12 @@ bool UnwrappedLineParser::tryToParseLambda() {
   SeenArrow = true;
   nextToken();
   break;
+case tok::kw_requires: {
+  auto *RequiresToken = FormatTok;
+  nextToken();
+  parseRequiresClause(RequiresToken);
+  break;
+}
 default:
   return true;
 }
@@ -3371,6 +3377,17 @@ void UnwrappedLineParser::parseConstraintExpression() {
   // lambda to be possible.
   // template  requires requires { ... } [[nodiscard]] ...;
   bool LambdaNextTimeAllowed = true;
+
+  // Within lambda declarations, it is permitted to put a requires clause after
+  // its template parameter list, which would place the requires clause right
+  // before the parentheses of the parameters of the lambda declaration. Thus,
+  // we track if we expect to see grouping parentheses at all.
+  // Without this check, `requires foo (T t)` in the below example would be
+  // seen as the whole requires clause, accidentally eating the parameters of
+  // the lambda.
+  // [&] requires foo (T t) { ... };
+  bool TopLevelParensAllowed = true;
+
   do {
 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false);
 
@@ -3383,7 +3400,10 @@ void UnwrappedLineParser::parseConstraintExpression() {
 }
 
 case tok::l_paren:
+  if (!TopLevelParensAllowed)
+return;
   parseParens(/*AmpAmpTokenType=*/TT_BinaryOperator);
+  TopLevelParensAllowed = false;
   break;
 
 case tok::l_square:
@@ -3407,6 +3427,7 @@ void UnwrappedLineParser::parseConstraintExpression() {
   FormatTok->setFinalizedType(TT_BinaryOperator);
   nextToken();
   LambdaNextTimeAllowed = true;
+  TopLevelParensAllowed = true;
   break;
 
 case tok::comma:
@@ -3430,6 +3451,7 @@ void UnwrappedLineParser::parseConstraintExpression() {
 case tok::star:
 case tok::slash:
   LambdaNextTimeAllowed = true;
+  TopLevelParensAllowed = true;
   // Just eat them.
   nextToken();
   break;
@@ -3438,6 +3460,7 @@ void UnwrappedLineParser::parseConstraintExpression() {
 case tok::coloncolon:
 case tok::kw_true:
 case tok::kw_false:
+  TopLevelParensAllowed = false;
   // Just eat them.
   nextToken();
   break;
@@ -3486,6 +3509,7 @@ void UnwrappedLineParser::parseConstraintExpression() {
 parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
 /*ClosingBraceKind=*/tok::greater);
   }
+  TopLevelParensAllowed = false;
   break;
 }
   } while (!eof());

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 3a6fb0e9e4b3..997630d08e2e 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -1279,6 +1279,110 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
   EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
   EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener);
   EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace);
+
+  // Lambdas with a requires-clause
+  Tokens = annotate("[]  (T t) requires Bar {}");
+ 

[clang] bb4f6c4 - [clang-format] Treat NTTP default values as expressions

2023-03-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-03-26T04:39:10+03:00
New Revision: bb4f6c4dca98a47054117708015bb2724256ee83

URL: 
https://github.com/llvm/llvm-project/commit/bb4f6c4dca98a47054117708015bb2724256ee83
DIFF: 
https://github.com/llvm/llvm-project/commit/bb4f6c4dca98a47054117708015bb2724256ee83.diff

LOG: [clang-format] Treat NTTP default values as expressions

clang-format already has logic to threat the right-hand side of an
equals sign. This patch applies that logic to template defaults,
which are likely to be non-template type parameters in which case the
default value should be annotated as an expression.
This should mostly only ever apply to bool and &&.

Fixes https://github.com/llvm/llvm-project/issues/61664

Reviewed By: MyDeveloperDay, owenpan

Differential Revision: https://reviews.llvm.org/D146760

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index dfde6e4e0163..91f9d5719b5a 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1722,6 +1722,11 @@ class AnnotatingParser {
   return false;
 }
 
+// This is the default value of a non-template type parameter, so treat
+// it as an expression.
+if (Contexts.back().ContextKind == tok::less)
+  return true;
+
 Tok = Tok->MatchingParen;
 if (!Tok)
   return false;

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 997630d08e2e..94b3a77ed5a0 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -253,6 +253,14 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
 "};");
   ASSERT_EQ(Tokens.size(), 30u) << Tokens;
   EXPECT_TOKEN(Tokens[14], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("template  struct S {};");
+  ASSERT_EQ(Tokens.size(), 15u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("template  struct S {};");
+  ASSERT_EQ(Tokens.size(), 18u) << Tokens;
+  EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_BinaryOperator);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {



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


[clang] 7ba9101 - [clang-format] Rewrite how indent is reduced for compacted namespaces

2023-02-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-02-25T12:13:53+02:00
New Revision: 7ba91016c6ad4cb8f82ed154753ddeeb524f9a64

URL: 
https://github.com/llvm/llvm-project/commit/7ba91016c6ad4cb8f82ed154753ddeeb524f9a64
DIFF: 
https://github.com/llvm/llvm-project/commit/7ba91016c6ad4cb8f82ed154753ddeeb524f9a64.diff

LOG: [clang-format] Rewrite how indent is reduced for compacted namespaces

The previous version set the indentation directly using IndentForLevel,
however, this has a few caveats, namely:

* IndentForLevel applies to all scopes of the entire program being
  formatted, but this indentation should only be adjusted for scopes
  of namespaces.

* The method it used only set the correct indent amount if one wasn't
  already set for a given level, meaning it didn't work correctly if
  anything with indentation preceded a namespace keyword. This
  includes preprocessing directives if using IndentPPDirectives.

This patch instead reduces the Level of all lines within namespaces
which are compacted by CompactNamespaces. This means they will get
correct indentation using the normal process.

Fixes https://github.com/llvm/llvm-project/issues/60843

Reviewed By: owenpan, MyDeveloperDay, HazardyKnusperkeks

Differential Revision: https://reviews.llvm.org/D144296

Added: 


Modified: 
clang/lib/Format/UnwrappedLineFormatter.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/UnwrappedLineFormatter.cpp 
b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 2e3441e6caec..b0314d6cfa75 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -60,7 +60,8 @@ class LevelIndentTracker {
 Offset = getIndentOffset(*Line.First);
 // Update the indent level cache size so that we can rely on it
 // having the right size in adjustToUnmodifiedline.
-skipLine(Line, /*UnknownIndent=*/true);
+if (Line.Level >= IndentForLevel.size())
+  IndentForLevel.resize(Line.Level + 1, -1);
 if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
 (Line.InPPDirective ||
  (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
@@ -81,13 +82,6 @@ class LevelIndentTracker {
   Indent = Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
   }
 
-  /// Update the indent state given that \p Line indent should be
-  /// skipped.
-  void skipLine(const AnnotatedLine &Line, bool UnknownIndent = false) {
-if (Line.Level >= IndentForLevel.size())
-  IndentForLevel.resize(Line.Level + 1, UnknownIndent ? -1 : Indent);
-  }
-
   /// Update the level indent to adapt to the given \p Line.
   ///
   /// When a line is not formatted, we move the subsequent lines on the same
@@ -367,20 +361,27 @@ class LineJoiner {
 // instead of TheLine->First.
 
 if (Style.CompactNamespaces) {
-  if (auto nsToken = TheLine->First->getNamespaceToken()) {
-int i = 0;
-unsigned closingLine = TheLine->MatchingClosingBlockLineIndex - 1;
-for (; I + 1 + i != E &&
-   nsToken->TokenText == getNamespaceTokenText(I[i + 1]) &&
-   closingLine == I[i + 1]->MatchingClosingBlockLineIndex &&
-   I[i + 1]->Last->TotalLength < Limit;
- i++, --closingLine) {
-  // No extra indent for compacted namespaces.
-  IndentTracker.skipLine(*I[i + 1]);
-
-  Limit -= I[i + 1]->Last->TotalLength;
+  if (const auto *NSToken = TheLine->First->getNamespaceToken()) {
+int J = 1;
+assert(TheLine->MatchingClosingBlockLineIndex > 0);
+for (auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 
1;
+ I + J != E && NSToken->TokenText == getNamespaceTokenText(I[J]) &&
+ ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
+ I[J]->Last->TotalLength < Limit;
+ ++J, --ClosingLineIndex) {
+  Limit -= I[J]->Last->TotalLength;
+
+  // Reduce indent level for bodies of namespaces which were compacted,
+  // but only if their content was indented in the first place.
+  auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
+  auto OutdentBy = I[J]->Level - TheLine->Level;
+  for (auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
+   ++CompactedLine) {
+if (!(*CompactedLine)->InPPDirective)
+  (*CompactedLine)->Level -= OutdentBy;
+  }
 }
-return i;
+return J - 1;
   }
 
   if (auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 97a0bfae2701..437e7b62a15d 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -4431,6 +4431,46 @@ TEST_F(FormatTest, FormatsCompactNamespaces) {

[clang] 393e197 - [clang-format] Don't move qualifiers past pointers-to-member

2023-02-25 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-02-25T12:19:20+02:00
New Revision: 393e197cd6eb8942c4eaec3fd6d05bc2e2289212

URL: 
https://github.com/llvm/llvm-project/commit/393e197cd6eb8942c4eaec3fd6d05bc2e2289212
DIFF: 
https://github.com/llvm/llvm-project/commit/393e197cd6eb8942c4eaec3fd6d05bc2e2289212.diff

LOG: [clang-format] Don't move qualifiers past pointers-to-member

Previously, given a pointer-to-member type such as `Foo const Bar::*`,
clang-format would see the `const Bar::` part as a regular type name
with scope resolution operators, and with `QualifierAlignment: Right` it
would attempt to "fix" it, resulting in `Foo Bar::const *`, a syntax
error.

This patch no longer allows qualifiers to be moved across `::*`.

Fixes https://github.com/llvm/llvm-project/issues/60898

Reviewed By: owenpan, MyDeveloperDay, HazardyKnusperkeks

Differential Revision: https://reviews.llvm.org/D144537

Added: 


Modified: 
clang/lib/Format/QualifierAlignmentFixer.cpp
clang/unittests/Format/QualifierFixerTest.cpp

Removed: 




diff  --git a/clang/lib/Format/QualifierAlignmentFixer.cpp 
b/clang/lib/Format/QualifierAlignmentFixer.cpp
index cef8b36ff758..609b412380f8 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -280,8 +280,11 @@ const FormatToken 
*LeftRightQualifierAlignmentFixer::analyzeRight(
 // The case  `const Foo &&` -> `Foo const &&`
 // The case  `const std::Foo &&` -> `std::Foo const &&`
 // The case  `const std::Foo &&` -> `std::Foo const &&`
-while (Next && Next->isOneOf(tok::identifier, tok::coloncolon))
+// However,  `const Bar::*` remains the same.
+while (Next && Next->isOneOf(tok::identifier, tok::coloncolon) &&
+   !Next->startsSequence(tok::coloncolon, tok::star)) {
   Next = Next->Next;
+}
 if (Next && Next->is(TT_TemplateOpener)) {
   Next = Next->MatchingParen;
   // Move to the end of any template class members e.g.

diff  --git a/clang/unittests/Format/QualifierFixerTest.cpp 
b/clang/unittests/Format/QualifierFixerTest.cpp
index 875ad8353e01..d320eacc52c8 100755
--- a/clang/unittests/Format/QualifierFixerTest.cpp
+++ b/clang/unittests/Format/QualifierFixerTest.cpp
@@ -420,6 +420,16 @@ TEST_F(QualifierFixerTest, RightQualifier) {
 
   // don't adjust macros
   verifyFormat("const INTPTR a;", "const INTPTR a;", Style);
+
+  // Pointers to members
+  verifyFormat("int S::*a;", Style);
+  verifyFormat("int const S::*a;", "const int S:: *a;", Style);
+  verifyFormat("int const S::*const a;", "const int S::* const a;", Style);
+  verifyFormat("int A::*const A::*p1;", Style);
+  verifyFormat("float (C::*p)(int);", Style);
+  verifyFormat("float (C::*const p)(int);", Style);
+  verifyFormat("float (C::*p)(int) const;", Style);
+  verifyFormat("float const (C::*p)(int);", "const float (C::*p)(int);", 
Style);
 }
 
 TEST_F(QualifierFixerTest, LeftQualifier) {
@@ -565,6 +575,16 @@ TEST_F(QualifierFixerTest, LeftQualifier) {
 
   // don't adjust macros
   verifyFormat("INTPTR const a;", "INTPTR const a;", Style);
+
+  // Pointers to members
+  verifyFormat("int S::*a;", Style);
+  verifyFormat("const int S::*a;", "int const S:: *a;", Style);
+  verifyFormat("const int S::*const a;", "int const S::* const a;", Style);
+  verifyFormat("int A::*const A::*p1;", Style);
+  verifyFormat("float (C::*p)(int);", Style);
+  verifyFormat("float (C::*const p)(int);", Style);
+  verifyFormat("float (C::*p)(int) const;", Style);
+  verifyFormat("const float (C::*p)(int);", "float const (C::*p)(int);", 
Style);
 }
 
 TEST_F(QualifierFixerTest, ConstVolatileQualifiersOrder) {



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


[clang] c916390 - [clang-format] Treat &/&& as reference when followed by requires clause

2023-03-14 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-03-14T12:51:34+02:00
New Revision: c9163901c8e118ec0b7d415ae6ef267c4b6d549f

URL: 
https://github.com/llvm/llvm-project/commit/c9163901c8e118ec0b7d415ae6ef267c4b6d549f
DIFF: 
https://github.com/llvm/llvm-project/commit/c9163901c8e118ec0b7d415ae6ef267c4b6d549f.diff

LOG: [clang-format] Treat &/&& as reference when followed by requires clause

Previously, the token annotator would get confused and annotate a member
function's ref qualifier as a binary operator, if said function also had
a requires clause after it.

This patch accounts for that, treating requires clauses more similarly
to `noexcept`, which also comes after the ref qualifier.

Fixes https://github.com/llvm/llvm-project/issues/61270

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D145656

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 5362f2f58e1eb..8613f51cd8a04 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2400,7 +2400,7 @@ class AnnotatingParser {
 
 if (!NextToken ||
 NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept, 
tok::comma,
-   tok::r_paren) ||
+   tok::r_paren, TT_RequiresClause) ||
 NextToken->canBePointerOrReferenceQualifier() ||
 (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) {
   return TT_PointerOrReference;
@@ -3758,8 +3758,9 @@ bool TokenAnnotator::spaceRequiredBetween(const 
AnnotatedLine &Line,
 if (Right.is(TT_BlockComment))
   return true;
 // foo() -> const Bar * override/final
-if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final,
-  tok::kw_noexcept) &&
+// S::foo() & noexcept/requires
+if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final, 
tok::kw_noexcept,
+  TT_RequiresClause) &&
 !Right.is(TT_StartOfName)) {
   return true;
 }

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index bd0d328719bae..1beb6a75c5225 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -24148,6 +24148,14 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"}",
Style);
 
+  verifyFormat("template \n"
+   "int S::bar(T t) &&\n"
+   "  requires F\n"
+   "{\n"
+   "  return 5;\n"
+   "}",
+   Style);
+
   verifyFormat("template \n"
"int bar(T t)\n"
"  requires F;",
@@ -24161,6 +24169,14 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"}",
Style);
 
+  verifyFormat("template \n"
+   "int S::bar(T t) &&\n"
+   "requires F\n"
+   "{\n"
+   "  return 5;\n"
+   "}",
+   Style);
+
   verifyFormat("template \n"
"int bar(T t)\n"
"requires F\n"
@@ -24174,6 +24190,7 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"template  requires Foo void bar() {}\n"
"template  void bar() requires Foo {}\n"
"template  void bar() requires Foo;\n"
+   "template  void S::bar() && requires Foo {}\n"
"template  requires Foo Bar(T) -> Bar;",
Style);
 
@@ -24185,6 +24202,8 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"requires Foo void bar() {}\n"
"template \n"
"void bar() requires Foo {}\n"
+   "template \n"
+   "void S::bar() && requires Foo {}\n"
"template \n"
"requires Foo Baz(T) -> Baz;",
ColumnStyle);
@@ -24229,6 +24248,9 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"void bar()\n"
"requires Foo;\n"
"template \n"
+   "void S::bar() &&\n"
+   "requires Foo {}\n"
+   "template \n"
"requires Foo Bar(T) -> Bar;",
Style);
 
@@ -24259,6 +24281,9 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"void bar()\n"
"  requires Foo {}\n"
"template \n"
+   "void S::bar() &&\n"
+   "  requires Foo {}\n"
+   "template \n"
"  requires Foo Bar(T) -> Bar;",
Style);
 
@@ -24289,6 +24314,9 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"void bar() requires Foo\n"
"{}\n"
"template  void bar() requires Foo;\n"
+  

[clang] 50acd67 - [clang-format] Don't format typename template parameters as expression

2023-04-01 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-04-01T16:52:51+03:00
New Revision: 50acd67018a53239f11a2889c28f77a1c7dc8c6b

URL: 
https://github.com/llvm/llvm-project/commit/50acd67018a53239f11a2889c28f77a1c7dc8c6b
DIFF: 
https://github.com/llvm/llvm-project/commit/50acd67018a53239f11a2889c28f77a1c7dc8c6b.diff

LOG: [clang-format] Don't format typename template parameters as expression

bb4f6c4dca98a47054117708015bb2724256ee83 made it so that template
parameter defaults are seen akin to assignments and formatted as
expressions, however, the patch did this for all template parameters,
even for `typename` template parameters.

This patch formats `typename` and `class` template parameters as types.

Fixes https://github.com/llvm/llvm-project/issues/61841

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D147318

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 1fc190e56c28..b1060bde9ded 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1723,10 +1723,13 @@ class AnnotatingParser {
   return false;
 }
 
-// This is the default value of a non-template type parameter, so treat
-// it as an expression.
-if (Contexts.back().ContextKind == tok::less)
-  return true;
+// This is the default value of a template parameter, determine if it's
+// type or non-type.
+if (Contexts.back().ContextKind == tok::less) {
+  assert(Current.Previous->Previous);
+  return !Current.Previous->Previous->isOneOf(tok::kw_typename,
+  tok::kw_class);
+}
 
 Tok = Tok->MatchingParen;
 if (!Tok)

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index bea85e5bdba2..19b1d96f75ab 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -261,6 +261,15 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
   Tokens = annotate("template  struct S {};");
   ASSERT_EQ(Tokens.size(), 18u) << Tokens;
   EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("template  struct S {};");
+  ASSERT_EQ(Tokens.size(), 17u) << Tokens;
+  EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_PointerOrReference);
+
+  Tokens = annotate("template  struct S {};");
+  ASSERT_EQ(Tokens.size(), 19u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_FunctionTypeLParen);
+  EXPECT_TOKEN(Tokens[7], tok::star, TT_PointerOrReference);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {



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


[clang] fd86789 - [clang-format] Don't allow variable decls to have trailing return arrows

2023-04-03 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-04-03T15:54:21+03:00
New Revision: fd86789962964a98157e8159c3d95cdc241942e3

URL: 
https://github.com/llvm/llvm-project/commit/fd86789962964a98157e8159c3d95cdc241942e3
DIFF: 
https://github.com/llvm/llvm-project/commit/fd86789962964a98157e8159c3d95cdc241942e3.diff

LOG: [clang-format] Don't allow variable decls to have trailing return arrows

The heuristic for determining if an arrow is a trailing return arrow
looks for the auto keyword, along with parentheses. This isn't
sufficient, since it also triggers on variable declarations with an auto
type, and with an arrow operator.

This patch makes sure a function declaration is being parsed, instead of
any other declaration.

Fixes https://github.com/llvm/llvm-project/issues/61469

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D147377

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index b1060bde9dedd..5171952dba43c 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1922,7 +1922,7 @@ class AnnotatingParser {
Style.Language == FormatStyle::LK_Java) {
   Current.setType(TT_LambdaArrow);
 } else if (Current.is(tok::arrow) && AutoFound &&
-   (Line.MustBeDeclaration || Line.InPPDirective) &&
+   (Line.MightBeFunctionDecl || Line.InPPDirective) &&
Current.NestingLevel == 0 &&
!Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) {
   // not auto operator->() -> xxx;

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 19b1d96f75ab2..dc2fd4d10c76c 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -1477,6 +1477,72 @@ TEST_F(TokenAnnotatorTest, 
UnderstandsC11GenericSelection) {
   EXPECT_TOKEN(Tokens[9], tok::colon, TT_GenericSelectionColon);
 }
 
+TEST_F(TokenAnnotatorTest, UnderstandsTrailingReturnArrow) {
+  auto Tokens = annotate("auto f() -> int;");
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow);
+
+  Tokens = annotate("auto operator->() -> int;");
+  ASSERT_EQ(Tokens.size(), 9u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::arrow, TT_OverloadedOperator);
+  EXPECT_TOKEN(Tokens[5], tok::arrow, TT_TrailingReturnArrow);
+
+  Tokens = annotate("auto operator++(int) -> int;");
+  ASSERT_EQ(Tokens.size(), 10u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::arrow, TT_TrailingReturnArrow);
+
+  Tokens = annotate("auto operator=() -> int;");
+  ASSERT_EQ(Tokens.size(), 9u) << Tokens;
+  EXPECT_TOKEN(Tokens[5], tok::arrow, TT_TrailingReturnArrow);
+
+  Tokens = annotate("auto operator=(int) -> int;");
+  ASSERT_EQ(Tokens.size(), 10u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::arrow, TT_TrailingReturnArrow);
+
+  Tokens = annotate("auto foo() -> auto { return Val; }");
+  ASSERT_EQ(Tokens.size(), 12u) << Tokens;
+  EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow);
+
+  Tokens = annotate("struct S { auto bar() const -> int; };");
+  ASSERT_EQ(Tokens.size(), 14u) << Tokens;
+  EXPECT_TOKEN(Tokens[8], tok::arrow, TT_TrailingReturnArrow);
+
+  // Not trailing return arrows
+  Tokens = annotate("auto a = b->c;");
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[4], tok::arrow, TT_Unknown);
+
+  Tokens = annotate("auto a = (b)->c;");
+  ASSERT_EQ(Tokens.size(), 10u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::arrow, TT_Unknown);
+
+  Tokens = annotate("auto a = b()->c;");
+  ASSERT_EQ(Tokens.size(), 10u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::arrow, TT_Unknown);
+
+  Tokens = annotate("auto a = b->c();");
+  ASSERT_EQ(Tokens.size(), 10u) << Tokens;
+  EXPECT_TOKEN(Tokens[4], tok::arrow, TT_Unknown);
+
+  Tokens = annotate("decltype(auto) a = b()->c;");
+  ASSERT_EQ(Tokens.size(), 13u) << Tokens;
+  EXPECT_TOKEN(Tokens[9], tok::arrow, TT_Unknown);
+
+  Tokens = annotate("void f() { auto a = b->c(); }");
+  ASSERT_EQ(Tokens.size(), 16u) << Tokens;
+  EXPECT_TOKEN(Tokens[9], tok::arrow, TT_Unknown);
+
+  Tokens = annotate("void f() { auto a = b()->c; }");
+  ASSERT_EQ(Tokens.size(), 16u) << Tokens;
+  EXPECT_TOKEN(Tokens[11], tok::arrow, TT_Unknown);
+
+  // Mixed
+  Tokens = annotate("auto f() -> int { auto a = b()->c; }");
+  ASSERT_EQ(Tokens.size(), 18u) << Tokens;
+  EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow);
+  EXPECT_TOKEN(Tokens[13], tok::arrow, TT_Unknown);
+}
+
 TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) {
   auto Annotate = [this](llvm::StringRef Code) {
 return annotate(Code, getLLVMStyle(FormatStyle::LK_Verilog));




[clang] 5dc94b3 - [clang-format] Don't modify template arguments on the LHS of assignment

2023-04-11 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2023-04-12T00:33:17+03:00
New Revision: 5dc94b3356bd861d304e1ab61f7bb9ef33bf46b3

URL: 
https://github.com/llvm/llvm-project/commit/5dc94b3356bd861d304e1ab61f7bb9ef33bf46b3
DIFF: 
https://github.com/llvm/llvm-project/commit/5dc94b3356bd861d304e1ab61f7bb9ef33bf46b3.diff

LOG: [clang-format] Don't modify template arguments on the LHS of assignment

After clang-format has determined that an equals sign starts an
expression, it will also go backwards and modify any star/amp/ampamp
binary operators on the left side of the assignment to be
pointers/references instead.

There already exists logic to skip over contents of parentheses and
square brackets, but this patch also expands that logic to apply to
angle brackets. This is so that binary operators inside of template
arguments would not be touched, primary arguments to non-type template
parameters.

Fixes https://github.com/llvm/llvm-project/issues/62055

Reviewed By: owenpan, MyDeveloperDay, HazardyKnusperkeks

Differential Revision: https://reviews.llvm.org/D148024

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index e7de8fd9a2174..18fccca622caa 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1819,7 +1819,7 @@ class AnnotatingParser {
  Previous && Previous->Previous &&
  !Previous->Previous->isOneOf(tok::comma, tok::semi);
  Previous = Previous->Previous) {
-  if (Previous->isOneOf(tok::r_square, tok::r_paren)) {
+  if (Previous->isOneOf(tok::r_square, tok::r_paren, tok::greater)) {
 Previous = Previous->MatchingParen;
 if (!Previous)
   break;

diff  --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 0fc6442773936..facd0060d0fde 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -270,6 +270,18 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
   ASSERT_EQ(Tokens.size(), 19u) << Tokens;
   EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_FunctionTypeLParen);
   EXPECT_TOKEN(Tokens[7], tok::star, TT_PointerOrReference);
+
+  Tokens = annotate("Foo a = {};");
+  ASSERT_EQ(Tokens.size(), 12u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("Foo a = {};");
+  ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+  EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference);
+
+  Tokens = annotate("template * = nullptr> void 
f();");
+  ASSERT_EQ(Tokens.size(), 19u) << Tokens;
+  EXPECT_TOKEN(Tokens[5], tok::ampamp, TT_BinaryOperator);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {



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


[clang] 8384347 - [clang-format] Don't require deduction guides to be templates

2022-12-16 Thread Emilia Dreamer via cfe-commits

Author: Emilia Dreamer
Date: 2022-12-16T23:26:05+02:00
New Revision: 8384347997f87d73c70f194d90c3efb7ddf6f963

URL: 
https://github.com/llvm/llvm-project/commit/8384347997f87d73c70f194d90c3efb7ddf6f963
DIFF: 
https://github.com/llvm/llvm-project/commit/8384347997f87d73c70f194d90c3efb7ddf6f963.diff

LOG: [clang-format] Don't require deduction guides to be templates

The C++ standard doesn't require that class template deduction guides
be templates themselves, but previously `isDeductionGuide` would assert
for the existence of a template closer or requires clause closer before
the deduction guide declaration.

This patch simply removes that check. Because of this, a test which
asserted that `x()->x<1>;` *isn't* a deduction guide failed, as it is
now formatted as a deduction guide. However, as @JohelEGP demonstrated,
it is [possible to make that a viable deduction guide][1].

Thus, that test has been removed, but other tests related to
non-template class template deduction guides have been added.

Fixes https://github.com/llvm/llvm-project/issues/55142

[1]: https://compiler-explorer.com/z/Wx3K6d5K9

Reviewed By: HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D139416

Added: 


Modified: 
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index cc0b7719b9e52..1fdceabbabc89 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1804,21 +1804,8 @@ class AnnotatingParser {
 FormatToken *LeadingIdentifier =
 Current.Previous->MatchingParen->Previous;
 
-// Differentiate a deduction guide by seeing the
-// > of the template prior to the leading identifier.
-if (LeadingIdentifier) {
-  FormatToken *PriorLeadingIdentifier = LeadingIdentifier->Previous;
-  // Skip back past explicit decoration
-  if (PriorLeadingIdentifier &&
-  PriorLeadingIdentifier->is(tok::kw_explicit)) {
-PriorLeadingIdentifier = PriorLeadingIdentifier->Previous;
-  }
-
-  return PriorLeadingIdentifier &&
- (PriorLeadingIdentifier->is(TT_TemplateCloser) ||
-  PriorLeadingIdentifier->ClosesRequiresClause) &&
- LeadingIdentifier->TokenText == Current.Next->TokenText;
-}
+return LeadingIdentifier &&
+   LeadingIdentifier->TokenText == Current.Next->TokenText;
   }
 }
 return false;

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 00f5c4bc80c7e..79e2979fcab5d 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -8008,12 +8008,14 @@ TEST_F(FormatTest, DeductionGuides) {
   verifyFormat("template  x() -> x<1>;");
   verifyFormat("template  explicit x(T &) -> x<1>;");
 
+  verifyFormat("A(const char *) -> A;");
+  verifyFormat("A() -> A;");
+
   // Ensure not deduction guides.
   verifyFormat("c()->f();");
   verifyFormat("x()->foo<1>;");
   verifyFormat("x = p->foo<3>();");
   verifyFormat("x()->x<1>();");
-  verifyFormat("x()->x<1>;");
 }
 
 TEST_F(FormatTest, BreaksFunctionDeclarationsWithTrailingTokens) {



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