From 596fa2d90044841c33b9a0e6b17406c2a45077a2 Mon Sep 17 00:00:00 2001 From: Marek Kurdej Date: Wed, 9 Mar 2022 11:05:34 +0100 Subject: [PATCH] [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 --- clang/lib/Format/UnwrappedLineParser.cpp | 45 ++++++++++++++++------- clang/lib/Format/UnwrappedLineParser.h | 2 ++ clang/unittests/Format/FormatTest.cpp | 46 ++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 3a245b8b5fa0..47e794c7b1ca 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(); @@ -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); diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 5cc01398a545..798bae24ad07 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -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(); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 37a42382e8f8..430a195f6025 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -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;