[clang] [clang-format] Correctly annotate list init braces of class types (PR #89706)

2024-04-23 Thread Owen Pan via cfe-commits

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


[clang] [clang-format] Correctly annotate list init braces of class types (PR #89706)

2024-04-23 Thread Björn Schäpers via cfe-commits

https://github.com/HazardyKnusperkeks approved this pull request.


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


[clang] [clang-format] Correctly annotate list init braces of class types (PR #89706)

2024-04-23 Thread via cfe-commits

https://github.com/mydeveloperday approved this pull request.


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


[clang] [clang-format] Correctly annotate list init braces of class types (PR #89706)

2024-04-22 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-format

Author: Owen Pan (owenca)


Changes

Fixes #71939.

---
Full diff: https://github.com/llvm/llvm-project/pull/89706.diff


2 Files Affected:

- (modified) clang/lib/Format/UnwrappedLineParser.cpp (+35-6) 
- (modified) clang/unittests/Format/TokenAnnotatorTest.cpp (+60) 


``diff
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 603268f771ac52..6e4e6901e473f7 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -819,8 +819,11 @@ FormatToken *UnwrappedLineParser::parseBlock(bool 
MustBeDeclaration,
 return IfLBrace;
   }
 
-  if (FormatTok->is(tok::r_brace) && Tok->is(TT_NamespaceLBrace))
-FormatTok->setFinalizedType(TT_NamespaceRBrace);
+  if (FormatTok->is(tok::r_brace)) {
+FormatTok->setBlockKind(BK_Block);
+if (Tok->is(TT_NamespaceLBrace))
+  FormatTok->setFinalizedType(TT_NamespaceRBrace);
+  }
 
   const bool IsFunctionRBrace =
   FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
@@ -3910,6 +3913,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
   const FormatToken  = *FormatTok;
   nextToken();
 
+  const FormatToken *ClassName = nullptr;
+  bool IsDerived = false;
   auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
 return Tok->is(tok::identifier) && Tok->TokenText != 
Tok->TokenText.upper();
   };
@@ -3934,15 +3939,35 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) 
{
 }
 if (FormatTok->is(tok::l_square) && handleCppAttributes())
   continue;
+const auto *Previous = FormatTok;
 nextToken();
-// We can have macros in between 'class' and the class name.
-if (!IsNonMacroIdentifier(FormatTok->Previous) &&
-FormatTok->is(tok::l_paren)) {
-  parseParens();
+switch (FormatTok->Tok.getKind()) {
+case tok::l_paren:
+  // We can have macros in between 'class' and the class name.
+  if (!IsNonMacroIdentifier(Previous))
+parseParens();
+  break;
+case tok::coloncolon:
+  break;
+default:
+  if (!ClassName && Previous->is(tok::identifier))
+ClassName = Previous;
 }
   }
 
+  auto IsListInitialization = [&] {
+if (!ClassName || IsDerived)
+  return false;
+assert(FormatTok->is(tok::l_brace));
+const auto *Prev = FormatTok->getPreviousNonComment();
+assert(Prev);
+return Prev != ClassName && Prev->is(tok::identifier) &&
+   Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
+  };
+
   if (FormatTok->isOneOf(tok::colon, tok::less)) {
+if (FormatTok->is(tok::colon))
+  IsDerived = true;
 int AngleNestingLevel = 0;
 do {
   if (FormatTok->is(tok::less))
@@ -3955,6 +3980,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
 break;
   }
   if (FormatTok->is(tok::l_brace)) {
+if (AngleNestingLevel == 0 && IsListInitialization())
+  return;
 calculateBraceTypes(/*ExpectClassBody=*/true);
 if (!tryToParseBracedList())
   break;
@@ -3999,6 +4026,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
 }
   };
   if (FormatTok->is(tok::l_brace)) {
+if (IsListInitialization())
+  return;
 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
 FormatTok->setFinalizedType(OpenBraceType);
 if (ParseAsExpr) {
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 34999b7376397b..6b8ab441cb46f8 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2855,6 +2855,66 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
   ASSERT_EQ(Tokens.size(), 18u) << Tokens;
   EXPECT_BRACE_KIND(Tokens[8], BK_BracedInit);
   EXPECT_BRACE_KIND(Tokens[16], BK_BracedInit);
+
+  Tokens = annotate("struct {};");
+  ASSERT_EQ(Tokens.size(), 5u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[1], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[2], BK_Block);
+
+  Tokens = annotate("struct : Base {};");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[3], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[4], BK_Block);
+
+  Tokens = annotate("struct Foo {};");
+  ASSERT_EQ(Tokens.size(), 6u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[2], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[3], BK_Block);
+
+  Tokens = annotate("struct ::Foo {};");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[3], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[4], BK_Block);
+
+  Tokens = annotate("struct NS::Foo {};");
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[4], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[5], BK_Block);
+
+  Tokens = annotate("struct Foo {};");
+  ASSERT_EQ(Tokens.size(), 9u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[5], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[6], BK_Block);
+
+  Tokens = annotate("struct Foo final {};");
+  

[clang] [clang-format] Correctly annotate list init braces of class types (PR #89706)

2024-04-22 Thread Owen Pan via cfe-commits

https://github.com/owenca created 
https://github.com/llvm/llvm-project/pull/89706

Fixes #71939.

>From 0fab05c4ab7ac95d7c08dd23a0441dc28c2ef813 Mon Sep 17 00:00:00 2001
From: Owen Pan 
Date: Mon, 22 Apr 2024 21:56:31 -0700
Subject: [PATCH] [clang-format] Correctly annotate list init braces of class
 types

Fixes #71939.
---
 clang/lib/Format/UnwrappedLineParser.cpp  | 41 +++--
 clang/unittests/Format/TokenAnnotatorTest.cpp | 60 +++
 2 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index 603268f771ac52..6e4e6901e473f7 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -819,8 +819,11 @@ FormatToken *UnwrappedLineParser::parseBlock(bool 
MustBeDeclaration,
 return IfLBrace;
   }
 
-  if (FormatTok->is(tok::r_brace) && Tok->is(TT_NamespaceLBrace))
-FormatTok->setFinalizedType(TT_NamespaceRBrace);
+  if (FormatTok->is(tok::r_brace)) {
+FormatTok->setBlockKind(BK_Block);
+if (Tok->is(TT_NamespaceLBrace))
+  FormatTok->setFinalizedType(TT_NamespaceRBrace);
+  }
 
   const bool IsFunctionRBrace =
   FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
@@ -3910,6 +3913,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
   const FormatToken  = *FormatTok;
   nextToken();
 
+  const FormatToken *ClassName = nullptr;
+  bool IsDerived = false;
   auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
 return Tok->is(tok::identifier) && Tok->TokenText != 
Tok->TokenText.upper();
   };
@@ -3934,15 +3939,35 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) 
{
 }
 if (FormatTok->is(tok::l_square) && handleCppAttributes())
   continue;
+const auto *Previous = FormatTok;
 nextToken();
-// We can have macros in between 'class' and the class name.
-if (!IsNonMacroIdentifier(FormatTok->Previous) &&
-FormatTok->is(tok::l_paren)) {
-  parseParens();
+switch (FormatTok->Tok.getKind()) {
+case tok::l_paren:
+  // We can have macros in between 'class' and the class name.
+  if (!IsNonMacroIdentifier(Previous))
+parseParens();
+  break;
+case tok::coloncolon:
+  break;
+default:
+  if (!ClassName && Previous->is(tok::identifier))
+ClassName = Previous;
 }
   }
 
+  auto IsListInitialization = [&] {
+if (!ClassName || IsDerived)
+  return false;
+assert(FormatTok->is(tok::l_brace));
+const auto *Prev = FormatTok->getPreviousNonComment();
+assert(Prev);
+return Prev != ClassName && Prev->is(tok::identifier) &&
+   Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
+  };
+
   if (FormatTok->isOneOf(tok::colon, tok::less)) {
+if (FormatTok->is(tok::colon))
+  IsDerived = true;
 int AngleNestingLevel = 0;
 do {
   if (FormatTok->is(tok::less))
@@ -3955,6 +3980,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
 break;
   }
   if (FormatTok->is(tok::l_brace)) {
+if (AngleNestingLevel == 0 && IsListInitialization())
+  return;
 calculateBraceTypes(/*ExpectClassBody=*/true);
 if (!tryToParseBracedList())
   break;
@@ -3999,6 +4026,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
 }
   };
   if (FormatTok->is(tok::l_brace)) {
+if (IsListInitialization())
+  return;
 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
 FormatTok->setFinalizedType(OpenBraceType);
 if (ParseAsExpr) {
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp 
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 34999b7376397b..6b8ab441cb46f8 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2855,6 +2855,66 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
   ASSERT_EQ(Tokens.size(), 18u) << Tokens;
   EXPECT_BRACE_KIND(Tokens[8], BK_BracedInit);
   EXPECT_BRACE_KIND(Tokens[16], BK_BracedInit);
+
+  Tokens = annotate("struct {};");
+  ASSERT_EQ(Tokens.size(), 5u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[1], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[2], BK_Block);
+
+  Tokens = annotate("struct : Base {};");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[3], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[4], BK_Block);
+
+  Tokens = annotate("struct Foo {};");
+  ASSERT_EQ(Tokens.size(), 6u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[2], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[3], BK_Block);
+
+  Tokens = annotate("struct ::Foo {};");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[3], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[4], BK_Block);
+
+  Tokens = annotate("struct NS::Foo {};");
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[4], BK_Block);
+  EXPECT_BRACE_KIND(Tokens[5], BK_Block);
+
+  Tokens = annotate("struct Foo {};");
+