[clang-format] Handle attributes before case label.

Fixes https://github.com/llvm/llvm-project/issues/53110.

Reviewed By: MyDeveloperDay, HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D121450
This commit is contained in:
Marek Kurdej 2022-03-09 11:05:34 +01:00
parent 3e4950d7fa
commit 596fa2d900
3 changed files with 81 additions and 12 deletions

View file

@ -480,6 +480,10 @@ bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace,
unsigned StatementCount = 0;
bool SwitchLabelEncountered = false;
do {
if (FormatTok->getType() == TT_AttributeMacro) {
nextToken();
continue;
}
tok::TokenKind kind = FormatTok->Tok.getKind();
if (FormatTok->getType() == TT_MacroBlockBegin)
kind = tok::l_brace;
@ -569,6 +573,8 @@ bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace,
parseCSharpAttribute();
break;
}
if (handleCppAttributes())
break;
LLVM_FALLTHROUGH;
default:
ParseDefault();
@ -1390,9 +1396,11 @@ void UnwrappedLineParser::parseStructuralElement(IfStmtKind *IfKind,
// e.g. "default void f() {}" in a Java interface.
break;
case tok::kw_case:
if (Style.isJavaScript() && Line->MustBeDeclaration)
if (Style.isJavaScript() && Line->MustBeDeclaration) {
// 'case: string' field declaration.
nextToken();
break;
}
parseCaseLabel();
return;
case tok::kw_try:
@ -1813,6 +1821,12 @@ void UnwrappedLineParser::parseStructuralElement(IfStmtKind *IfKind,
case tok::kw_new:
parseNew();
break;
case tok::kw_case:
if (Style.isJavaScript() && Line->MustBeDeclaration)
// 'case: string' field declaration.
break;
parseCaseLabel();
break;
default:
nextToken();
break;
@ -2376,17 +2390,24 @@ static void markOptionalBraces(FormatToken *LeftBrace) {
RightBrace->Optional = true;
}
void UnwrappedLineParser::handleAttributes() {
// Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
if (FormatTok->is(TT_AttributeMacro))
nextToken();
handleCppAttributes();
}
bool UnwrappedLineParser::handleCppAttributes() {
// Handle [[likely]] / [[unlikely]] attributes.
if (FormatTok->is(tok::l_square) && tryToParseSimpleAttribute()) {
parseSquare();
return true;
}
return false;
}
FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
bool KeepBraces) {
auto HandleAttributes = [this]() {
// Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
if (FormatTok->is(TT_AttributeMacro))
nextToken();
// Handle [[likely]] / [[unlikely]] attributes.
if (FormatTok->is(tok::l_square) && tryToParseSimpleAttribute())
parseSquare();
};
assert(FormatTok->is(tok::kw_if) && "'if' expected");
nextToken();
if (FormatTok->is(tok::exclaim))
@ -2399,7 +2420,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
if (FormatTok->is(tok::l_paren))
parseParens();
}
HandleAttributes();
handleAttributes();
bool NeedsUnwrappedLine = false;
keepAncestorBraces();
@ -2436,7 +2457,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
Kind = IfStmtKind::IfElse;
}
nextToken();
HandleAttributes();
handleAttributes();
if (FormatTok->is(tok::l_brace)) {
ElseLeftBrace = FormatTok;
CompoundStatementIndenter Indenter(this, Style, Line->Level);

View file

@ -121,6 +121,8 @@ private:
void parseSquare(bool LambdaIntroducer = false);
void keepAncestorBraces();
void parseUnbracedBody(bool CheckEOF = false);
void handleAttributes();
bool handleCppAttributes();
FormatToken *parseIfThenElse(IfStmtKind *IfKind, bool KeepBraces = false);
void parseTryCatch();
void parseForOrWhileLoop();

View file

@ -2602,6 +2602,52 @@ TEST_F(FormatTest, FormatsSwitchStatement) {
"}",
getLLVMStyleWithColumns(34));
verifyFormat("switch (a) {\n"
"[[likely]] case 1:\n"
" return;\n"
"}");
verifyFormat("switch (a) {\n"
"[[likely]] [[other::likely]] case 1:\n"
" return;\n"
"}");
verifyFormat("switch (x) {\n"
"case 1:\n"
" return;\n"
"[[likely]] case 2:\n"
" return;\n"
"}");
verifyFormat("switch (a) {\n"
"case 1:\n"
"[[likely]] case 2:\n"
" return;\n"
"}");
FormatStyle Attributes = getLLVMStyle();
Attributes.AttributeMacros.push_back("LIKELY");
Attributes.AttributeMacros.push_back("OTHER_LIKELY");
verifyFormat("switch (a) {\n"
"LIKELY case b:\n"
" return;\n"
"}",
Attributes);
verifyFormat("switch (a) {\n"
"LIKELY OTHER_LIKELY() case b:\n"
" return;\n"
"}",
Attributes);
verifyFormat("switch (a) {\n"
"case 1:\n"
" return;\n"
"LIKELY case 2:\n"
" return;\n"
"}",
Attributes);
verifyFormat("switch (a) {\n"
"case 1:\n"
"LIKELY case 2:\n"
" return;\n"
"}",
Attributes);
FormatStyle Style = getLLVMStyle();
Style.IndentCaseLabels = true;
Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;