Skip to content

Commit 469c8a0

Browse files
authored
[clang-format] Correctly annotate list init braces of class types (#89706)
Fixes #71939.
1 parent cc73c5c commit 469c8a0

File tree

2 files changed

+95
-6
lines changed

2 files changed

+95
-6
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,11 @@ FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration,
819819
return IfLBrace;
820820
}
821821

822-
if (FormatTok->is(tok::r_brace) && Tok->is(TT_NamespaceLBrace))
823-
FormatTok->setFinalizedType(TT_NamespaceRBrace);
822+
if (FormatTok->is(tok::r_brace)) {
823+
FormatTok->setBlockKind(BK_Block);
824+
if (Tok->is(TT_NamespaceLBrace))
825+
FormatTok->setFinalizedType(TT_NamespaceRBrace);
826+
}
824827

825828
const bool IsFunctionRBrace =
826829
FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
@@ -3910,6 +3913,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
39103913
const FormatToken &InitialToken = *FormatTok;
39113914
nextToken();
39123915

3916+
const FormatToken *ClassName = nullptr;
3917+
bool IsDerived = false;
39133918
auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
39143919
return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();
39153920
};
@@ -3934,15 +3939,35 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
39343939
}
39353940
if (FormatTok->is(tok::l_square) && handleCppAttributes())
39363941
continue;
3942+
const auto *Previous = FormatTok;
39373943
nextToken();
3938-
// We can have macros in between 'class' and the class name.
3939-
if (!IsNonMacroIdentifier(FormatTok->Previous) &&
3940-
FormatTok->is(tok::l_paren)) {
3941-
parseParens();
3944+
switch (FormatTok->Tok.getKind()) {
3945+
case tok::l_paren:
3946+
// We can have macros in between 'class' and the class name.
3947+
if (!IsNonMacroIdentifier(Previous))
3948+
parseParens();
3949+
break;
3950+
case tok::coloncolon:
3951+
break;
3952+
default:
3953+
if (!ClassName && Previous->is(tok::identifier))
3954+
ClassName = Previous;
39423955
}
39433956
}
39443957

3958+
auto IsListInitialization = [&] {
3959+
if (!ClassName || IsDerived)
3960+
return false;
3961+
assert(FormatTok->is(tok::l_brace));
3962+
const auto *Prev = FormatTok->getPreviousNonComment();
3963+
assert(Prev);
3964+
return Prev != ClassName && Prev->is(tok::identifier) &&
3965+
Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
3966+
};
3967+
39453968
if (FormatTok->isOneOf(tok::colon, tok::less)) {
3969+
if (FormatTok->is(tok::colon))
3970+
IsDerived = true;
39463971
int AngleNestingLevel = 0;
39473972
do {
39483973
if (FormatTok->is(tok::less))
@@ -3955,6 +3980,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
39553980
break;
39563981
}
39573982
if (FormatTok->is(tok::l_brace)) {
3983+
if (AngleNestingLevel == 0 && IsListInitialization())
3984+
return;
39583985
calculateBraceTypes(/*ExpectClassBody=*/true);
39593986
if (!tryToParseBracedList())
39603987
break;
@@ -3999,6 +4026,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
39994026
}
40004027
};
40014028
if (FormatTok->is(tok::l_brace)) {
4029+
if (IsListInitialization())
4030+
return;
40024031
auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
40034032
FormatTok->setFinalizedType(OpenBraceType);
40044033
if (ParseAsExpr) {

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,6 +2855,66 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
28552855
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
28562856
EXPECT_BRACE_KIND(Tokens[8], BK_BracedInit);
28572857
EXPECT_BRACE_KIND(Tokens[16], BK_BracedInit);
2858+
2859+
Tokens = annotate("struct {};");
2860+
ASSERT_EQ(Tokens.size(), 5u) << Tokens;
2861+
EXPECT_BRACE_KIND(Tokens[1], BK_Block);
2862+
EXPECT_BRACE_KIND(Tokens[2], BK_Block);
2863+
2864+
Tokens = annotate("struct : Base {};");
2865+
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
2866+
EXPECT_BRACE_KIND(Tokens[3], BK_Block);
2867+
EXPECT_BRACE_KIND(Tokens[4], BK_Block);
2868+
2869+
Tokens = annotate("struct Foo {};");
2870+
ASSERT_EQ(Tokens.size(), 6u) << Tokens;
2871+
EXPECT_BRACE_KIND(Tokens[2], BK_Block);
2872+
EXPECT_BRACE_KIND(Tokens[3], BK_Block);
2873+
2874+
Tokens = annotate("struct ::Foo {};");
2875+
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
2876+
EXPECT_BRACE_KIND(Tokens[3], BK_Block);
2877+
EXPECT_BRACE_KIND(Tokens[4], BK_Block);
2878+
2879+
Tokens = annotate("struct NS::Foo {};");
2880+
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
2881+
EXPECT_BRACE_KIND(Tokens[4], BK_Block);
2882+
EXPECT_BRACE_KIND(Tokens[5], BK_Block);
2883+
2884+
Tokens = annotate("struct Foo<int> {};");
2885+
ASSERT_EQ(Tokens.size(), 9u) << Tokens;
2886+
EXPECT_BRACE_KIND(Tokens[5], BK_Block);
2887+
EXPECT_BRACE_KIND(Tokens[6], BK_Block);
2888+
2889+
Tokens = annotate("struct Foo final {};");
2890+
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
2891+
EXPECT_BRACE_KIND(Tokens[3], BK_Block);
2892+
EXPECT_BRACE_KIND(Tokens[4], BK_Block);
2893+
2894+
Tokens = annotate("struct [[foo]] [[bar]] Foo final : Base1, Base2 {};");
2895+
ASSERT_EQ(Tokens.size(), 21u) << Tokens;
2896+
EXPECT_BRACE_KIND(Tokens[17], BK_Block);
2897+
EXPECT_BRACE_KIND(Tokens[18], BK_Block);
2898+
2899+
Tokens = annotate("struct Foo x{};");
2900+
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
2901+
EXPECT_BRACE_KIND(Tokens[3], BK_BracedInit);
2902+
EXPECT_BRACE_KIND(Tokens[4], BK_BracedInit);
2903+
2904+
Tokens = annotate("struct ::Foo x{};");
2905+
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
2906+
EXPECT_BRACE_KIND(Tokens[4], BK_BracedInit);
2907+
EXPECT_BRACE_KIND(Tokens[5], BK_BracedInit);
2908+
2909+
Tokens = annotate("struct NS::Foo x{};");
2910+
ASSERT_EQ(Tokens.size(), 9u) << Tokens;
2911+
EXPECT_BRACE_KIND(Tokens[5], BK_BracedInit);
2912+
EXPECT_BRACE_KIND(Tokens[6], BK_BracedInit);
2913+
2914+
Tokens = annotate("struct Foo<int> x{};");
2915+
ASSERT_EQ(Tokens.size(), 10u) << Tokens;
2916+
EXPECT_BRACE_KIND(Tokens[6], BK_BracedInit);
2917+
EXPECT_BRACE_KIND(Tokens[7], BK_BracedInit);
28582918
}
28592919

28602920
TEST_F(TokenAnnotatorTest, UnderstandsElaboratedTypeSpecifier) {

0 commit comments

Comments
 (0)