[clang] 4e88cb6 - [clang-format] Handle attributes before case label. Relanded.
Marek Kurdej via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 23 08:24:40 PDT 2022
Author: Marek Kurdej
Date: 2022-03-23T16:24:24+01:00
New Revision: 4e88cb6825eefca3c0eb66b5ae40ab123fcc7073
URL: https://github.com/llvm/llvm-project/commit/4e88cb6825eefca3c0eb66b5ae40ab123fcc7073
DIFF: https://github.com/llvm/llvm-project/commit/4e88cb6825eefca3c0eb66b5ae40ab123fcc7073.diff
LOG: [clang-format] Handle attributes before case label. Relanded.
Fixes https://github.com/llvm/llvm-project/issues/53110.
Reviewed By: MyDeveloperDay, HazardyKnusperkeks, owenpan
Differential Revision: https://reviews.llvm.org/D121450
Relanding as the original patch provoked an infinite loop in JavaScript/TypeScript.
A reproducer test case was added and the issue fixed.
Added:
Modified:
clang/lib/Format/UnwrappedLineParser.cpp
clang/lib/Format/UnwrappedLineParser.h
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/FormatTestJS.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 36205b8ee18cd..8052eb932141d 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -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();
@@ -1397,9 +1403,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:
@@ -1820,6 +1828,14 @@ void UnwrappedLineParser::parseStructuralElement(IfStmtKind *IfKind,
case tok::kw_new:
parseNew();
break;
+ case tok::kw_case:
+ if (Style.isJavaScript() && Line->MustBeDeclaration) {
+ // 'case: string' field declaration.
+ nextToken();
+ break;
+ }
+ parseCaseLabel();
+ break;
default:
nextToken();
break;
@@ -2388,17 +2404,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))
@@ -2411,7 +2434,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
if (FormatTok->is(tok::l_paren))
parseParens();
}
- HandleAttributes();
+ handleAttributes();
bool NeedsUnwrappedLine = false;
keepAncestorBraces();
@@ -2448,7 +2471,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);
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 5cc01398a5457..798bae24ad075 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -121,6 +121,8 @@ class UnwrappedLineParser {
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();
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 539e9c22767ea..e36a267c01f4b 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2609,6 +2609,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;
diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp
index 85aad28c085cb..6077d21c5e582 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -337,6 +337,13 @@ TEST_F(FormatTestJS, ReservedWords) {
" x: 'x'\n"
"};",
"const Axis = {for: 'for', x: 'x'};");
+ verifyFormat("export class Foo extends Bar {\n"
+ " get case(): Case {\n"
+ " return (\n"
+ " (this.Bar$has('case')) ? (this.Bar$get('case')) :\n"
+ " (this.case = new Case()));\n"
+ " }\n"
+ "}");
}
TEST_F(FormatTestJS, ReservedWordsMethods) {
More information about the cfe-commits
mailing list