[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 #61188. Differential Revision: https://reviews.llvm.org/D145344
This commit is contained in:
@@ -3701,13 +3701,13 @@ void UnwrappedLineParser::parseJavaEnumBody() {
|
||||
void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
|
||||
const FormatToken &InitialToken = *FormatTok;
|
||||
nextToken();
|
||||
handleAttributes();
|
||||
|
||||
// The actual identifier can be a nested name specifier, and in macros
|
||||
// it is often token-pasted.
|
||||
// An [[attribute]] can be before the identifier.
|
||||
while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
|
||||
tok::kw___attribute, tok::kw___declspec,
|
||||
tok::kw_alignas, tok::l_square, tok::r_square) ||
|
||||
tok::kw_alignas) ||
|
||||
((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
|
||||
FormatTok->isOneOf(tok::period, tok::comma))) {
|
||||
if (Style.isJavaScript() &&
|
||||
@@ -3725,15 +3725,10 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
|
||||
FormatTok->is(tok::identifier) &&
|
||||
FormatTok->TokenText != FormatTok->TokenText.upper();
|
||||
nextToken();
|
||||
// We can have macros or attributes in between 'class' and the class name.
|
||||
// We can have macros in between 'class' and the class name.
|
||||
if (!IsNonMacroIdentifier) {
|
||||
if (FormatTok->is(tok::l_paren)) {
|
||||
parseParens();
|
||||
} else if (FormatTok->is(TT_AttributeSquare)) {
|
||||
parseSquare();
|
||||
// Consume the closing TT_AttributeSquare.
|
||||
if (FormatTok->Next && FormatTok->is(TT_AttributeSquare))
|
||||
nextToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25233,6 +25233,11 @@ TEST_F(FormatTest, RemoveSemicolon) {
|
||||
"}",
|
||||
Style);
|
||||
|
||||
verifyFormat("class [[deprecated(\"\")]] C {\n"
|
||||
" int i;\n"
|
||||
"};",
|
||||
Style);
|
||||
|
||||
verifyIncompleteFormat("class C final [[deprecated(l]] {});", Style);
|
||||
|
||||
// These tests are here to show a problem that may not be easily
|
||||
|
||||
@@ -345,6 +345,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsClasses) {
|
||||
Tokens = annotate("const class {} c;");
|
||||
EXPECT_EQ(Tokens.size(), 7u) << Tokens;
|
||||
EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_ClassLBrace);
|
||||
|
||||
Tokens = annotate("class [[deprecated(\"\")]] C { int i; };");
|
||||
EXPECT_EQ(Tokens.size(), 17u) << Tokens;
|
||||
EXPECT_TOKEN(Tokens[10], tok::l_brace, TT_ClassLBrace);
|
||||
}
|
||||
|
||||
TEST_F(TokenAnnotatorTest, UnderstandsStructs) {
|
||||
|
||||
Reference in New Issue
Block a user