diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -121,6 +121,8 @@ 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/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -480,6 +480,10 @@ 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 @@ parseCSharpAttribute(); break; } + if (handleCppAttributes()) + break; LLVM_FALLTHROUGH; default: ParseDefault(); @@ -1390,9 +1396,11 @@ // 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 @@ 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 @@ 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 @@ if (FormatTok->is(tok::l_paren)) parseParens(); } - HandleAttributes(); + handleAttributes(); bool NeedsUnwrappedLine = false; keepAncestorBraces(); @@ -2436,7 +2457,7 @@ Kind = IfStmtKind::IfElse; } nextToken(); - HandleAttributes(); + handleAttributes(); if (FormatTok->is(tok::l_brace)) { ElseLeftBrace = FormatTok; CompoundStatementIndenter Indenter(this, Style, Line->Level); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -2602,6 +2602,52 @@ "}", 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;