[clang] [clang-format] Correctly annotate list init braces of class types (PR #89706)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 22 21:58:40 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-format
Author: Owen Pan (owenca)
<details>
<summary>Changes</summary>
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 &InitialToken = *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<int> {};");
+ 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 {};");
+ ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+ EXPECT_BRACE_KIND(Tokens[3], BK_Block);
+ EXPECT_BRACE_KIND(Tokens[4], BK_Block);
+
+ Tokens = annotate("struct [[foo]] [[bar]] Foo final : Base1, Base2 {};");
+ ASSERT_EQ(Tokens.size(), 21u) << Tokens;
+ EXPECT_BRACE_KIND(Tokens[17], BK_Block);
+ EXPECT_BRACE_KIND(Tokens[18], BK_Block);
+
+ Tokens = annotate("struct Foo x{};");
+ ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+ EXPECT_BRACE_KIND(Tokens[3], BK_BracedInit);
+ EXPECT_BRACE_KIND(Tokens[4], BK_BracedInit);
+
+ Tokens = annotate("struct ::Foo x{};");
+ ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+ EXPECT_BRACE_KIND(Tokens[4], BK_BracedInit);
+ EXPECT_BRACE_KIND(Tokens[5], BK_BracedInit);
+
+ Tokens = annotate("struct NS::Foo x{};");
+ ASSERT_EQ(Tokens.size(), 9u) << Tokens;
+ EXPECT_BRACE_KIND(Tokens[5], BK_BracedInit);
+ EXPECT_BRACE_KIND(Tokens[6], BK_BracedInit);
+
+ Tokens = annotate("struct Foo<int> x{};");
+ ASSERT_EQ(Tokens.size(), 10u) << Tokens;
+ EXPECT_BRACE_KIND(Tokens[6], BK_BracedInit);
+ EXPECT_BRACE_KIND(Tokens[7], BK_BracedInit);
}
TEST_F(TokenAnnotatorTest, UnderstandsElaboratedTypeSpecifier) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/89706
More information about the cfe-commits
mailing list