Skip to content

Commit 7b4e71b

Browse files
owencatstellar
authored andcommitted
[clang-format] Don't annotate left brace of class as FunctionLBrace
The l_brace of class/struct/union was incorrectly annotated as TT_FunctionLBrace in the presence of attributes. This in turn would cause the RemoveSemicolon option to remove the semicolon at the end of the declaration, resulting in invalid code being generated. Fixes llvm#61188. Differential Revision: https://reviews.llvm.org/D145344 (cherry picked from commit a02c3af)
1 parent a146bdc commit 7b4e71b

File tree

3 files changed

+12
-8
lines changed

3 files changed

+12
-8
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3849,13 +3849,13 @@ void UnwrappedLineParser::parseJavaEnumBody() {
38493849
void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
38503850
const FormatToken &InitialToken = *FormatTok;
38513851
nextToken();
3852+
handleAttributes();
38523853

38533854
// The actual identifier can be a nested name specifier, and in macros
38543855
// it is often token-pasted.
3855-
// An [[attribute]] can be before the identifier.
38563856
while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
38573857
tok::kw___attribute, tok::kw___declspec,
3858-
tok::kw_alignas, tok::l_square, tok::r_square) ||
3858+
tok::kw_alignas) ||
38593859
((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
38603860
FormatTok->isOneOf(tok::period, tok::comma))) {
38613861
if (Style.isJavaScript() &&
@@ -3873,15 +3873,10 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
38733873
FormatTok->is(tok::identifier) &&
38743874
FormatTok->TokenText != FormatTok->TokenText.upper();
38753875
nextToken();
3876-
// We can have macros or attributes in between 'class' and the class name.
3876+
// We can have macros in between 'class' and the class name.
38773877
if (!IsNonMacroIdentifier) {
38783878
if (FormatTok->is(tok::l_paren)) {
38793879
parseParens();
3880-
} else if (FormatTok->is(TT_AttributeSquare)) {
3881-
parseSquare();
3882-
// Consume the closing TT_AttributeSquare.
3883-
if (FormatTok->Next && FormatTok->is(TT_AttributeSquare))
3884-
nextToken();
38853880
}
38863881
}
38873882
}

clang/unittests/Format/FormatTest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25207,6 +25207,11 @@ TEST_F(FormatTest, RemoveSemicolon) {
2520725207
"}",
2520825208
Style);
2520925209

25210+
verifyFormat("class [[deprecated(\"\")]] C {\n"
25211+
" int i;\n"
25212+
"};",
25213+
Style);
25214+
2521025215
verifyIncompleteFormat("class C final [[deprecated(l]] {});", Style);
2521125216

2521225217
// These tests are here to show a problem that may not be easily

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsClasses) {
278278
Tokens = annotate("const class {} c;");
279279
EXPECT_EQ(Tokens.size(), 7u) << Tokens;
280280
EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_ClassLBrace);
281+
282+
Tokens = annotate("class [[deprecated(\"\")]] C { int i; };");
283+
EXPECT_EQ(Tokens.size(), 17u) << Tokens;
284+
EXPECT_TOKEN(Tokens[10], tok::l_brace, TT_ClassLBrace);
281285
}
282286

283287
TEST_F(TokenAnnotatorTest, UnderstandsStructs) {

0 commit comments

Comments
 (0)