diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp | 525 |
1 files changed, 276 insertions, 249 deletions
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp index e3fb976ee1cc..91b8fdc8a3c3 100644 --- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp +++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp @@ -14,7 +14,6 @@ #include "UnwrappedLineParser.h" #include "FormatToken.h" -#include "FormatTokenLexer.h" #include "FormatTokenSource.h" #include "Macros.h" #include "TokenAnnotator.h" @@ -25,7 +24,6 @@ #include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/raw_ostream.h" -#include <algorithm> #include <utility> #define DEBUG_TYPE "format-parser" @@ -51,9 +49,7 @@ void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line, << "T=" << (unsigned)I->Tok->getType() << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText << "\"] "; - for (SmallVectorImpl<UnwrappedLine>::const_iterator - CI = I->Children.begin(), - CE = I->Children.end(); + for (const auto *CI = I->Children.begin(), *CE = I->Children.end(); CI != CE; ++CI) { OS << "\n"; printLine(OS, *CI, (Prefix + " ").str()); @@ -121,7 +117,7 @@ public: assert(Parser.Line->Tokens.empty()); Parser.Line = std::move(PreBlockLine); if (Parser.CurrentLines == &Parser.PreprocessorDirectives) - Parser.MustBreakBeforeNextToken = true; + Parser.AtEndOfPPLine = true; Parser.CurrentLines = OriginalLines; } @@ -137,7 +133,8 @@ public: CompoundStatementIndenter(UnwrappedLineParser *Parser, const FormatStyle &Style, unsigned &LineLevel) : CompoundStatementIndenter(Parser, LineLevel, - Style.BraceWrapping.AfterControlStatement, + Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always, Style.BraceWrapping.IndentBraces) {} CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel, bool WrapBrace, bool IndentBrace) @@ -160,8 +157,8 @@ UnwrappedLineParser::UnwrappedLineParser( ArrayRef<FormatToken *> Tokens, UnwrappedLineConsumer &Callback, llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator, IdentifierTable &IdentTable) - : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), - CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()), + : Line(new UnwrappedLine), AtEndOfPPLine(false), CurrentLines(&Lines), + Style(Style), IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords), CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr), Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1), @@ -169,9 +166,7 @@ UnwrappedLineParser::UnwrappedLineParser( ? IG_Rejected : IG_Inited), IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn), - Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) { - assert(IsCpp == LangOpts.CXXOperatorNames); -} + Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {} void UnwrappedLineParser::reset() { PPBranchLevel = -1; @@ -182,7 +177,7 @@ void UnwrappedLineParser::reset() { Line.reset(new UnwrappedLine); CommentsBeforeNextToken.clear(); FormatTok = nullptr; - MustBreakBeforeNextToken = false; + AtEndOfPPLine = false; IsDecltypeAutoFunction = false; PreprocessorDirectives.clear(); CurrentLines = &Lines; @@ -274,7 +269,7 @@ void UnwrappedLineParser::parseFile() { bool MustBeDeclaration = !Line->InPPDirective && !Style.isJavaScript(); ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, MustBeDeclaration); - if (Style.Language == FormatStyle::LK_TextProto) + if (Style.isTextProto() || (Style.isJson() && FormatTok->IsFirst)) parseBracedList(); else parseLevel(); @@ -288,10 +283,8 @@ void UnwrappedLineParser::parseFile() { // // endfile comment // do not have a chance to be put on a line of their own until this point. // Here we add this newline before end-of-file comments. - if (Style.Language == FormatStyle::LK_TextProto && - !CommentsBeforeNextToken.empty()) { + if (Style.isTextProto() && !CommentsBeforeNextToken.empty()) addUnwrappedLine(); - } flushComments(true); addUnwrappedLine(); } @@ -300,6 +293,7 @@ void UnwrappedLineParser::parseCSharpGenericTypeConstraint() { do { switch (FormatTok->Tok.getKind()) { case tok::l_brace: + case tok::semi: return; default: if (FormatTok->is(Keywords.kw_where)) { @@ -346,7 +340,7 @@ bool UnwrappedLineParser::precededByCommentOrPPDirective() const { (Previous->IsMultiline || Previous->NewlinesBefore > 0); } -/// \brief Parses a level, that is ???. +/// Parses a level, that is ???. /// \param OpeningBrace Opening brace (\p nullptr if absent) of that level. /// \param IfKind The \p if statement kind in the level. /// \param IfLeftBrace The left brace of the \p if block in the level. @@ -394,7 +388,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, break; case tok::l_brace: if (InRequiresExpression) { - FormatTok->setFinalizedType(TT_RequiresExpressionLBrace); + FormatTok->setFinalizedType(TT_CompoundRequirementLBrace); } else if (FormatTok->Previous && FormatTok->Previous->ClosesRequiresClause) { // We need the 'default' case here to correctly parse a function @@ -505,10 +499,10 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { auto *NextTok = Tokens->getNextNonComment(); if (!Line->InMacroBody && !Style.isTableGen()) { - // Skip PPDirective lines and comments. + // Skip PPDirective lines (except macro definitions) and comments. while (NextTok->is(tok::hash)) { NextTok = Tokens->getNextToken(); - if (NextTok->is(tok::pp_not_keyword)) + if (NextTok->isOneOf(tok::pp_not_keyword, tok::pp_define)) break; do { NextTok = Tokens->getNextToken(); @@ -570,8 +564,9 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in, Keywords.kw_as)); ProbablyBracedList = - ProbablyBracedList || (IsCpp && (PrevTok->Tok.isLiteral() || - NextTok->is(tok::l_paren))); + ProbablyBracedList || + (IsCpp && (PrevTok->Tok.isLiteral() || + NextTok->isOneOf(tok::l_paren, tok::arrow))); // If there is a comma, semicolon or right paren after the closing // brace, we assume this is a braced initializer list. @@ -1031,6 +1026,12 @@ void UnwrappedLineParser::parsePPDirective() { case tok::pp_pragma: parsePPPragma(); break; + case tok::pp_error: + case tok::pp_warning: + nextToken(); + if (!eof() && Style.isCpp()) + FormatTok->setFinalizedType(TT_AfterPPDirective); + [[fallthrough]]; default: parsePPUnknown(); break; @@ -1154,6 +1155,7 @@ void UnwrappedLineParser::parsePPDefine() { return; } + bool MaybeIncludeGuard = false; if (IncludeGuard == IG_IfNdefed && IncludeGuardToken->TokenText == FormatTok->TokenText) { IncludeGuard = IG_Defined; @@ -1164,6 +1166,7 @@ void UnwrappedLineParser::parsePPDefine() { break; } } + MaybeIncludeGuard = IncludeGuard == IG_Defined; } // In the context of a define, even keywords should be treated as normal @@ -1174,6 +1177,11 @@ void UnwrappedLineParser::parsePPDefine() { FormatTok->Tok.setKind(tok::identifier); FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define); nextToken(); + + // IncludeGuard can't have a non-empty macro definition. + if (MaybeIncludeGuard && !eof()) + IncludeGuard = IG_Rejected; + if (FormatTok->Tok.getKind() == tok::l_paren && !FormatTok->hasWhitespaceBefore()) { parseParens(); @@ -1210,9 +1218,8 @@ void UnwrappedLineParser::parsePPPragma() { } void UnwrappedLineParser::parsePPUnknown() { - do { + while (!eof()) nextToken(); - } while (!eof()); if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) Line->Level += PPBranchLevel + 1; addUnwrappedLine(); @@ -1348,7 +1355,7 @@ bool UnwrappedLineParser::parseModuleImport() { // Handle import <foo/bar.h> as we would an include statement. else if (FormatTok->is(tok::less)) { nextToken(); - while (!FormatTok->isOneOf(tok::semi, tok::greater, tok::eof)) { + while (!FormatTok->isOneOf(tok::semi, tok::greater) && !eof()) { // Mark tokens up to the trailing line comments as implicit string // literals. if (FormatTok->isNot(tok::comment) && @@ -1420,8 +1427,7 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() { void UnwrappedLineParser::parseStructuralElement( const FormatToken *OpeningBrace, IfStmtKind *IfKind, FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) { - if (Style.Language == FormatStyle::LK_TableGen && - FormatTok->is(tok::pp_include)) { + if (Style.isTableGen() && FormatTok->is(tok::pp_include)) { nextToken(); if (FormatTok->is(tok::string_literal)) nextToken(); @@ -1463,12 +1469,10 @@ void UnwrappedLineParser::parseStructuralElement( // Tokens that only make sense at the beginning of a line. if (FormatTok->isAccessSpecifierKeyword()) { - if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || - Style.isCSharp()) { + if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) nextToken(); - } else { + else parseAccessSpecifier(); - } return; } switch (FormatTok->Tok.getKind()) { @@ -1568,6 +1572,11 @@ void UnwrappedLineParser::parseStructuralElement( } parseCaseLabel(); return; + case tok::kw_goto: + nextToken(); + if (FormatTok->is(tok::kw_case)) + nextToken(); + break; case tok::kw_try: case tok::kw___try: if (Style.isJavaScript() && Line->MustBeDeclaration) { @@ -1616,6 +1625,10 @@ void UnwrappedLineParser::parseStructuralElement( parseNamespace(); return; } + if (FormatTok->is(tok::l_brace)) { + parseCppExportBlock(); + return; + } if (FormatTok->is(Keywords.kw_import) && parseModuleImport()) return; } @@ -1689,21 +1702,22 @@ void UnwrappedLineParser::parseStructuralElement( *HasLabel = true; return; } + if (Style.isJava() && FormatTok->is(Keywords.kw_record)) { + parseRecord(/*ParseAsExpr=*/false, /*IsJavaRecord=*/true); + addUnwrappedLine(); + return; + } // In all other cases, parse the declaration. break; default: break; } + bool SeenEqual = false; for (const bool InRequiresExpression = - OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); + OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace, + TT_CompoundRequirementLBrace); !eof();) { - if (IsCpp && FormatTok->isCppAlternativeOperatorKeyword()) { - if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true); - Next && Next->isBinaryOperator()) { - FormatTok->Tok.setKind(tok::identifier); - } - } const FormatToken *Previous = FormatTok->Previous; switch (FormatTok->Tok.getKind()) { case tok::at: @@ -1712,12 +1726,12 @@ void UnwrappedLineParser::parseStructuralElement( nextToken(); parseBracedList(); break; - } else if (Style.Language == FormatStyle::LK_Java && - FormatTok->is(Keywords.kw_interface)) { + } + if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) { nextToken(); break; } - switch (FormatTok->Tok.getObjCKeywordID()) { + switch (bool IsAutoRelease = false; FormatTok->Tok.getObjCKeywordID()) { case tok::objc_public: case tok::objc_protected: case tok::objc_package: @@ -1738,19 +1752,11 @@ void UnwrappedLineParser::parseStructuralElement( addUnwrappedLine(); return; case tok::objc_autoreleasepool: - nextToken(); - if (FormatTok->is(tok::l_brace)) { - if (Style.BraceWrapping.AfterControlStatement == - FormatStyle::BWACS_Always) { - addUnwrappedLine(); - } - parseBlock(); - } - addUnwrappedLine(); - return; + IsAutoRelease = true; + [[fallthrough]]; case tok::objc_synchronized: nextToken(); - if (FormatTok->is(tok::l_paren)) { + if (!IsAutoRelease && FormatTok->is(tok::l_paren)) { // Skip synchronization object parseParens(); } @@ -1774,7 +1780,7 @@ void UnwrappedLineParser::parseStructuralElement( break; case tok::kw_requires: { if (IsCpp) { - bool ParsedClause = parseRequires(); + bool ParsedClause = parseRequires(SeenEqual); if (ParsedClause) return; } else { @@ -1831,8 +1837,8 @@ void UnwrappedLineParser::parseStructuralElement( nextToken(); if (FormatTok->is(tok::l_paren)) { parseParens(); - assert(FormatTok->Previous); - if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto, + if (FormatTok->Previous && + FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto, tok::l_paren)) { Line->SeenDecltypeAuto = true; } @@ -1841,10 +1847,8 @@ void UnwrappedLineParser::parseStructuralElement( case tok::period: nextToken(); // In Java, classes have an implicit static member "class". - if (Style.Language == FormatStyle::LK_Java && FormatTok && - FormatTok->is(tok::kw_class)) { + if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class)) nextToken(); - } if (Style.isJavaScript() && FormatTok && FormatTok->Tok.getIdentifierInfo()) { // JavaScript only has pseudo keywords, all keywords are allowed to @@ -1878,8 +1882,11 @@ void UnwrappedLineParser::parseStructuralElement( if (FormatTok->isBinaryOperator()) nextToken(); break; - case tok::caret: + case tok::caret: { + const auto *Prev = FormatTok->getPreviousNonComment(); nextToken(); + if (Prev && Prev->is(tok::identifier)) + break; // Block return type. if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) { nextToken(); @@ -1894,6 +1901,7 @@ void UnwrappedLineParser::parseStructuralElement( if (FormatTok->is(tok::l_brace)) parseChildBlock(); break; + } case tok::l_brace: if (InRequiresExpression) FormatTok->setFinalizedType(TT_BracedListLBrace); @@ -1903,7 +1911,7 @@ void UnwrappedLineParser::parseStructuralElement( // structural element. // FIXME: Figure out cases where this is not true, and add projections // for them (the one we know is missing are lambdas). - if (Style.Language == FormatStyle::LK_Java && + if (Style.isJava() && Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) { // If necessary, we could set the type to something different than // TT_FunctionLBrace. @@ -1959,7 +1967,7 @@ void UnwrappedLineParser::parseStructuralElement( tryToParseJSFunction(); break; } - if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) && + if ((Style.isJavaScript() || Style.isJava()) && FormatTok->is(Keywords.kw_interface)) { if (Style.isJavaScript()) { // In JavaScript/TypeScript, "interface" can be used as a standalone @@ -2035,7 +2043,9 @@ void UnwrappedLineParser::parseStructuralElement( ? FormatTok->NewlinesBefore > 0 : CommentsBeforeNextToken.front()->NewlinesBefore > 0; - if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) && + if (FollowedByNewline && + (Text.size() >= 5 || + (FunctionLike && FormatTok->isNot(tok::l_paren))) && tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) { if (PreviousToken->isNot(TT_UntouchableMacroFunc)) PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro); @@ -2052,6 +2062,7 @@ void UnwrappedLineParser::parseStructuralElement( break; } + SeenEqual = true; nextToken(); if (FormatTok->is(tok::l_brace)) { // Block kind should probably be set to BK_BracedInit for any language. @@ -2081,10 +2092,16 @@ void UnwrappedLineParser::parseStructuralElement( parseSquare(); break; case tok::kw_new: - parseNew(); + if (Style.isCSharp() && + (Tokens->peekNextToken()->isAccessSpecifierKeyword() || + (Previous && Previous->isAccessSpecifierKeyword()))) { + nextToken(); + } else { + parseNew(); + } break; case tok::kw_switch: - if (Style.Language == FormatStyle::LK_Java) + if (Style.isJava()) parseSwitch(/*IsExpr=*/true); else nextToken(); @@ -2149,7 +2166,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { if (!Style.isCSharp()) return false; // See if it's a property accessor. - if (FormatTok->Previous->isNot(tok::identifier)) + if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier)) return false; // See if we are inside a property accessor. @@ -2165,12 +2182,16 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { // Track these as they do not require line breaks to be introduced. bool HasSpecialAccessor = false; bool IsTrivialPropertyAccessor = true; + bool HasAttribute = false; while (!eof()) { - if (Tok->isAccessSpecifierKeyword() || - Tok->isOneOf(tok::semi, Keywords.kw_internal, Keywords.kw_get, - Keywords.kw_init, Keywords.kw_set)) { - if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set)) + if (const bool IsAccessorKeyword = + Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set); + IsAccessorKeyword || Tok->isAccessSpecifierKeyword() || + Tok->isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) { + if (IsAccessorKeyword) HasSpecialAccessor = true; + else if (Tok->is(tok::l_square)) + HasAttribute = true; Tok = Tokens->getNextToken(); continue; } @@ -2179,7 +2200,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { break; } - if (!HasSpecialAccessor) { + if (!HasSpecialAccessor || HasAttribute) { Tokens->setPosition(StoredPosition); return false; } @@ -2364,13 +2385,25 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() { const FormatToken *Previous = FormatTok->Previous; const FormatToken *LeftSquare = FormatTok; nextToken(); - if ((Previous && ((Previous->Tok.getIdentifierInfo() && - !Previous->isOneOf(tok::kw_return, tok::kw_co_await, - tok::kw_co_yield, tok::kw_co_return)) || - Previous->closesScope())) || - LeftSquare->isCppStructuredBinding(IsCpp)) { - return false; + if (Previous) { + if (Previous->Tok.getIdentifierInfo() && + !Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield, + tok::kw_co_return)) { + return false; + } + if (Previous->closesScope()) { + // Not a potential C-style cast. + if (Previous->isNot(tok::r_paren)) + return false; + const auto *BeforeRParen = Previous->getPreviousNonComment(); + // Lambdas can be cast to function types only, e.g. `std::function<int()>` + // and `int (*)()`. + if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren)) + return false; + } } + if (LeftSquare->isCppStructuredBinding(IsCpp)) + return false; if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind())) return false; if (FormatTok->is(tok::r_square)) { @@ -2541,60 +2574,87 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) { return false; } -/// \brief Parses a pair of parentheses (and everything between them). +/// Parses a pair of parentheses (and everything between them). /// \param AmpAmpTokenType If different than TT_Unknown sets this type for all /// double ampersands. This applies for all nested scopes as well. /// /// Returns whether there is a `=` token between the parentheses. -bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { +bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType, + bool InMacroCall) { assert(FormatTok->is(tok::l_paren) && "'(' expected."); - auto *LeftParen = FormatTok; + auto *LParen = FormatTok; + auto *Prev = FormatTok->Previous; + bool SeenComma = false; bool SeenEqual = false; bool MightBeFoldExpr = false; - const bool MightBeStmtExpr = Tokens->peekNextToken()->is(tok::l_brace); nextToken(); + const bool MightBeStmtExpr = FormatTok->is(tok::l_brace); + if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro)) + InMacroCall = true; do { switch (FormatTok->Tok.getKind()) { case tok::l_paren: - if (parseParens(AmpAmpTokenType)) + if (parseParens(AmpAmpTokenType, InMacroCall)) SeenEqual = true; - if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace)) + if (Style.isJava() && FormatTok->is(tok::l_brace)) parseChildBlock(); break; case tok::r_paren: { - auto *Prev = LeftParen->Previous; - if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody && - Style.RemoveParentheses > FormatStyle::RPS_Leave) { - const auto *Next = Tokens->peekNextToken(); - const bool DoubleParens = - Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren); - const auto *PrevPrev = Prev ? Prev->getPreviousNonComment() : nullptr; - const bool Blacklisted = - PrevPrev && - (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) || - (SeenEqual && - (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) || - PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if)))); - const bool ReturnParens = - Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement && - ((NestedLambdas.empty() && !IsDecltypeAutoFunction) || - (!NestedLambdas.empty() && !NestedLambdas.back())) && - Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next && - Next->is(tok::semi); - if ((DoubleParens && !Blacklisted) || ReturnParens) { - LeftParen->Optional = true; - FormatTok->Optional = true; - } - } + auto *RParen = FormatTok; + nextToken(); if (Prev) { + auto OptionalParens = [&] { + if (MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall || + Line->InMacroBody || + Style.RemoveParentheses == FormatStyle::RPS_Leave || + RParen->getPreviousNonComment() == LParen) { + return false; + } + const bool DoubleParens = + Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren); + if (DoubleParens) { + const auto *PrevPrev = Prev->getPreviousNonComment(); + const bool Excluded = + PrevPrev && + (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) || + (SeenEqual && + (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) || + PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if)))); + if (!Excluded) + return true; + } else { + const bool CommaSeparated = + Prev->isOneOf(tok::l_paren, tok::comma) && + FormatTok->isOneOf(tok::comma, tok::r_paren); + if (CommaSeparated && + // LParen is not preceded by ellipsis, comma. + !Prev->endsSequence(tok::comma, tok::ellipsis) && + // RParen is not followed by comma, ellipsis. + !(FormatTok->is(tok::comma) && + Tokens->peekNextToken()->is(tok::ellipsis))) { + return true; + } + const bool ReturnParens = + Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement && + ((NestedLambdas.empty() && !IsDecltypeAutoFunction) || + (!NestedLambdas.empty() && !NestedLambdas.back())) && + Prev->isOneOf(tok::kw_return, tok::kw_co_return) && + FormatTok->is(tok::semi); + if (ReturnParens) + return true; + } + return false; + }; if (Prev->is(TT_TypenameMacro)) { - LeftParen->setFinalizedType(TT_TypeDeclarationParen); - FormatTok->setFinalizedType(TT_TypeDeclarationParen); - } else if (Prev->is(tok::greater) && FormatTok->Previous == LeftParen) { + LParen->setFinalizedType(TT_TypeDeclarationParen); + RParen->setFinalizedType(TT_TypeDeclarationParen); + } else if (Prev->is(tok::greater) && RParen->Previous == LParen) { Prev->setFinalizedType(TT_TemplateCloser); + } else if (OptionalParens()) { + LParen->Optional = true; + RParen->Optional = true; } } - nextToken(); return SeenEqual; } case tok::r_brace: @@ -2614,6 +2674,10 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { parseBracedList(); } break; + case tok::comma: + SeenComma = true; + nextToken(); + break; case tok::ellipsis: MightBeFoldExpr = true; nextToken(); @@ -2638,7 +2702,7 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { nextToken(); break; case tok::kw_switch: - if (Style.Language == FormatStyle::LK_Java) + if (Style.isJava()) parseSwitch(/*IsExpr=*/true); else nextToken(); @@ -3015,7 +3079,7 @@ void UnwrappedLineParser::parseTryCatch() { } } // Parse try with resource. - if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren)) + if (Style.isJava() && FormatTok->is(tok::l_paren)) parseParens(); keepAncestorBraces(); @@ -3038,30 +3102,35 @@ void UnwrappedLineParser::parseTryCatch() { parseStructuralElement(); --Line->Level; } - while (true) { + for (bool SeenCatch = false;;) { if (FormatTok->is(tok::at)) nextToken(); if (!(FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except, - tok::kw___finally) || - ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && - FormatTok->is(Keywords.kw_finally)) || - (FormatTok->isObjCAtKeyword(tok::objc_catch) || - FormatTok->isObjCAtKeyword(tok::objc_finally)))) { + tok::kw___finally, tok::objc_catch, + tok::objc_finally) || + ((Style.isJava() || Style.isJavaScript()) && + FormatTok->is(Keywords.kw_finally)))) { break; } + if (FormatTok->is(tok::kw_catch)) + SeenCatch = true; nextToken(); while (FormatTok->isNot(tok::l_brace)) { if (FormatTok->is(tok::l_paren)) { parseParens(); continue; } - if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof)) { + if (FormatTok->isOneOf(tok::semi, tok::r_brace) || eof()) { if (Style.RemoveBracesLLVM) NestedTooDeep.pop_back(); return; } nextToken(); } + if (SeenCatch) { + FormatTok->setFinalizedType(TT_ControlStatementLBrace); + SeenCatch = false; + } NeedsUnwrappedLine = false; Line->MustBeDeclaration = false; CompoundStatementIndenter Indenter(this, Style, Line->Level); @@ -3079,6 +3148,26 @@ void UnwrappedLineParser::parseTryCatch() { addUnwrappedLine(); } +void UnwrappedLineParser::parseNamespaceOrExportBlock(unsigned AddLevels) { + bool ManageWhitesmithsBraces = + AddLevels == 0u && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; + + // If we're in Whitesmiths mode, indent the brace if we're not indenting + // the whole block. + if (ManageWhitesmithsBraces) + ++Line->Level; + + // Munch the semicolon after the block. This is more common than one would + // think. Putting the semicolon into its own line is very ugly. + parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true, + /*KeepBraces=*/true, /*IfKind=*/nullptr, ManageWhitesmithsBraces); + + addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep); + + if (ManageWhitesmithsBraces) + --Line->Level; +} + void UnwrappedLineParser::parseNamespace() { assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) && "'namespace' expected"); @@ -3111,29 +3200,15 @@ void UnwrappedLineParser::parseNamespace() { DeclarationScopeStack.size() > 1) ? 1u : 0u; - bool ManageWhitesmithsBraces = - AddLevels == 0u && - Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; - - // If we're in Whitesmiths mode, indent the brace if we're not indenting - // the whole block. - if (ManageWhitesmithsBraces) - ++Line->Level; - - // Munch the semicolon after a namespace. This is more common than one would - // think. Putting the semicolon into its own line is very ugly. - parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true, - /*KeepBraces=*/true, /*IfKind=*/nullptr, - ManageWhitesmithsBraces); - - addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep); - - if (ManageWhitesmithsBraces) - --Line->Level; + parseNamespaceOrExportBlock(AddLevels); } // FIXME: Add error handling. } +void UnwrappedLineParser::parseCppExportBlock() { + parseNamespaceOrExportBlock(/*AddLevels=*/Style.IndentExportBlock ? 1 : 0); +} + void UnwrappedLineParser::parseNew() { assert(FormatTok->is(tok::kw_new) && "'new' expected"); nextToken(); @@ -3155,7 +3230,7 @@ void UnwrappedLineParser::parseNew() { } while (!eof()); } - if (Style.Language != FormatStyle::LK_Java) + if (!Style.isJava()) return; // In Java, we can parse everything up to the parens, which aren't optional. @@ -3317,7 +3392,7 @@ void UnwrappedLineParser::parseCaseLabel() { FormatTok->setFinalizedType(TT_CaseLabelColon); break; } - if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::arrow)) { + if (Style.isJava() && FormatTok->is(tok::arrow)) { FormatTok->setFinalizedType(TT_CaseLabelArrow); Case->setFinalizedType(TT_SwitchExpressionLabel); break; @@ -3356,81 +3431,21 @@ void UnwrappedLineParser::parseSwitch(bool IsExpr) { NestedTooDeep.pop_back(); } -// Operators that can follow a C variable. -static bool isCOperatorFollowingVar(tok::TokenKind Kind) { - switch (Kind) { - case tok::ampamp: - case tok::ampequal: - case tok::arrow: - case tok::caret: - case tok::caretequal: - case tok::comma: - case tok::ellipsis: - case tok::equal: - case tok::equalequal: - case tok::exclaim: - case tok::exclaimequal: - case tok::greater: - case tok::greaterequal: - case tok::greatergreater: - case tok::greatergreaterequal: - case tok::l_paren: - case tok::l_square: - case tok::less: - case tok::lessequal: - case tok::lessless: - case tok::lesslessequal: - case tok::minus: - case tok::minusequal: - case tok::minusminus: - case tok::percent: - case tok::percentequal: - case tok::period: - case tok::pipe: - case tok::pipeequal: - case tok::pipepipe: - case tok::plus: - case tok::plusequal: - case tok::plusplus: - case tok::question: - case tok::r_brace: - case tok::r_paren: - case tok::r_square: - case tok::semi: - case tok::slash: - case tok::slashequal: - case tok::star: - case tok::starequal: - return true; - default: - return false; - } -} - void UnwrappedLineParser::parseAccessSpecifier() { - FormatToken *AccessSpecifierCandidate = FormatTok; nextToken(); // Understand Qt's slots. if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots)) nextToken(); // Otherwise, we don't know what it is, and we'd better keep the next token. - if (FormatTok->is(tok::colon)) { + if (FormatTok->is(tok::colon)) nextToken(); - addUnwrappedLine(); - } else if (FormatTok->isNot(tok::coloncolon) && - !isCOperatorFollowingVar(FormatTok->Tok.getKind())) { - // Not a variable name nor namespace name. - addUnwrappedLine(); - } else if (AccessSpecifierCandidate) { - // Consider the access specifier to be a C identifier. - AccessSpecifierCandidate->Tok.setKind(tok::identifier); - } + addUnwrappedLine(); } -/// \brief Parses a requires, decides if it is a clause or an expression. +/// Parses a requires, decides if it is a clause or an expression. /// \pre The current token has to be the requires keyword. /// \returns true if it parsed a clause. -bool UnwrappedLineParser::parseRequires() { +bool UnwrappedLineParser::parseRequires(bool SeenEqual) { assert(FormatTok->is(tok::kw_requires) && "'requires' expected"); auto RequiresToken = FormatTok; @@ -3474,10 +3489,11 @@ bool UnwrappedLineParser::parseRequires() { case tok::r_paren: case tok::kw_noexcept: case tok::kw_const: + case tok::star: + case tok::amp: // This is a requires clause. parseRequiresClause(RequiresToken); return true; - case tok::amp: case tok::ampamp: { // This can be either: // if (... && requires (T t) ...) @@ -3486,7 +3502,7 @@ bool UnwrappedLineParser::parseRequires() { // We check the one token before that for a const: // void member(...) const && requires (C<T> ... auto PrevPrev = PreviousNonComment->getPreviousNonComment(); - if (PrevPrev && PrevPrev->is(tok::kw_const)) { + if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) { parseRequiresClause(RequiresToken); return true; } @@ -3570,7 +3586,7 @@ bool UnwrappedLineParser::parseRequires() { return true; } -/// \brief Parses a requires clause. +/// Parses a requires clause. /// \param RequiresToken The requires keyword token, which starts this clause. /// \pre We need to be on the next token after the requires keyword. /// \sa parseRequiresExpression @@ -3596,11 +3612,11 @@ void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) { // It could be inlined into here. parseConstraintExpression(); - if (!InRequiresExpression) + if (!InRequiresExpression && FormatTok->Previous) FormatTok->Previous->ClosesRequiresClause = true; } -/// \brief Parses a requires expression. +/// Parses a requires expression. /// \param RequiresToken The requires keyword token, which starts this clause. /// \pre We need to be on the next token after the requires keyword. /// \sa parseRequiresClause @@ -3624,7 +3640,7 @@ void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) { } } -/// \brief Parses a constraint expression. +/// Parses a constraint expression. /// /// This is the body of a requires clause. It returns, when the parsing is /// complete, or the expression is incorrect. @@ -3829,7 +3845,7 @@ bool UnwrappedLineParser::parseEnum() { FormatTok->setFinalizedType(TT_EnumLBrace); FormatTok->setBlockKind(BK_Block); - if (Style.Language == FormatStyle::LK_Java) { + if (Style.isJava()) { // Java enums are different. parseJavaEnumBody(); return true; @@ -3870,8 +3886,7 @@ bool UnwrappedLineParser::parseStructLike() { // record declaration or definition can start a structural element. parseRecord(); // This does not apply to Java, JavaScript and C#. - if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || - Style.isCSharp()) { + if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) { if (FormatTok->is(tok::semi)) nextToken(); addUnwrappedLine(); @@ -3989,11 +4004,13 @@ void UnwrappedLineParser::parseJavaEnumBody() { addUnwrappedLine(); } -void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { +void UnwrappedLineParser::parseRecord(bool ParseAsExpr, bool IsJavaRecord) { + assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record)); const FormatToken &InitialToken = *FormatTok; nextToken(); - const FormatToken *ClassName = nullptr; + FormatToken *ClassName = + IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok : nullptr; bool IsDerived = false; auto IsNonMacroIdentifier = [](const FormatToken *Tok) { return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper(); @@ -4007,7 +4024,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash, tok::kw_alignas, tok::l_square) || FormatTok->isAttribute() || - ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && + ((Style.isJava() || Style.isJavaScript()) && FormatTok->isOneOf(tok::period, tok::comma))) { if (Style.isJavaScript() && FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) { @@ -4023,12 +4040,12 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { } if (FormatTok->is(tok::l_square) && handleCppAttributes()) continue; - const auto *Previous = FormatTok; + auto *Previous = FormatTok; nextToken(); switch (FormatTok->Tok.getKind()) { case tok::l_paren: // We can have macros in between 'class' and the class name. - if (!IsNonMacroIdentifier(Previous) || + if (IsJavaRecord || !IsNonMacroIdentifier(Previous) || // e.g. `struct macro(a) S { int i; };` Previous->Previous == &InitialToken) { parseParens(); @@ -4038,15 +4055,19 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { case tok::hashhash: break; default: - if (!JSPastExtendsOrImplements && !ClassName && - Previous->is(tok::identifier) && Previous->isNot(TT_AttributeMacro)) { + if (JSPastExtendsOrImplements || ClassName || + Previous->isNot(tok::identifier) || Previous->is(TT_AttributeMacro)) { + break; + } + if (const auto Text = Previous->TokenText; + Text.size() == 1 || Text != Text.upper()) { ClassName = Previous; } } } auto IsListInitialization = [&] { - if (!ClassName || IsDerived) + if (!ClassName || IsDerived || JSPastExtendsOrImplements) return false; assert(FormatTok->is(tok::l_brace)); const auto *Prev = FormatTok->getPreviousNonComment(); @@ -4066,7 +4087,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { if (AngleNestingLevel == 0) { if (FormatTok->is(tok::colon)) { IsDerived = true; - } else if (FormatTok->is(tok::identifier) && + } else if (!IsDerived && FormatTok->is(tok::identifier) && FormatTok->Previous->is(tok::coloncolon)) { ClassName = FormatTok; } else if (FormatTok->is(tok::l_paren) && @@ -4123,6 +4144,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { if (FormatTok->is(tok::l_brace)) { if (IsListInitialization()) return; + if (ClassName) + ClassName->setFinalizedType(TT_ClassHeadName); auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken); FormatTok->setFinalizedType(OpenBraceType); if (ParseAsExpr) { @@ -4166,17 +4189,15 @@ void UnwrappedLineParser::parseObjCProtocolList() { do { nextToken(); // Early exit in case someone forgot a close angle. - if (FormatTok->isOneOf(tok::semi, tok::l_brace) || - FormatTok->isObjCAtKeyword(tok::objc_end)) { + if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end)) return; - } } while (!eof() && FormatTok->isNot(tok::greater)); nextToken(); // Skip '>'. } void UnwrappedLineParser::parseObjCUntilAtEnd() { do { - if (FormatTok->isObjCAtKeyword(tok::objc_end)) { + if (FormatTok->is(tok::objc_end)) { nextToken(); addUnwrappedLine(); break; @@ -4199,8 +4220,7 @@ void UnwrappedLineParser::parseObjCUntilAtEnd() { } void UnwrappedLineParser::parseObjCInterfaceOrImplementation() { - assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_interface || - FormatTok->Tok.getObjCKeywordID() == tok::objc_implementation); + assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation)); nextToken(); nextToken(); // interface name @@ -4248,10 +4268,8 @@ void UnwrappedLineParser::parseObjCLightweightGenerics() { do { nextToken(); // Early exit in case someone forgot a close angle. - if (FormatTok->isOneOf(tok::semi, tok::l_brace) || - FormatTok->isObjCAtKeyword(tok::objc_end)) { + if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end)) break; - } if (FormatTok->is(tok::less)) { ++NumOpenAngles; } else if (FormatTok->is(tok::greater)) { @@ -4265,7 +4283,7 @@ void UnwrappedLineParser::parseObjCLightweightGenerics() { // Returns true for the declaration/definition form of @protocol, // false for the expression form. bool UnwrappedLineParser::parseObjCProtocol() { - assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_protocol); + assert(FormatTok->is(tok::objc_protocol)); nextToken(); if (FormatTok->is(tok::l_paren)) { @@ -4422,7 +4440,8 @@ unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() { Prev->setFinalizedType(TT_VerilogDimensionedTypeName); parseSquare(); } else if (Keywords.isVerilogIdentifier(*FormatTok) || - FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) { + FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon, + Keywords.kw_automatic, tok::kw_static)) { nextToken(); } else { break; @@ -4586,7 +4605,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { } else { // At the top level we only get here when no unexpansion is going on, or // when conditional formatting led to unfinished macro reconstructions. - assert(!Reconstruct || (CurrentLines != &Lines) || PPStack.size() > 0); + assert(!Reconstruct || (CurrentLines != &Lines) || !PPStack.empty()); CurrentLines->push_back(std::move(*Line)); } Line->Tokens.clear(); @@ -4618,9 +4637,9 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) { // section on \p Line. static bool continuesLineCommentSection(const FormatToken &FormatTok, - const UnwrappedLine &Line, + const UnwrappedLine &Line, const FormatStyle &Style, const llvm::Regex &CommentPragmasRegex) { - if (Line.Tokens.empty()) + if (Line.Tokens.empty() || Style.ReflowComments != FormatStyle::RCS_Always) return false; StringRef IndentContent = FormatTok.TokenText; @@ -4733,7 +4752,7 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) { // FIXME: Consider putting separate line comment sections as children to the // unwrapped line instead. Tok->ContinuesLineCommentSection = - continuesLineCommentSection(*Tok, *Line, CommentPragmasRegex); + continuesLineCommentSection(*Tok, *Line, Style, CommentPragmasRegex); if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection) addUnwrappedLine(); pushToken(Tok); @@ -4767,8 +4786,7 @@ void UnwrappedLineParser::nextToken(int LevelDifference) { } void UnwrappedLineParser::distributeComments( - const SmallVectorImpl<FormatToken *> &Comments, - const FormatToken *NextTok) { + const ArrayRef<FormatToken *> &Comments, const FormatToken *NextTok) { // Whether or not a line comment token continues a line is controlled by // the method continuesLineCommentSection, with the following caveat: // @@ -4806,8 +4824,8 @@ void UnwrappedLineParser::distributeComments( if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) { FormatTok->ContinuesLineCommentSection = false; } else { - FormatTok->ContinuesLineCommentSection = - continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex); + FormatTok->ContinuesLineCommentSection = continuesLineCommentSection( + *FormatTok, *Line, Style, CommentPragmasRegex); } if (!FormatTok->ContinuesLineCommentSection && (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) { @@ -4859,9 +4877,16 @@ void UnwrappedLineParser::readToken(int LevelDifference) { PreviousWasComment = FormatTok->is(tok::comment); while (!Line->InPPDirective && FormatTok->is(tok::hash) && - (!Style.isVerilog() || - Keywords.isVerilogPPDirective(*Tokens->peekNextToken())) && FirstNonCommentOnLine) { + // In Verilog, the backtick is used for macro invocations. In TableGen, + // the single hash is used for the paste operator. + const auto *Next = Tokens->peekNextToken(); + if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*Next)) || + (Style.isTableGen() && + !Next->isOneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef, + tok::pp_ifndef, tok::pp_endif))) { + break; + } distributeComments(Comments, FormatTok); Comments.clear(); // If there is an unfinished unwrapped line, we flush the preprocessor @@ -4990,7 +5015,7 @@ void UnwrappedLineParser::readToken(int LevelDifference) { namespace { template <typename Iterator> void pushTokens(Iterator Begin, Iterator End, - llvm::SmallVectorImpl<FormatToken *> &Into) { + SmallVectorImpl<FormatToken *> &Into) { for (auto I = Begin; I != End; ++I) { Into.push_back(I->Tok); for (const auto &Child : I->Children) @@ -5054,10 +5079,12 @@ UnwrappedLineParser::parseMacroCall() { void UnwrappedLineParser::pushToken(FormatToken *Tok) { Line->Tokens.push_back(UnwrappedLineNode(Tok)); - if (MustBreakBeforeNextToken) { - Line->Tokens.back().Tok->MustBreakBefore = true; - Line->Tokens.back().Tok->MustBreakBeforeFinalized = true; - MustBreakBeforeNextToken = false; + if (AtEndOfPPLine) { + auto &Tok = *Line->Tokens.back().Tok; + Tok.MustBreakBefore = true; + Tok.MustBreakBeforeFinalized = true; + Tok.FirstAfterPPLine = true; + AtEndOfPPLine = false; } } |
