5111 lines · cpp
1//===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the implementation of the UnwrappedLineParser,11/// which turns a stream of tokens into UnwrappedLines.12///13//===----------------------------------------------------------------------===//14 15#include "UnwrappedLineParser.h"16#include "FormatToken.h"17#include "FormatTokenSource.h"18#include "Macros.h"19#include "TokenAnnotator.h"20#include "clang/Basic/TokenKinds.h"21#include "llvm/ADT/STLExtras.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/Support/Debug.h"24#include "llvm/Support/raw_os_ostream.h"25#include "llvm/Support/raw_ostream.h"26 27#include <utility>28 29#define DEBUG_TYPE "format-parser"30 31namespace clang {32namespace format {33 34namespace {35 36void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,37 StringRef Prefix = "", bool PrintText = false) {38 OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn39 << ")" << (Line.InPPDirective ? " MACRO" : "") << ": ";40 bool NewLine = false;41 for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),42 E = Line.Tokens.end();43 I != E; ++I) {44 if (NewLine) {45 OS << Prefix;46 NewLine = false;47 }48 OS << I->Tok->Tok.getName() << "["49 << "T=" << (unsigned)I->Tok->getType()50 << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText51 << "\"] ";52 for (const auto *CI = I->Children.begin(), *CE = I->Children.end();53 CI != CE; ++CI) {54 OS << "\n";55 printLine(OS, *CI, (Prefix + " ").str());56 NewLine = true;57 }58 }59 if (!NewLine)60 OS << "\n";61}62 63[[maybe_unused]] static void printDebugInfo(const UnwrappedLine &Line) {64 printLine(llvm::dbgs(), Line);65}66 67class ScopedDeclarationState {68public:69 ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack,70 bool MustBeDeclaration)71 : Line(Line), Stack(Stack) {72 Line.MustBeDeclaration = MustBeDeclaration;73 Stack.push_back(MustBeDeclaration);74 }75 ~ScopedDeclarationState() {76 Stack.pop_back();77 if (!Stack.empty())78 Line.MustBeDeclaration = Stack.back();79 else80 Line.MustBeDeclaration = true;81 }82 83private:84 UnwrappedLine &Line;85 llvm::BitVector &Stack;86};87 88} // end anonymous namespace89 90std::ostream &operator<<(std::ostream &Stream, const UnwrappedLine &Line) {91 llvm::raw_os_ostream OS(Stream);92 printLine(OS, Line);93 return Stream;94}95 96class ScopedLineState {97public:98 ScopedLineState(UnwrappedLineParser &Parser,99 bool SwitchToPreprocessorLines = false)100 : Parser(Parser), OriginalLines(Parser.CurrentLines) {101 if (SwitchToPreprocessorLines)102 Parser.CurrentLines = &Parser.PreprocessorDirectives;103 else if (!Parser.Line->Tokens.empty())104 Parser.CurrentLines = &Parser.Line->Tokens.back().Children;105 PreBlockLine = std::move(Parser.Line);106 Parser.Line = std::make_unique<UnwrappedLine>();107 Parser.Line->Level = PreBlockLine->Level;108 Parser.Line->PPLevel = PreBlockLine->PPLevel;109 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;110 Parser.Line->InMacroBody = PreBlockLine->InMacroBody;111 Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel;112 }113 114 ~ScopedLineState() {115 if (!Parser.Line->Tokens.empty())116 Parser.addUnwrappedLine();117 assert(Parser.Line->Tokens.empty());118 Parser.Line = std::move(PreBlockLine);119 if (Parser.CurrentLines == &Parser.PreprocessorDirectives)120 Parser.AtEndOfPPLine = true;121 Parser.CurrentLines = OriginalLines;122 }123 124private:125 UnwrappedLineParser &Parser;126 127 std::unique_ptr<UnwrappedLine> PreBlockLine;128 SmallVectorImpl<UnwrappedLine> *OriginalLines;129};130 131class CompoundStatementIndenter {132public:133 CompoundStatementIndenter(UnwrappedLineParser *Parser,134 const FormatStyle &Style, unsigned &LineLevel)135 : CompoundStatementIndenter(Parser, LineLevel,136 Style.BraceWrapping.AfterControlStatement ==137 FormatStyle::BWACS_Always,138 Style.BraceWrapping.IndentBraces) {}139 CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel,140 bool WrapBrace, bool IndentBrace)141 : LineLevel(LineLevel), OldLineLevel(LineLevel) {142 if (WrapBrace)143 Parser->addUnwrappedLine();144 if (IndentBrace)145 ++LineLevel;146 }147 ~CompoundStatementIndenter() { LineLevel = OldLineLevel; }148 149private:150 unsigned &LineLevel;151 unsigned OldLineLevel;152};153 154UnwrappedLineParser::UnwrappedLineParser(155 SourceManager &SourceMgr, const FormatStyle &Style,156 const AdditionalKeywords &Keywords, unsigned FirstStartColumn,157 ArrayRef<FormatToken *> Tokens, UnwrappedLineConsumer &Callback,158 llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,159 IdentifierTable &IdentTable)160 : Line(new UnwrappedLine), AtEndOfPPLine(false), CurrentLines(&Lines),161 Style(Style), IsCpp(Style.isCpp()),162 LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),163 CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),164 Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),165 IncludeGuard(getIncludeGuardState(Style.IndentPPDirectives)),166 IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn),167 Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}168 169void UnwrappedLineParser::reset() {170 PPBranchLevel = -1;171 IncludeGuard = getIncludeGuardState(Style.IndentPPDirectives);172 IncludeGuardToken = nullptr;173 Line.reset(new UnwrappedLine);174 CommentsBeforeNextToken.clear();175 FormatTok = nullptr;176 AtEndOfPPLine = false;177 IsDecltypeAutoFunction = false;178 PreprocessorDirectives.clear();179 CurrentLines = &Lines;180 DeclarationScopeStack.clear();181 NestedTooDeep.clear();182 NestedLambdas.clear();183 PPStack.clear();184 Line->FirstStartColumn = FirstStartColumn;185 186 if (!Unexpanded.empty())187 for (FormatToken *Token : AllTokens)188 Token->MacroCtx.reset();189 CurrentExpandedLines.clear();190 ExpandedLines.clear();191 Unexpanded.clear();192 InExpansion = false;193 Reconstruct.reset();194}195 196void UnwrappedLineParser::parse() {197 IndexedTokenSource TokenSource(AllTokens);198 Line->FirstStartColumn = FirstStartColumn;199 do {200 LLVM_DEBUG(llvm::dbgs() << "----\n");201 reset();202 Tokens = &TokenSource;203 TokenSource.reset();204 205 readToken();206 parseFile();207 208 // If we found an include guard then all preprocessor directives (other than209 // the guard) are over-indented by one.210 if (IncludeGuard == IG_Found) {211 for (auto &Line : Lines)212 if (Line.InPPDirective && Line.Level > 0)213 --Line.Level;214 }215 216 // Create line with eof token.217 assert(eof());218 pushToken(FormatTok);219 addUnwrappedLine();220 221 // In a first run, format everything with the lines containing macro calls222 // replaced by the expansion.223 if (!ExpandedLines.empty()) {224 LLVM_DEBUG(llvm::dbgs() << "Expanded lines:\n");225 for (const auto &Line : Lines) {226 if (!Line.Tokens.empty()) {227 auto it = ExpandedLines.find(Line.Tokens.begin()->Tok);228 if (it != ExpandedLines.end()) {229 for (const auto &Expanded : it->second) {230 LLVM_DEBUG(printDebugInfo(Expanded));231 Callback.consumeUnwrappedLine(Expanded);232 }233 continue;234 }235 }236 LLVM_DEBUG(printDebugInfo(Line));237 Callback.consumeUnwrappedLine(Line);238 }239 Callback.finishRun();240 }241 242 LLVM_DEBUG(llvm::dbgs() << "Unwrapped lines:\n");243 for (const UnwrappedLine &Line : Lines) {244 LLVM_DEBUG(printDebugInfo(Line));245 Callback.consumeUnwrappedLine(Line);246 }247 Callback.finishRun();248 Lines.clear();249 while (!PPLevelBranchIndex.empty() &&250 PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {251 PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);252 PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);253 }254 if (!PPLevelBranchIndex.empty()) {255 ++PPLevelBranchIndex.back();256 assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());257 assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());258 }259 } while (!PPLevelBranchIndex.empty());260}261 262void UnwrappedLineParser::parseFile() {263 // The top-level context in a file always has declarations, except for pre-264 // processor directives and JavaScript files.265 bool MustBeDeclaration = !Line->InPPDirective && !Style.isJavaScript();266 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,267 MustBeDeclaration);268 if (Style.isTextProto() || (Style.isJson() && FormatTok->IsFirst))269 parseBracedList();270 else271 parseLevel();272 // Make sure to format the remaining tokens.273 //274 // LK_TextProto is special since its top-level is parsed as the body of a275 // braced list, which does not necessarily have natural line separators such276 // as a semicolon. Comments after the last entry that have been determined to277 // not belong to that line, as in:278 // key: value279 // // endfile comment280 // do not have a chance to be put on a line of their own until this point.281 // Here we add this newline before end-of-file comments.282 if (Style.isTextProto() && !CommentsBeforeNextToken.empty())283 addUnwrappedLine();284 flushComments(true);285 addUnwrappedLine();286}287 288void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {289 do {290 switch (FormatTok->Tok.getKind()) {291 case tok::l_brace:292 case tok::semi:293 return;294 default:295 if (FormatTok->is(Keywords.kw_where)) {296 addUnwrappedLine();297 nextToken();298 parseCSharpGenericTypeConstraint();299 break;300 }301 nextToken();302 break;303 }304 } while (!eof());305}306 307void UnwrappedLineParser::parseCSharpAttribute() {308 int UnpairedSquareBrackets = 1;309 do {310 switch (FormatTok->Tok.getKind()) {311 case tok::r_square:312 nextToken();313 --UnpairedSquareBrackets;314 if (UnpairedSquareBrackets == 0) {315 addUnwrappedLine();316 return;317 }318 break;319 case tok::l_square:320 ++UnpairedSquareBrackets;321 nextToken();322 break;323 default:324 nextToken();325 break;326 }327 } while (!eof());328}329 330bool UnwrappedLineParser::precededByCommentOrPPDirective() const {331 if (!Lines.empty() && Lines.back().InPPDirective)332 return true;333 334 const FormatToken *Previous = Tokens->getPreviousToken();335 return Previous && Previous->is(tok::comment) &&336 (Previous->IsMultiline || Previous->NewlinesBefore > 0);337}338 339/// Parses a level, that is ???.340/// \param OpeningBrace Opening brace (\p nullptr if absent) of that level.341/// \param IfKind The \p if statement kind in the level.342/// \param IfLeftBrace The left brace of the \p if block in the level.343/// \returns true if a simple block of if/else/for/while, or false otherwise.344/// (A simple block has a single statement.)345bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,346 IfStmtKind *IfKind,347 FormatToken **IfLeftBrace) {348 const bool InRequiresExpression =349 OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);350 const bool IsPrecededByCommentOrPPDirective =351 !Style.RemoveBracesLLVM || precededByCommentOrPPDirective();352 FormatToken *IfLBrace = nullptr;353 bool HasDoWhile = false;354 bool HasLabel = false;355 unsigned StatementCount = 0;356 bool SwitchLabelEncountered = false;357 358 do {359 if (FormatTok->isAttribute()) {360 nextToken();361 if (FormatTok->is(tok::l_paren))362 parseParens();363 continue;364 }365 tok::TokenKind Kind = FormatTok->Tok.getKind();366 if (FormatTok->is(TT_MacroBlockBegin))367 Kind = tok::l_brace;368 else if (FormatTok->is(TT_MacroBlockEnd))369 Kind = tok::r_brace;370 371 auto ParseDefault = [this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,372 &HasLabel, &StatementCount] {373 parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,374 HasDoWhile ? nullptr : &HasDoWhile,375 HasLabel ? nullptr : &HasLabel);376 ++StatementCount;377 assert(StatementCount > 0 && "StatementCount overflow!");378 };379 380 switch (Kind) {381 case tok::comment:382 nextToken();383 addUnwrappedLine();384 break;385 case tok::l_brace:386 if (InRequiresExpression) {387 FormatTok->setFinalizedType(TT_CompoundRequirementLBrace);388 } else if (FormatTok->Previous &&389 FormatTok->Previous->ClosesRequiresClause) {390 // We need the 'default' case here to correctly parse a function391 // l_brace.392 ParseDefault();393 continue;394 }395 if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {396 if (tryToParseBracedList())397 continue;398 FormatTok->setFinalizedType(TT_BlockLBrace);399 }400 parseBlock();401 ++StatementCount;402 assert(StatementCount > 0 && "StatementCount overflow!");403 addUnwrappedLine();404 break;405 case tok::r_brace:406 if (OpeningBrace) {407 if (!Style.RemoveBracesLLVM || Line->InPPDirective ||408 OpeningBrace->isNoneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {409 return false;410 }411 if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||412 HasDoWhile || IsPrecededByCommentOrPPDirective ||413 precededByCommentOrPPDirective()) {414 return false;415 }416 const FormatToken *Next = Tokens->peekNextToken();417 if (Next->is(tok::comment) && Next->NewlinesBefore == 0)418 return false;419 if (IfLeftBrace)420 *IfLeftBrace = IfLBrace;421 return true;422 }423 nextToken();424 addUnwrappedLine();425 break;426 case tok::kw_default: {427 unsigned StoredPosition = Tokens->getPosition();428 auto *Next = Tokens->getNextNonComment();429 FormatTok = Tokens->setPosition(StoredPosition);430 if (Next->isNoneOf(tok::colon, tok::arrow)) {431 // default not followed by `:` or `->` is not a case label; treat it432 // like an identifier.433 parseStructuralElement();434 break;435 }436 // Else, if it is 'default:', fall through to the case handling.437 [[fallthrough]];438 }439 case tok::kw_case:440 if (Style.Language == FormatStyle::LK_Proto || Style.isVerilog() ||441 (Style.isJavaScript() && Line->MustBeDeclaration)) {442 // Proto: there are no switch/case statements443 // Verilog: Case labels don't have this word. We handle case444 // labels including default in TokenAnnotator.445 // JavaScript: A 'case: string' style field declaration.446 ParseDefault();447 break;448 }449 if (!SwitchLabelEncountered &&450 (Style.IndentCaseLabels ||451 (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||452 (Line->InPPDirective && Line->Level == 1))) {453 ++Line->Level;454 }455 SwitchLabelEncountered = true;456 parseStructuralElement();457 break;458 case tok::l_square:459 if (Style.isCSharp()) {460 nextToken();461 parseCSharpAttribute();462 break;463 }464 if (handleCppAttributes())465 break;466 [[fallthrough]];467 default:468 ParseDefault();469 break;470 }471 } while (!eof());472 473 return false;474}475 476void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {477 // We'll parse forward through the tokens until we hit478 // a closing brace or eof - note that getNextToken() will479 // parse macros, so this will magically work inside macro480 // definitions, too.481 unsigned StoredPosition = Tokens->getPosition();482 FormatToken *Tok = FormatTok;483 const FormatToken *PrevTok = Tok->Previous;484 // Keep a stack of positions of lbrace tokens. We will485 // update information about whether an lbrace starts a486 // braced init list or a different block during the loop.487 struct StackEntry {488 FormatToken *Tok;489 const FormatToken *PrevTok;490 };491 SmallVector<StackEntry, 8> LBraceStack;492 assert(Tok->is(tok::l_brace));493 494 do {495 auto *NextTok = Tokens->getNextNonComment();496 497 if (!Line->InMacroBody && !Style.isTableGen()) {498 // Skip PPDirective lines (except macro definitions) and comments.499 while (NextTok->is(tok::hash)) {500 NextTok = Tokens->getNextToken();501 if (NextTok->isOneOf(tok::pp_not_keyword, tok::pp_define))502 break;503 do {504 NextTok = Tokens->getNextToken();505 } while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));506 507 while (NextTok->is(tok::comment))508 NextTok = Tokens->getNextToken();509 }510 }511 512 switch (Tok->Tok.getKind()) {513 case tok::l_brace:514 if (Style.isJavaScript() && PrevTok) {515 if (PrevTok->isOneOf(tok::colon, tok::less)) {516 // A ':' indicates this code is in a type, or a braced list517 // following a label in an object literal ({a: {b: 1}}).518 // A '<' could be an object used in a comparison, but that is nonsense519 // code (can never return true), so more likely it is a generic type520 // argument (`X<{a: string; b: number}>`).521 // The code below could be confused by semicolons between the522 // individual members in a type member list, which would normally523 // trigger BK_Block. In both cases, this must be parsed as an inline524 // braced init.525 Tok->setBlockKind(BK_BracedInit);526 } else if (PrevTok->is(tok::r_paren)) {527 // `) { }` can only occur in function or method declarations in JS.528 Tok->setBlockKind(BK_Block);529 }530 } else {531 Tok->setBlockKind(BK_Unknown);532 }533 LBraceStack.push_back({Tok, PrevTok});534 break;535 case tok::r_brace:536 if (LBraceStack.empty())537 break;538 if (auto *LBrace = LBraceStack.back().Tok; LBrace->is(BK_Unknown)) {539 bool ProbablyBracedList = false;540 if (Style.Language == FormatStyle::LK_Proto) {541 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);542 } else if (LBrace->isNot(TT_EnumLBrace)) {543 // Using OriginalColumn to distinguish between ObjC methods and544 // binary operators is a bit hacky.545 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&546 NextTok->OriginalColumn == 0;547 548 // Try to detect a braced list. Note that regardless how we mark inner549 // braces here, we will overwrite the BlockKind later if we parse a550 // braced list (where all blocks inside are by default braced lists),551 // or when we explicitly detect blocks (for example while parsing552 // lambdas).553 554 // If we already marked the opening brace as braced list, the closing555 // must also be part of it.556 ProbablyBracedList = LBrace->is(TT_BracedListLBrace);557 558 ProbablyBracedList = ProbablyBracedList ||559 (Style.isJavaScript() &&560 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,561 Keywords.kw_as));562 ProbablyBracedList =563 ProbablyBracedList ||564 (IsCpp && (PrevTok->Tok.isLiteral() ||565 NextTok->isOneOf(tok::l_paren, tok::arrow)));566 567 // If there is a comma, semicolon or right paren after the closing568 // brace, we assume this is a braced initializer list.569 // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a570 // braced list in JS.571 ProbablyBracedList =572 ProbablyBracedList ||573 NextTok->isOneOf(tok::comma, tok::period, tok::colon,574 tok::r_paren, tok::r_square, tok::ellipsis);575 576 // Distinguish between braced list in a constructor initializer list577 // followed by constructor body, or just adjacent blocks.578 ProbablyBracedList =579 ProbablyBracedList ||580 (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&581 LBraceStack.back().PrevTok->isOneOf(tok::identifier,582 tok::greater));583 584 ProbablyBracedList =585 ProbablyBracedList ||586 (NextTok->is(tok::identifier) &&587 PrevTok->isNoneOf(tok::semi, tok::r_brace, tok::l_brace));588 589 ProbablyBracedList = ProbablyBracedList ||590 (NextTok->is(tok::semi) &&591 (!ExpectClassBody || LBraceStack.size() != 1));592 593 ProbablyBracedList =594 ProbablyBracedList ||595 (NextTok->isBinaryOperator() && !NextIsObjCMethod);596 597 if (!Style.isCSharp() && NextTok->is(tok::l_square)) {598 // We can have an array subscript after a braced init599 // list, but C++11 attributes are expected after blocks.600 NextTok = Tokens->getNextToken();601 ProbablyBracedList = NextTok->isNot(tok::l_square);602 }603 604 // Cpp macro definition body that is a nonempty braced list or block:605 if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&606 !FormatTok->Previous && NextTok->is(tok::eof) &&607 // A statement can end with only `;` (simple statement), a block608 // closing brace (compound statement), or `:` (label statement).609 // If PrevTok is a block opening brace, Tok ends an empty block.610 PrevTok->isNoneOf(tok::semi, BK_Block, tok::colon)) {611 ProbablyBracedList = true;612 }613 }614 const auto BlockKind = ProbablyBracedList ? BK_BracedInit : BK_Block;615 Tok->setBlockKind(BlockKind);616 LBrace->setBlockKind(BlockKind);617 }618 LBraceStack.pop_back();619 break;620 case tok::identifier:621 if (Tok->isNot(TT_StatementMacro))622 break;623 [[fallthrough]];624 case tok::at:625 case tok::semi:626 case tok::kw_if:627 case tok::kw_while:628 case tok::kw_for:629 case tok::kw_switch:630 case tok::kw_try:631 case tok::kw___try:632 if (!LBraceStack.empty() && LBraceStack.back().Tok->is(BK_Unknown))633 LBraceStack.back().Tok->setBlockKind(BK_Block);634 break;635 default:636 break;637 }638 639 PrevTok = Tok;640 Tok = NextTok;641 } while (Tok->isNot(tok::eof) && !LBraceStack.empty());642 643 // Assume other blocks for all unclosed opening braces.644 for (const auto &Entry : LBraceStack)645 if (Entry.Tok->is(BK_Unknown))646 Entry.Tok->setBlockKind(BK_Block);647 648 FormatTok = Tokens->setPosition(StoredPosition);649}650 651// Sets the token type of the directly previous right brace.652void UnwrappedLineParser::setPreviousRBraceType(TokenType Type) {653 if (auto Prev = FormatTok->getPreviousNonComment();654 Prev && Prev->is(tok::r_brace)) {655 Prev->setFinalizedType(Type);656 }657}658 659template <class T>660static inline void hash_combine(std::size_t &seed, const T &v) {661 std::hash<T> hasher;662 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);663}664 665size_t UnwrappedLineParser::computePPHash() const {666 size_t h = 0;667 for (const auto &i : PPStack) {668 hash_combine(h, size_t(i.Kind));669 hash_combine(h, i.Line);670 }671 return h;672}673 674// Checks whether \p ParsedLine might fit on a single line. If \p OpeningBrace675// is not null, subtracts its length (plus the preceding space) when computing676// the length of \p ParsedLine. We must clone the tokens of \p ParsedLine before677// running the token annotator on it so that we can restore them afterward.678bool UnwrappedLineParser::mightFitOnOneLine(679 UnwrappedLine &ParsedLine, const FormatToken *OpeningBrace) const {680 const auto ColumnLimit = Style.ColumnLimit;681 if (ColumnLimit == 0)682 return true;683 684 auto &Tokens = ParsedLine.Tokens;685 assert(!Tokens.empty());686 687 const auto *LastToken = Tokens.back().Tok;688 assert(LastToken);689 690 SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());691 692 int Index = 0;693 for (const auto &Token : Tokens) {694 assert(Token.Tok);695 auto &SavedToken = SavedTokens[Index++];696 SavedToken.Tok = new FormatToken;697 SavedToken.Tok->copyFrom(*Token.Tok);698 SavedToken.Children = std::move(Token.Children);699 }700 701 AnnotatedLine Line(ParsedLine);702 assert(Line.Last == LastToken);703 704 TokenAnnotator Annotator(Style, Keywords);705 Annotator.annotate(Line);706 Annotator.calculateFormattingInformation(Line);707 708 auto Length = LastToken->TotalLength;709 if (OpeningBrace) {710 assert(OpeningBrace != Tokens.front().Tok);711 if (auto Prev = OpeningBrace->Previous;712 Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {713 Length -= ColumnLimit;714 }715 Length -= OpeningBrace->TokenText.size() + 1;716 }717 718 if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {719 assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));720 Length -= FirstToken->TokenText.size() + 1;721 }722 723 Index = 0;724 for (auto &Token : Tokens) {725 const auto &SavedToken = SavedTokens[Index++];726 Token.Tok->copyFrom(*SavedToken.Tok);727 Token.Children = std::move(SavedToken.Children);728 delete SavedToken.Tok;729 }730 731 // If these change PPLevel needs to be used for get correct indentation.732 assert(!Line.InMacroBody);733 assert(!Line.InPPDirective);734 return Line.Level * Style.IndentWidth + Length <= ColumnLimit;735}736 737FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration,738 unsigned AddLevels, bool MunchSemi,739 bool KeepBraces,740 IfStmtKind *IfKind,741 bool UnindentWhitesmithsBraces) {742 auto HandleVerilogBlockLabel = [this]() {743 // ":" name744 if (Style.isVerilog() && FormatTok->is(tok::colon)) {745 nextToken();746 if (Keywords.isVerilogIdentifier(*FormatTok))747 nextToken();748 }749 };750 751 // Whether this is a Verilog-specific block that has a special header like a752 // module.753 const bool VerilogHierarchy =754 Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);755 assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||756 (Style.isVerilog() &&757 (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&758 "'{' or macro block token expected");759 FormatToken *Tok = FormatTok;760 const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);761 auto Index = CurrentLines->size();762 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);763 FormatTok->setBlockKind(BK_Block);764 765 // For Whitesmiths mode, jump to the next level prior to skipping over the766 // braces.767 if (!VerilogHierarchy && AddLevels > 0 &&768 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {769 ++Line->Level;770 }771 772 size_t PPStartHash = computePPHash();773 774 const unsigned InitialLevel = Line->Level;775 if (VerilogHierarchy) {776 AddLevels += parseVerilogHierarchyHeader();777 } else {778 nextToken(/*LevelDifference=*/AddLevels);779 HandleVerilogBlockLabel();780 }781 782 // Bail out if there are too many levels. Otherwise, the stack might overflow.783 if (Line->Level > 300)784 return nullptr;785 786 if (MacroBlock && FormatTok->is(tok::l_paren))787 parseParens();788 789 size_t NbPreprocessorDirectives =790 !parsingPPDirective() ? PreprocessorDirectives.size() : 0;791 addUnwrappedLine();792 size_t OpeningLineIndex =793 CurrentLines->empty()794 ? (UnwrappedLine::kInvalidIndex)795 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);796 797 // Whitesmiths is weird here. The brace needs to be indented for the namespace798 // block, but the block itself may not be indented depending on the style799 // settings. This allows the format to back up one level in those cases.800 if (UnindentWhitesmithsBraces)801 --Line->Level;802 803 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,804 MustBeDeclaration);805 if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)806 Line->Level += AddLevels;807 808 FormatToken *IfLBrace = nullptr;809 const bool SimpleBlock = parseLevel(Tok, IfKind, &IfLBrace);810 811 if (eof())812 return IfLBrace;813 814 if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)815 : FormatTok->isNot(tok::r_brace)) {816 Line->Level = InitialLevel;817 FormatTok->setBlockKind(BK_Block);818 return IfLBrace;819 }820 821 if (FormatTok->is(tok::r_brace)) {822 FormatTok->setBlockKind(BK_Block);823 if (Tok->is(TT_NamespaceLBrace))824 FormatTok->setFinalizedType(TT_NamespaceRBrace);825 }826 827 const bool IsFunctionRBrace =828 FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);829 830 auto RemoveBraces = [=]() mutable {831 if (!SimpleBlock)832 return false;833 assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));834 assert(FormatTok->is(tok::r_brace));835 const bool WrappedOpeningBrace = !Tok->Previous;836 if (WrappedOpeningBrace && FollowedByComment)837 return false;838 const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;839 if (KeepBraces && !HasRequiredIfBraces)840 return false;841 if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {842 const FormatToken *Previous = Tokens->getPreviousToken();843 assert(Previous);844 if (Previous->is(tok::r_brace) && !Previous->Optional)845 return false;846 }847 assert(!CurrentLines->empty());848 auto &LastLine = CurrentLines->back();849 if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))850 return false;851 if (Tok->is(TT_ElseLBrace))852 return true;853 if (WrappedOpeningBrace) {854 assert(Index > 0);855 --Index; // The line above the wrapped l_brace.856 Tok = nullptr;857 }858 return mightFitOnOneLine((*CurrentLines)[Index], Tok);859 };860 if (RemoveBraces()) {861 Tok->MatchingParen = FormatTok;862 FormatTok->MatchingParen = Tok;863 }864 865 size_t PPEndHash = computePPHash();866 867 // Munch the closing brace.868 nextToken(/*LevelDifference=*/-AddLevels);869 870 // When this is a function block and there is an unnecessary semicolon871 // afterwards then mark it as optional (so the RemoveSemi pass can get rid of872 // it later).873 if (Style.RemoveSemicolon && IsFunctionRBrace) {874 while (FormatTok->is(tok::semi)) {875 FormatTok->Optional = true;876 nextToken();877 }878 }879 880 HandleVerilogBlockLabel();881 882 if (MacroBlock && FormatTok->is(tok::l_paren))883 parseParens();884 885 Line->Level = InitialLevel;886 887 if (FormatTok->is(tok::kw_noexcept)) {888 // A noexcept in a requires expression.889 nextToken();890 }891 892 if (FormatTok->is(tok::arrow)) {893 // Following the } or noexcept we can find a trailing return type arrow894 // as part of an implicit conversion constraint.895 nextToken();896 parseStructuralElement();897 }898 899 if (MunchSemi && FormatTok->is(tok::semi))900 nextToken();901 902 if (PPStartHash == PPEndHash) {903 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;904 if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {905 // Update the opening line to add the forward reference as well906 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =907 CurrentLines->size() - 1;908 }909 }910 911 return IfLBrace;912}913 914static bool isGoogScope(const UnwrappedLine &Line) {915 // FIXME: Closure-library specific stuff should not be hard-coded but be916 // configurable.917 if (Line.Tokens.size() < 4)918 return false;919 auto I = Line.Tokens.begin();920 if (I->Tok->TokenText != "goog")921 return false;922 ++I;923 if (I->Tok->isNot(tok::period))924 return false;925 ++I;926 if (I->Tok->TokenText != "scope")927 return false;928 ++I;929 return I->Tok->is(tok::l_paren);930}931 932static bool isIIFE(const UnwrappedLine &Line,933 const AdditionalKeywords &Keywords) {934 // Look for the start of an immediately invoked anonymous function.935 // https://en.wikipedia.org/wiki/Immediately-invoked_function_expression936 // This is commonly done in JavaScript to create a new, anonymous scope.937 // Example: (function() { ... })()938 if (Line.Tokens.size() < 3)939 return false;940 auto I = Line.Tokens.begin();941 if (I->Tok->isNot(tok::l_paren))942 return false;943 ++I;944 if (I->Tok->isNot(Keywords.kw_function))945 return false;946 ++I;947 return I->Tok->is(tok::l_paren);948}949 950static bool ShouldBreakBeforeBrace(const FormatStyle &Style,951 const FormatToken &InitialToken,952 const bool IsJavaRecord) {953 if (IsJavaRecord)954 return Style.BraceWrapping.AfterClass;955 956 tok::TokenKind Kind = InitialToken.Tok.getKind();957 if (InitialToken.is(TT_NamespaceMacro))958 Kind = tok::kw_namespace;959 960 switch (Kind) {961 case tok::kw_namespace:962 return Style.BraceWrapping.AfterNamespace;963 case tok::kw_class:964 return Style.BraceWrapping.AfterClass;965 case tok::kw_union:966 return Style.BraceWrapping.AfterUnion;967 case tok::kw_struct:968 return Style.BraceWrapping.AfterStruct;969 case tok::kw_enum:970 return Style.BraceWrapping.AfterEnum;971 default:972 return false;973 }974}975 976void UnwrappedLineParser::parseChildBlock() {977 assert(FormatTok->is(tok::l_brace));978 FormatTok->setBlockKind(BK_Block);979 const FormatToken *OpeningBrace = FormatTok;980 nextToken();981 {982 bool SkipIndent = (Style.isJavaScript() &&983 (isGoogScope(*Line) || isIIFE(*Line, Keywords)));984 ScopedLineState LineState(*this);985 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,986 /*MustBeDeclaration=*/false);987 Line->Level += SkipIndent ? 0 : 1;988 parseLevel(OpeningBrace);989 flushComments(isOnNewLine(*FormatTok));990 Line->Level -= SkipIndent ? 0 : 1;991 }992 nextToken();993}994 995void UnwrappedLineParser::parsePPDirective() {996 assert(FormatTok->is(tok::hash) && "'#' expected");997 ScopedMacroState MacroState(*Line, Tokens, FormatTok);998 999 nextToken();1000 1001 if (!FormatTok->Tok.getIdentifierInfo()) {1002 parsePPUnknown();1003 return;1004 }1005 1006 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {1007 case tok::pp_define:1008 parsePPDefine();1009 return;1010 case tok::pp_if:1011 parsePPIf(/*IfDef=*/false);1012 break;1013 case tok::pp_ifdef:1014 case tok::pp_ifndef:1015 parsePPIf(/*IfDef=*/true);1016 break;1017 case tok::pp_else:1018 case tok::pp_elifdef:1019 case tok::pp_elifndef:1020 case tok::pp_elif:1021 parsePPElse();1022 break;1023 case tok::pp_endif:1024 parsePPEndIf();1025 break;1026 case tok::pp_pragma:1027 parsePPPragma();1028 break;1029 case tok::pp_error:1030 case tok::pp_warning:1031 nextToken();1032 if (!eof() && Style.isCpp())1033 FormatTok->setFinalizedType(TT_AfterPPDirective);1034 [[fallthrough]];1035 default:1036 parsePPUnknown();1037 break;1038 }1039}1040 1041void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {1042 size_t Line = CurrentLines->size();1043 if (CurrentLines == &PreprocessorDirectives)1044 Line += Lines.size();1045 1046 if (Unreachable ||1047 (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) {1048 PPStack.push_back({PP_Unreachable, Line});1049 } else {1050 PPStack.push_back({PP_Conditional, Line});1051 }1052}1053 1054void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {1055 ++PPBranchLevel;1056 assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());1057 if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {1058 PPLevelBranchIndex.push_back(0);1059 PPLevelBranchCount.push_back(0);1060 }1061 PPChainBranchIndex.push(Unreachable ? -1 : 0);1062 bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;1063 conditionalCompilationCondition(Unreachable || Skip);1064}1065 1066void UnwrappedLineParser::conditionalCompilationAlternative() {1067 if (!PPStack.empty())1068 PPStack.pop_back();1069 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());1070 if (!PPChainBranchIndex.empty())1071 ++PPChainBranchIndex.top();1072 conditionalCompilationCondition(1073 PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&1074 PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());1075}1076 1077void UnwrappedLineParser::conditionalCompilationEnd() {1078 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());1079 if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {1080 if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel])1081 PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;1082 }1083 // Guard against #endif's without #if.1084 if (PPBranchLevel > -1)1085 --PPBranchLevel;1086 if (!PPChainBranchIndex.empty())1087 PPChainBranchIndex.pop();1088 if (!PPStack.empty())1089 PPStack.pop_back();1090}1091 1092void UnwrappedLineParser::parsePPIf(bool IfDef) {1093 bool IfNDef = FormatTok->is(tok::pp_ifndef);1094 nextToken();1095 bool Unreachable = false;1096 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0"))1097 Unreachable = true;1098 if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")1099 Unreachable = true;1100 conditionalCompilationStart(Unreachable);1101 FormatToken *IfCondition = FormatTok;1102 // If there's a #ifndef on the first line, and the only lines before it are1103 // comments, it could be an include guard.1104 bool MaybeIncludeGuard = IfNDef;1105 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {1106 for (auto &Line : Lines) {1107 if (Line.Tokens.front().Tok->isNot(tok::comment)) {1108 MaybeIncludeGuard = false;1109 IncludeGuard = IG_Rejected;1110 break;1111 }1112 }1113 }1114 --PPBranchLevel;1115 parsePPUnknown();1116 ++PPBranchLevel;1117 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {1118 IncludeGuard = IG_IfNdefed;1119 IncludeGuardToken = IfCondition;1120 }1121}1122 1123void UnwrappedLineParser::parsePPElse() {1124 // If a potential include guard has an #else, it's not an include guard.1125 if (IncludeGuard == IG_Defined && PPBranchLevel == 0)1126 IncludeGuard = IG_Rejected;1127 // Don't crash when there is an #else without an #if.1128 assert(PPBranchLevel >= -1);1129 if (PPBranchLevel == -1)1130 conditionalCompilationStart(/*Unreachable=*/true);1131 conditionalCompilationAlternative();1132 --PPBranchLevel;1133 parsePPUnknown();1134 ++PPBranchLevel;1135}1136 1137void UnwrappedLineParser::parsePPEndIf() {1138 conditionalCompilationEnd();1139 parsePPUnknown();1140 // If the #endif of a potential include guard is the last thing in the file,1141 // then we found an include guard.1142 if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&1143 getIncludeGuardState(Style.IndentPPDirectives) == IG_Inited) {1144 IncludeGuard = IG_Found;1145 }1146}1147 1148void UnwrappedLineParser::parsePPDefine() {1149 nextToken();1150 1151 if (!FormatTok->Tok.getIdentifierInfo()) {1152 IncludeGuard = IG_Rejected;1153 IncludeGuardToken = nullptr;1154 parsePPUnknown();1155 return;1156 }1157 1158 bool MaybeIncludeGuard = false;1159 if (IncludeGuard == IG_IfNdefed &&1160 IncludeGuardToken->TokenText == FormatTok->TokenText) {1161 IncludeGuard = IG_Defined;1162 IncludeGuardToken = nullptr;1163 for (auto &Line : Lines) {1164 if (Line.Tokens.front().Tok->isNoneOf(tok::comment, tok::hash)) {1165 IncludeGuard = IG_Rejected;1166 break;1167 }1168 }1169 MaybeIncludeGuard = IncludeGuard == IG_Defined;1170 }1171 1172 // In the context of a define, even keywords should be treated as normal1173 // identifiers. Setting the kind to identifier is not enough, because we need1174 // to treat additional keywords like __except as well, which are already1175 // identifiers. Setting the identifier info to null interferes with include1176 // guard processing above, and changes preprocessing nesting.1177 FormatTok->Tok.setKind(tok::identifier);1178 FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);1179 nextToken();1180 1181 // IncludeGuard can't have a non-empty macro definition.1182 if (MaybeIncludeGuard && !eof())1183 IncludeGuard = IG_Rejected;1184 1185 if (FormatTok->is(tok::l_paren) && !FormatTok->hasWhitespaceBefore())1186 parseParens();1187 if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)1188 Line->Level += PPBranchLevel + 1;1189 addUnwrappedLine();1190 ++Line->Level;1191 1192 Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);1193 assert((int)Line->PPLevel >= 0);1194 1195 if (eof())1196 return;1197 1198 Line->InMacroBody = true;1199 1200 if (!Style.SkipMacroDefinitionBody) {1201 // Errors during a preprocessor directive can only affect the layout of the1202 // preprocessor directive, and thus we ignore them. An alternative approach1203 // would be to use the same approach we use on the file level (no1204 // re-indentation if there was a structural error) within the macro1205 // definition.1206 parseFile();1207 return;1208 }1209 1210 for (auto *Comment : CommentsBeforeNextToken)1211 Comment->Finalized = true;1212 1213 do {1214 FormatTok->Finalized = true;1215 FormatTok = Tokens->getNextToken();1216 } while (!eof());1217 1218 addUnwrappedLine();1219}1220 1221void UnwrappedLineParser::parsePPPragma() {1222 Line->InPragmaDirective = true;1223 parsePPUnknown();1224}1225 1226void UnwrappedLineParser::parsePPUnknown() {1227 while (!eof())1228 nextToken();1229 if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)1230 Line->Level += PPBranchLevel + 1;1231 addUnwrappedLine();1232}1233 1234// Here we exclude certain tokens that are not usually the first token in an1235// unwrapped line. This is used in attempt to distinguish macro calls without1236// trailing semicolons from other constructs split to several lines.1237static bool tokenCanStartNewLine(const FormatToken &Tok) {1238 // Semicolon can be a null-statement, l_square can be a start of a macro or1239 // a C++11 attribute, but this doesn't seem to be common.1240 return Tok.isNoneOf(tok::semi, tok::l_brace,1241 // Tokens that can only be used as binary operators and a1242 // part of overloaded operator names.1243 tok::period, tok::periodstar, tok::arrow, tok::arrowstar,1244 tok::less, tok::greater, tok::slash, tok::percent,1245 tok::lessless, tok::greatergreater, tok::equal,1246 tok::plusequal, tok::minusequal, tok::starequal,1247 tok::slashequal, tok::percentequal, tok::ampequal,1248 tok::pipeequal, tok::caretequal, tok::greatergreaterequal,1249 tok::lesslessequal,1250 // Colon is used in labels, base class lists, initializer1251 // lists, range-based for loops, ternary operator, but1252 // should never be the first token in an unwrapped line.1253 tok::colon,1254 // 'noexcept' is a trailing annotation.1255 tok::kw_noexcept);1256}1257 1258static bool mustBeJSIdent(const AdditionalKeywords &Keywords,1259 const FormatToken *FormatTok) {1260 // FIXME: This returns true for C/C++ keywords like 'struct'.1261 return FormatTok->is(tok::identifier) &&1262 (!FormatTok->Tok.getIdentifierInfo() ||1263 FormatTok->isNoneOf(1264 Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async,1265 Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally,1266 Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,1267 Keywords.kw_let, Keywords.kw_var, tok::kw_const,1268 Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,1269 Keywords.kw_instanceof, Keywords.kw_interface,1270 Keywords.kw_override, Keywords.kw_throws, Keywords.kw_from));1271}1272 1273static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,1274 const FormatToken *FormatTok) {1275 return FormatTok->Tok.isLiteral() ||1276 FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||1277 mustBeJSIdent(Keywords, FormatTok);1278}1279 1280// isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement1281// when encountered after a value (see mustBeJSIdentOrValue).1282static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,1283 const FormatToken *FormatTok) {1284 return FormatTok->isOneOf(1285 tok::kw_return, Keywords.kw_yield,1286 // conditionals1287 tok::kw_if, tok::kw_else,1288 // loops1289 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,1290 // switch/case1291 tok::kw_switch, tok::kw_case,1292 // exceptions1293 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,1294 // declaration1295 tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,1296 Keywords.kw_async, Keywords.kw_function,1297 // import/export1298 Keywords.kw_import, tok::kw_export);1299}1300 1301// Checks whether a token is a type in K&R C (aka C78).1302static bool isC78Type(const FormatToken &Tok) {1303 return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,1304 tok::kw_unsigned, tok::kw_float, tok::kw_double,1305 tok::identifier);1306}1307 1308// This function checks whether a token starts the first parameter declaration1309// in a K&R C (aka C78) function definition, e.g.:1310// int f(a, b)1311// short a, b;1312// {1313// return a + b;1314// }1315static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next,1316 const FormatToken *FuncName) {1317 assert(Tok);1318 assert(Next);1319 assert(FuncName);1320 1321 if (FuncName->isNot(tok::identifier))1322 return false;1323 1324 const FormatToken *Prev = FuncName->Previous;1325 if (!Prev || (Prev->isNot(tok::star) && !isC78Type(*Prev)))1326 return false;1327 1328 if (!isC78Type(*Tok) &&1329 Tok->isNoneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {1330 return false;1331 }1332 1333 if (Next->isNot(tok::star) && !Next->Tok.getIdentifierInfo())1334 return false;1335 1336 Tok = Tok->Previous;1337 if (!Tok || Tok->isNot(tok::r_paren))1338 return false;1339 1340 Tok = Tok->Previous;1341 if (!Tok || Tok->isNot(tok::identifier))1342 return false;1343 1344 return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);1345}1346 1347bool UnwrappedLineParser::parseModuleImport() {1348 assert(FormatTok->is(Keywords.kw_import) && "'import' expected");1349 1350 if (auto Token = Tokens->peekNextToken(/*SkipComment=*/true);1351 !Token->Tok.getIdentifierInfo() &&1352 Token->isNoneOf(tok::colon, tok::less, tok::string_literal)) {1353 return false;1354 }1355 1356 nextToken();1357 while (!eof()) {1358 if (FormatTok->is(tok::colon)) {1359 FormatTok->setFinalizedType(TT_ModulePartitionColon);1360 }1361 // Handle import <foo/bar.h> as we would an include statement.1362 else if (FormatTok->is(tok::less)) {1363 nextToken();1364 while (FormatTok->isNoneOf(tok::semi, tok::greater) && !eof()) {1365 // Mark tokens up to the trailing line comments as implicit string1366 // literals.1367 if (FormatTok->isNot(tok::comment) &&1368 !FormatTok->TokenText.starts_with("//")) {1369 FormatTok->setFinalizedType(TT_ImplicitStringLiteral);1370 }1371 nextToken();1372 }1373 }1374 if (FormatTok->is(tok::semi)) {1375 nextToken();1376 break;1377 }1378 nextToken();1379 }1380 1381 addUnwrappedLine();1382 return true;1383}1384 1385// readTokenWithJavaScriptASI reads the next token and terminates the current1386// line if JavaScript Automatic Semicolon Insertion must1387// happen between the current token and the next token.1388//1389// This method is conservative - it cannot cover all edge cases of JavaScript,1390// but only aims to correctly handle certain well known cases. It *must not*1391// return true in speculative cases.1392void UnwrappedLineParser::readTokenWithJavaScriptASI() {1393 FormatToken *Previous = FormatTok;1394 readToken();1395 FormatToken *Next = FormatTok;1396 1397 bool IsOnSameLine =1398 CommentsBeforeNextToken.empty()1399 ? Next->NewlinesBefore == 01400 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;1401 if (IsOnSameLine)1402 return;1403 1404 bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);1405 bool PreviousStartsTemplateExpr =1406 Previous->is(TT_TemplateString) && Previous->TokenText.ends_with("${");1407 if (PreviousMustBeValue || Previous->is(tok::r_paren)) {1408 // If the line contains an '@' sign, the previous token might be an1409 // annotation, which can precede another identifier/value.1410 bool HasAt = llvm::any_of(Line->Tokens, [](UnwrappedLineNode &LineNode) {1411 return LineNode.Tok->is(tok::at);1412 });1413 if (HasAt)1414 return;1415 }1416 if (Next->is(tok::exclaim) && PreviousMustBeValue)1417 return addUnwrappedLine();1418 bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);1419 bool NextEndsTemplateExpr =1420 Next->is(TT_TemplateString) && Next->TokenText.starts_with("}");1421 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&1422 (PreviousMustBeValue ||1423 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,1424 tok::minusminus))) {1425 return addUnwrappedLine();1426 }1427 if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&1428 isJSDeclOrStmt(Keywords, Next)) {1429 return addUnwrappedLine();1430 }1431}1432 1433void UnwrappedLineParser::parseStructuralElement(1434 const FormatToken *OpeningBrace, IfStmtKind *IfKind,1435 FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) {1436 if (Style.isTableGen() && FormatTok->is(tok::pp_include)) {1437 nextToken();1438 if (FormatTok->is(tok::string_literal))1439 nextToken();1440 addUnwrappedLine();1441 return;1442 }1443 1444 if (IsCpp) {1445 while (FormatTok->is(tok::l_square) && handleCppAttributes()) {1446 }1447 } else if (Style.isVerilog()) {1448 if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {1449 parseForOrWhileLoop(/*HasParens=*/false);1450 return;1451 }1452 if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {1453 parseForOrWhileLoop();1454 return;1455 }1456 if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,1457 Keywords.kw_assume, Keywords.kw_cover)) {1458 parseIfThenElse(IfKind, /*KeepBraces=*/false, /*IsVerilogAssert=*/true);1459 return;1460 }1461 1462 // Skip things that can exist before keywords like 'if' and 'case'.1463 while (true) {1464 if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,1465 Keywords.kw_unique0)) {1466 nextToken();1467 } else if (FormatTok->is(tok::l_paren) &&1468 Tokens->peekNextToken()->is(tok::star)) {1469 parseParens();1470 } else {1471 break;1472 }1473 }1474 }1475 1476 // Tokens that only make sense at the beginning of a line.1477 if (FormatTok->isAccessSpecifierKeyword()) {1478 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())1479 nextToken();1480 else1481 parseAccessSpecifier();1482 return;1483 }1484 switch (FormatTok->Tok.getKind()) {1485 case tok::kw_asm:1486 nextToken();1487 if (FormatTok->is(tok::l_brace)) {1488 FormatTok->setFinalizedType(TT_InlineASMBrace);1489 nextToken();1490 while (FormatTok && !eof()) {1491 if (FormatTok->is(tok::r_brace)) {1492 FormatTok->setFinalizedType(TT_InlineASMBrace);1493 nextToken();1494 addUnwrappedLine();1495 break;1496 }1497 FormatTok->Finalized = true;1498 nextToken();1499 }1500 }1501 break;1502 case tok::kw_namespace:1503 parseNamespace();1504 return;1505 case tok::kw_if: {1506 if (Style.isJavaScript() && Line->MustBeDeclaration) {1507 // field/method declaration.1508 break;1509 }1510 FormatToken *Tok = parseIfThenElse(IfKind);1511 if (IfLeftBrace)1512 *IfLeftBrace = Tok;1513 return;1514 }1515 case tok::kw_for:1516 case tok::kw_while:1517 if (Style.isJavaScript() && Line->MustBeDeclaration) {1518 // field/method declaration.1519 break;1520 }1521 parseForOrWhileLoop();1522 return;1523 case tok::kw_do:1524 if (Style.isJavaScript() && Line->MustBeDeclaration) {1525 // field/method declaration.1526 break;1527 }1528 parseDoWhile();1529 if (HasDoWhile)1530 *HasDoWhile = true;1531 return;1532 case tok::kw_switch:1533 if (Style.isJavaScript() && Line->MustBeDeclaration) {1534 // 'switch: string' field declaration.1535 break;1536 }1537 parseSwitch(/*IsExpr=*/false);1538 return;1539 case tok::kw_default: {1540 // In Verilog default along with other labels are handled in the next loop.1541 if (Style.isVerilog())1542 break;1543 if (Style.isJavaScript() && Line->MustBeDeclaration) {1544 // 'default: string' field declaration.1545 break;1546 }1547 auto *Default = FormatTok;1548 nextToken();1549 if (FormatTok->is(tok::colon)) {1550 FormatTok->setFinalizedType(TT_CaseLabelColon);1551 parseLabel();1552 return;1553 }1554 if (FormatTok->is(tok::arrow)) {1555 FormatTok->setFinalizedType(TT_CaseLabelArrow);1556 Default->setFinalizedType(TT_SwitchExpressionLabel);1557 parseLabel();1558 return;1559 }1560 // e.g. "default void f() {}" in a Java interface.1561 break;1562 }1563 case tok::kw_case:1564 // Proto: there are no switch/case statements.1565 if (Style.Language == FormatStyle::LK_Proto) {1566 nextToken();1567 return;1568 }1569 if (Style.isVerilog()) {1570 parseBlock();1571 addUnwrappedLine();1572 return;1573 }1574 if (Style.isJavaScript() && Line->MustBeDeclaration) {1575 // 'case: string' field declaration.1576 nextToken();1577 break;1578 }1579 parseCaseLabel();1580 return;1581 case tok::kw_goto:1582 nextToken();1583 if (FormatTok->is(tok::kw_case))1584 nextToken();1585 break;1586 case tok::kw_try:1587 case tok::kw___try:1588 if (Style.isJavaScript() && Line->MustBeDeclaration) {1589 // field/method declaration.1590 break;1591 }1592 parseTryCatch();1593 return;1594 case tok::kw_extern:1595 if (Style.isVerilog()) {1596 // In Verilog an extern module declaration looks like a start of module.1597 // But there is no body and endmodule. So we handle it separately.1598 parseVerilogExtern();1599 return;1600 }1601 nextToken();1602 if (FormatTok->is(tok::string_literal)) {1603 nextToken();1604 if (FormatTok->is(tok::l_brace)) {1605 if (Style.BraceWrapping.AfterExternBlock)1606 addUnwrappedLine();1607 // Either we indent or for backwards compatibility we follow the1608 // AfterExternBlock style.1609 unsigned AddLevels =1610 (Style.IndentExternBlock == FormatStyle::IEBS_Indent) ||1611 (Style.BraceWrapping.AfterExternBlock &&1612 Style.IndentExternBlock ==1613 FormatStyle::IEBS_AfterExternBlock)1614 ? 1u1615 : 0u;1616 parseBlock(/*MustBeDeclaration=*/true, AddLevels);1617 addUnwrappedLine();1618 return;1619 }1620 }1621 break;1622 case tok::kw_export:1623 if (Style.isJavaScript()) {1624 parseJavaScriptEs6ImportExport();1625 return;1626 }1627 if (Style.isVerilog()) {1628 parseVerilogExtern();1629 return;1630 }1631 if (IsCpp) {1632 nextToken();1633 if (FormatTok->is(tok::kw_namespace)) {1634 parseNamespace();1635 return;1636 }1637 if (FormatTok->is(tok::l_brace)) {1638 parseCppExportBlock();1639 return;1640 }1641 if (FormatTok->is(Keywords.kw_import) && parseModuleImport())1642 return;1643 }1644 break;1645 case tok::kw_inline:1646 nextToken();1647 if (FormatTok->is(tok::kw_namespace)) {1648 parseNamespace();1649 return;1650 }1651 break;1652 case tok::identifier:1653 if (FormatTok->is(TT_ForEachMacro)) {1654 parseForOrWhileLoop();1655 return;1656 }1657 if (FormatTok->is(TT_MacroBlockBegin)) {1658 parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,1659 /*MunchSemi=*/false);1660 return;1661 }1662 if (FormatTok->is(Keywords.kw_import)) {1663 if (Style.isJavaScript()) {1664 parseJavaScriptEs6ImportExport();1665 return;1666 }1667 if (Style.Language == FormatStyle::LK_Proto) {1668 nextToken();1669 if (FormatTok->is(tok::kw_public))1670 nextToken();1671 if (FormatTok->isNot(tok::string_literal))1672 return;1673 nextToken();1674 if (FormatTok->is(tok::semi))1675 nextToken();1676 addUnwrappedLine();1677 return;1678 }1679 if (Style.isVerilog()) {1680 parseVerilogExtern();1681 return;1682 }1683 if (IsCpp && parseModuleImport())1684 return;1685 }1686 if (IsCpp && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,1687 Keywords.kw_slots, Keywords.kw_qslots)) {1688 nextToken();1689 if (FormatTok->is(tok::colon)) {1690 nextToken();1691 addUnwrappedLine();1692 return;1693 }1694 }1695 if (IsCpp && FormatTok->is(TT_StatementMacro)) {1696 parseStatementMacro();1697 return;1698 }1699 if (IsCpp && FormatTok->is(TT_NamespaceMacro)) {1700 parseNamespace();1701 return;1702 }1703 // In Verilog labels can be any expression, so we don't do them here.1704 // JS doesn't have macros, and within classes colons indicate fields, not1705 // labels.1706 // TableGen doesn't have labels.1707 if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&1708 Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) {1709 nextToken();1710 if (!Line->InMacroBody || CurrentLines->size() > 1)1711 Line->Tokens.begin()->Tok->MustBreakBefore = true;1712 FormatTok->setFinalizedType(TT_GotoLabelColon);1713 parseLabel(!Style.IndentGotoLabels);1714 if (HasLabel)1715 *HasLabel = true;1716 return;1717 }1718 if (Style.isJava() && FormatTok->is(Keywords.kw_record)) {1719 parseRecord(/*ParseAsExpr=*/false, /*IsJavaRecord=*/true);1720 addUnwrappedLine();1721 return;1722 }1723 // In all other cases, parse the declaration.1724 break;1725 default:1726 break;1727 }1728 1729 bool SeenEqual = false;1730 for (const bool InRequiresExpression =1731 OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,1732 TT_CompoundRequirementLBrace);1733 !eof();) {1734 const FormatToken *Previous = FormatTok->Previous;1735 switch (FormatTok->Tok.getKind()) {1736 case tok::at:1737 nextToken();1738 if (FormatTok->is(tok::l_brace)) {1739 nextToken();1740 parseBracedList();1741 break;1742 }1743 if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) {1744 nextToken();1745 break;1746 }1747 switch (bool IsAutoRelease = false; FormatTok->Tok.getObjCKeywordID()) {1748 case tok::objc_public:1749 case tok::objc_protected:1750 case tok::objc_package:1751 case tok::objc_private:1752 return parseAccessSpecifier();1753 case tok::objc_interface:1754 case tok::objc_implementation:1755 return parseObjCInterfaceOrImplementation();1756 case tok::objc_protocol:1757 if (parseObjCProtocol())1758 return;1759 break;1760 case tok::objc_end:1761 return; // Handled by the caller.1762 case tok::objc_optional:1763 case tok::objc_required:1764 nextToken();1765 addUnwrappedLine();1766 return;1767 case tok::objc_autoreleasepool:1768 IsAutoRelease = true;1769 [[fallthrough]];1770 case tok::objc_synchronized:1771 nextToken();1772 if (!IsAutoRelease && FormatTok->is(tok::l_paren)) {1773 // Skip synchronization object1774 parseParens();1775 }1776 if (FormatTok->is(tok::l_brace)) {1777 if (Style.BraceWrapping.AfterControlStatement ==1778 FormatStyle::BWACS_Always) {1779 addUnwrappedLine();1780 }1781 parseBlock();1782 }1783 addUnwrappedLine();1784 return;1785 case tok::objc_try:1786 // This branch isn't strictly necessary (the kw_try case below would1787 // do this too after the tok::at is parsed above). But be explicit.1788 parseTryCatch();1789 return;1790 default:1791 break;1792 }1793 break;1794 case tok::kw_requires: {1795 if (IsCpp) {1796 bool ParsedClause = parseRequires(SeenEqual);1797 if (ParsedClause)1798 return;1799 } else {1800 nextToken();1801 }1802 break;1803 }1804 case tok::kw_enum:1805 // Ignore if this is part of "template <enum ..." or "... -> enum" or1806 // "template <..., enum ...>".1807 if (Previous && Previous->isOneOf(tok::less, tok::arrow, tok::comma)) {1808 nextToken();1809 break;1810 }1811 1812 // parseEnum falls through and does not yet add an unwrapped line as an1813 // enum definition can start a structural element.1814 if (!parseEnum())1815 break;1816 // This only applies to C++ and Verilog.1817 if (!IsCpp && !Style.isVerilog()) {1818 addUnwrappedLine();1819 return;1820 }1821 break;1822 case tok::kw_typedef:1823 nextToken();1824 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,1825 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,1826 Keywords.kw_CF_CLOSED_ENUM,1827 Keywords.kw_NS_CLOSED_ENUM)) {1828 parseEnum();1829 }1830 break;1831 case tok::kw_class:1832 if (Style.isVerilog()) {1833 parseBlock();1834 addUnwrappedLine();1835 return;1836 }1837 if (Style.isTableGen()) {1838 // Do nothing special. In this case the l_brace becomes FunctionLBrace.1839 // This is same as def and so on.1840 nextToken();1841 break;1842 }1843 [[fallthrough]];1844 case tok::kw_struct:1845 case tok::kw_union:1846 if (parseStructLike())1847 return;1848 break;1849 case tok::kw_decltype:1850 nextToken();1851 if (FormatTok->is(tok::l_paren)) {1852 parseParens();1853 if (FormatTok->Previous &&1854 FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,1855 tok::l_paren)) {1856 Line->SeenDecltypeAuto = true;1857 }1858 }1859 break;1860 case tok::period:1861 nextToken();1862 // In Java, classes have an implicit static member "class".1863 if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class))1864 nextToken();1865 if (Style.isJavaScript() && FormatTok &&1866 FormatTok->Tok.getIdentifierInfo()) {1867 // JavaScript only has pseudo keywords, all keywords are allowed to1868 // appear in "IdentifierName" positions. See http://es5.github.io/#x7.61869 nextToken();1870 }1871 break;1872 case tok::semi:1873 nextToken();1874 addUnwrappedLine();1875 return;1876 case tok::r_brace:1877 addUnwrappedLine();1878 return;1879 case tok::l_paren: {1880 parseParens();1881 // Break the unwrapped line if a K&R C function definition has a parameter1882 // declaration.1883 if (OpeningBrace || !IsCpp || !Previous || eof())1884 break;1885 if (isC78ParameterDecl(FormatTok,1886 Tokens->peekNextToken(/*SkipComment=*/true),1887 Previous)) {1888 addUnwrappedLine();1889 return;1890 }1891 break;1892 }1893 case tok::kw_operator:1894 nextToken();1895 if (FormatTok->isBinaryOperator())1896 nextToken();1897 break;1898 case tok::caret: {1899 const auto *Prev = FormatTok->getPreviousNonComment();1900 nextToken();1901 if (Prev && Prev->is(tok::identifier))1902 break;1903 // Block return type.1904 if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {1905 nextToken();1906 // Return types: pointers are ok too.1907 while (FormatTok->is(tok::star))1908 nextToken();1909 }1910 // Block argument list.1911 if (FormatTok->is(tok::l_paren))1912 parseParens();1913 // Block body.1914 if (FormatTok->is(tok::l_brace))1915 parseChildBlock();1916 break;1917 }1918 case tok::l_brace:1919 if (InRequiresExpression)1920 FormatTok->setFinalizedType(TT_BracedListLBrace);1921 if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {1922 IsDecltypeAutoFunction = Line->SeenDecltypeAuto;1923 // A block outside of parentheses must be the last part of a1924 // structural element.1925 // FIXME: Figure out cases where this is not true, and add projections1926 // for them (the one we know is missing are lambdas).1927 if (Style.isJava() &&1928 Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {1929 // If necessary, we could set the type to something different than1930 // TT_FunctionLBrace.1931 if (Style.BraceWrapping.AfterControlStatement ==1932 FormatStyle::BWACS_Always) {1933 addUnwrappedLine();1934 }1935 } else if (Style.BraceWrapping.AfterFunction) {1936 addUnwrappedLine();1937 }1938 if (!Previous || Previous->isNot(TT_TypeDeclarationParen))1939 FormatTok->setFinalizedType(TT_FunctionLBrace);1940 parseBlock();1941 IsDecltypeAutoFunction = false;1942 addUnwrappedLine();1943 return;1944 }1945 // Otherwise this was a braced init list, and the structural1946 // element continues.1947 break;1948 case tok::kw_try:1949 if (Style.isJavaScript() && Line->MustBeDeclaration) {1950 // field/method declaration.1951 nextToken();1952 break;1953 }1954 // We arrive here when parsing function-try blocks.1955 if (Style.BraceWrapping.AfterFunction)1956 addUnwrappedLine();1957 parseTryCatch();1958 return;1959 case tok::identifier: {1960 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&1961 Line->MustBeDeclaration) {1962 addUnwrappedLine();1963 parseCSharpGenericTypeConstraint();1964 break;1965 }1966 if (FormatTok->is(TT_MacroBlockEnd)) {1967 addUnwrappedLine();1968 return;1969 }1970 1971 // Function declarations (as opposed to function expressions) are parsed1972 // on their own unwrapped line by continuing this loop. Function1973 // expressions (functions that are not on their own line) must not create1974 // a new unwrapped line, so they are special cased below.1975 size_t TokenCount = Line->Tokens.size();1976 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&1977 (TokenCount > 1 ||1978 (TokenCount == 1 &&1979 Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {1980 tryToParseJSFunction();1981 break;1982 }1983 if ((Style.isJavaScript() || Style.isJava()) &&1984 FormatTok->is(Keywords.kw_interface)) {1985 if (Style.isJavaScript()) {1986 // In JavaScript/TypeScript, "interface" can be used as a standalone1987 // identifier, e.g. in `var interface = 1;`. If "interface" is1988 // followed by another identifier, it is very like to be an actual1989 // interface declaration.1990 unsigned StoredPosition = Tokens->getPosition();1991 FormatToken *Next = Tokens->getNextToken();1992 FormatTok = Tokens->setPosition(StoredPosition);1993 if (!mustBeJSIdent(Keywords, Next)) {1994 nextToken();1995 break;1996 }1997 }1998 parseRecord();1999 addUnwrappedLine();2000 return;2001 }2002 2003 if (Style.isVerilog()) {2004 if (FormatTok->is(Keywords.kw_table)) {2005 parseVerilogTable();2006 return;2007 }2008 if (Keywords.isVerilogBegin(*FormatTok) ||2009 Keywords.isVerilogHierarchy(*FormatTok)) {2010 parseBlock();2011 addUnwrappedLine();2012 return;2013 }2014 }2015 2016 if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {2017 if (parseStructLike())2018 return;2019 break;2020 }2021 2022 if (IsCpp && FormatTok->is(TT_StatementMacro)) {2023 parseStatementMacro();2024 return;2025 }2026 2027 // See if the following token should start a new unwrapped line.2028 StringRef Text = FormatTok->TokenText;2029 2030 FormatToken *PreviousToken = FormatTok;2031 nextToken();2032 2033 // JS doesn't have macros, and within classes colons indicate fields, not2034 // labels.2035 if (Style.isJavaScript())2036 break;2037 2038 auto OneTokenSoFar = [&]() {2039 auto I = Line->Tokens.begin(), E = Line->Tokens.end();2040 while (I != E && I->Tok->is(tok::comment))2041 ++I;2042 if (Style.isVerilog())2043 while (I != E && I->Tok->is(tok::hash))2044 ++I;2045 return I != E && (++I == E);2046 };2047 if (OneTokenSoFar()) {2048 // Recognize function-like macro usages without trailing semicolon as2049 // well as free-standing macros like Q_OBJECT.2050 bool FunctionLike = FormatTok->is(tok::l_paren);2051 if (FunctionLike)2052 parseParens();2053 2054 bool FollowedByNewline =2055 CommentsBeforeNextToken.empty()2056 ? FormatTok->NewlinesBefore > 02057 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;2058 2059 if (FollowedByNewline &&2060 (Text.size() >= 5 ||2061 (FunctionLike && FormatTok->isNot(tok::l_paren))) &&2062 tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) {2063 if (PreviousToken->isNot(TT_UntouchableMacroFunc))2064 PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);2065 addUnwrappedLine();2066 return;2067 }2068 }2069 break;2070 }2071 case tok::equal:2072 if ((Style.isJavaScript() || Style.isCSharp()) &&2073 FormatTok->is(TT_FatArrow)) {2074 tryToParseChildBlock();2075 break;2076 }2077 2078 SeenEqual = true;2079 nextToken();2080 if (FormatTok->is(tok::l_brace)) {2081 // Block kind should probably be set to BK_BracedInit for any language.2082 // C# needs this change to ensure that array initialisers and object2083 // initialisers are indented the same way.2084 if (Style.isCSharp())2085 FormatTok->setBlockKind(BK_BracedInit);2086 // TableGen's defset statement has syntax of the form,2087 // `defset <type> <name> = { <statement>... }`2088 if (Style.isTableGen() &&2089 Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {2090 FormatTok->setFinalizedType(TT_FunctionLBrace);2091 parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,2092 /*MunchSemi=*/false);2093 addUnwrappedLine();2094 break;2095 }2096 nextToken();2097 parseBracedList();2098 } else if (Style.Language == FormatStyle::LK_Proto &&2099 FormatTok->is(tok::less)) {2100 nextToken();2101 parseBracedList(/*IsAngleBracket=*/true);2102 }2103 break;2104 case tok::l_square:2105 parseSquare();2106 break;2107 case tok::kw_new:2108 if (Style.isCSharp() &&2109 (Tokens->peekNextToken()->isAccessSpecifierKeyword() ||2110 (Previous && Previous->isAccessSpecifierKeyword()))) {2111 nextToken();2112 } else {2113 parseNew();2114 }2115 break;2116 case tok::kw_switch:2117 if (Style.isJava())2118 parseSwitch(/*IsExpr=*/true);2119 else2120 nextToken();2121 break;2122 case tok::kw_case:2123 // Proto: there are no switch/case statements.2124 if (Style.Language == FormatStyle::LK_Proto) {2125 nextToken();2126 return;2127 }2128 // In Verilog switch is called case.2129 if (Style.isVerilog()) {2130 parseBlock();2131 addUnwrappedLine();2132 return;2133 }2134 if (Style.isJavaScript() && Line->MustBeDeclaration) {2135 // 'case: string' field declaration.2136 nextToken();2137 break;2138 }2139 parseCaseLabel();2140 break;2141 case tok::kw_default:2142 nextToken();2143 if (Style.isVerilog()) {2144 if (FormatTok->is(tok::colon)) {2145 // The label will be handled in the next iteration.2146 break;2147 }2148 if (FormatTok->is(Keywords.kw_clocking)) {2149 // A default clocking block.2150 parseBlock();2151 addUnwrappedLine();2152 return;2153 }2154 parseVerilogCaseLabel();2155 return;2156 }2157 break;2158 case tok::colon:2159 nextToken();2160 if (Style.isVerilog()) {2161 parseVerilogCaseLabel();2162 return;2163 }2164 break;2165 case tok::greater:2166 nextToken();2167 if (FormatTok->is(tok::l_brace))2168 FormatTok->Previous->setFinalizedType(TT_TemplateCloser);2169 break;2170 default:2171 nextToken();2172 break;2173 }2174 }2175}2176 2177bool UnwrappedLineParser::tryToParsePropertyAccessor() {2178 assert(FormatTok->is(tok::l_brace));2179 if (!Style.isCSharp())2180 return false;2181 // See if it's a property accessor.2182 if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))2183 return false;2184 2185 // See if we are inside a property accessor.2186 //2187 // Record the current tokenPosition so that we can advance and2188 // reset the current token. `Next` is not set yet so we need2189 // another way to advance along the token stream.2190 unsigned int StoredPosition = Tokens->getPosition();2191 FormatToken *Tok = Tokens->getNextToken();2192 2193 // A trivial property accessor is of the form:2194 // { [ACCESS_SPECIFIER] [get]; [ACCESS_SPECIFIER] [set|init] }2195 // Track these as they do not require line breaks to be introduced.2196 bool HasSpecialAccessor = false;2197 bool IsTrivialPropertyAccessor = true;2198 bool HasAttribute = false;2199 while (!eof()) {2200 if (const bool IsAccessorKeyword =2201 Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set);2202 IsAccessorKeyword || Tok->isAccessSpecifierKeyword() ||2203 Tok->isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {2204 if (IsAccessorKeyword)2205 HasSpecialAccessor = true;2206 else if (Tok->is(tok::l_square))2207 HasAttribute = true;2208 Tok = Tokens->getNextToken();2209 continue;2210 }2211 if (Tok->isNot(tok::r_brace))2212 IsTrivialPropertyAccessor = false;2213 break;2214 }2215 2216 if (!HasSpecialAccessor || HasAttribute) {2217 Tokens->setPosition(StoredPosition);2218 return false;2219 }2220 2221 // Try to parse the property accessor:2222 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties2223 Tokens->setPosition(StoredPosition);2224 if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)2225 addUnwrappedLine();2226 nextToken();2227 do {2228 switch (FormatTok->Tok.getKind()) {2229 case tok::r_brace:2230 nextToken();2231 if (FormatTok->is(tok::equal)) {2232 while (!eof() && FormatTok->isNot(tok::semi))2233 nextToken();2234 nextToken();2235 }2236 addUnwrappedLine();2237 return true;2238 case tok::l_brace:2239 ++Line->Level;2240 parseBlock(/*MustBeDeclaration=*/true);2241 addUnwrappedLine();2242 --Line->Level;2243 break;2244 case tok::equal:2245 if (FormatTok->is(TT_FatArrow)) {2246 ++Line->Level;2247 do {2248 nextToken();2249 } while (!eof() && FormatTok->isNot(tok::semi));2250 nextToken();2251 addUnwrappedLine();2252 --Line->Level;2253 break;2254 }2255 nextToken();2256 break;2257 default:2258 if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,2259 Keywords.kw_set) &&2260 !IsTrivialPropertyAccessor) {2261 // Non-trivial get/set needs to be on its own line.2262 addUnwrappedLine();2263 }2264 nextToken();2265 }2266 } while (!eof());2267 2268 // Unreachable for well-formed code (paired '{' and '}').2269 return true;2270}2271 2272bool UnwrappedLineParser::tryToParseLambda() {2273 assert(FormatTok->is(tok::l_square));2274 if (!IsCpp) {2275 nextToken();2276 return false;2277 }2278 FormatToken &LSquare = *FormatTok;2279 if (!tryToParseLambdaIntroducer())2280 return false;2281 2282 FormatToken *Arrow = nullptr;2283 bool InTemplateParameterList = false;2284 2285 while (FormatTok->isNot(tok::l_brace)) {2286 if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {2287 nextToken();2288 continue;2289 }2290 switch (FormatTok->Tok.getKind()) {2291 case tok::l_brace:2292 break;2293 case tok::l_paren:2294 parseParens(/*AmpAmpTokenType=*/TT_PointerOrReference);2295 break;2296 case tok::l_square:2297 parseSquare();2298 break;2299 case tok::less:2300 assert(FormatTok->Previous);2301 if (FormatTok->Previous->is(tok::r_square))2302 InTemplateParameterList = true;2303 nextToken();2304 break;2305 case tok::kw_auto:2306 case tok::kw_class:2307 case tok::kw_struct:2308 case tok::kw_union:2309 case tok::kw_template:2310 case tok::kw_typename:2311 case tok::amp:2312 case tok::star:2313 case tok::kw_const:2314 case tok::kw_constexpr:2315 case tok::kw_consteval:2316 case tok::comma:2317 case tok::greater:2318 case tok::identifier:2319 case tok::numeric_constant:2320 case tok::coloncolon:2321 case tok::kw_mutable:2322 case tok::kw_noexcept:2323 case tok::kw_static:2324 nextToken();2325 break;2326 // Specialization of a template with an integer parameter can contain2327 // arithmetic, logical, comparison and ternary operators.2328 //2329 // FIXME: This also accepts sequences of operators that are not in the scope2330 // of a template argument list.2331 //2332 // In a C++ lambda a template type can only occur after an arrow. We use2333 // this as an heuristic to distinguish between Objective-C expressions2334 // followed by an `a->b` expression, such as:2335 // ([obj func:arg] + a->b)2336 // Otherwise the code below would parse as a lambda.2337 case tok::plus:2338 case tok::minus:2339 case tok::exclaim:2340 case tok::tilde:2341 case tok::slash:2342 case tok::percent:2343 case tok::lessless:2344 case tok::pipe:2345 case tok::pipepipe:2346 case tok::ampamp:2347 case tok::caret:2348 case tok::equalequal:2349 case tok::exclaimequal:2350 case tok::greaterequal:2351 case tok::lessequal:2352 case tok::question:2353 case tok::colon:2354 case tok::ellipsis:2355 case tok::kw_true:2356 case tok::kw_false:2357 if (Arrow || InTemplateParameterList) {2358 nextToken();2359 break;2360 }2361 return true;2362 case tok::arrow:2363 Arrow = FormatTok;2364 nextToken();2365 break;2366 case tok::kw_requires:2367 parseRequiresClause();2368 break;2369 case tok::equal:2370 if (!InTemplateParameterList)2371 return true;2372 nextToken();2373 break;2374 default:2375 return true;2376 }2377 }2378 2379 FormatTok->setFinalizedType(TT_LambdaLBrace);2380 LSquare.setFinalizedType(TT_LambdaLSquare);2381 2382 if (Arrow)2383 Arrow->setFinalizedType(TT_LambdaArrow);2384 2385 NestedLambdas.push_back(Line->SeenDecltypeAuto);2386 parseChildBlock();2387 assert(!NestedLambdas.empty());2388 NestedLambdas.pop_back();2389 2390 return true;2391}2392 2393bool UnwrappedLineParser::tryToParseLambdaIntroducer() {2394 const FormatToken *Previous = FormatTok->Previous;2395 const FormatToken *LeftSquare = FormatTok;2396 nextToken();2397 if (Previous) {2398 if (Previous->closesScope()) {2399 // Not a potential C-style cast.2400 if (Previous->isNot(tok::r_paren))2401 return false;2402 const auto *BeforeRParen = Previous->getPreviousNonComment();2403 // Lambdas can be cast to function types only, e.g. `std::function<int()>`2404 // and `int (*)()`.2405 if (!BeforeRParen || BeforeRParen->isNoneOf(tok::greater, tok::r_paren))2406 return false;2407 } else if (Previous->is(tok::star)) {2408 Previous = Previous->getPreviousNonComment();2409 }2410 if (Previous && Previous->Tok.getIdentifierInfo() &&2411 Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,2412 tok::kw_co_return)) {2413 return false;2414 }2415 }2416 if (LeftSquare->isCppStructuredBinding(IsCpp))2417 return false;2418 if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))2419 return false;2420 if (FormatTok->is(tok::r_square)) {2421 const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true);2422 if (Next->is(tok::greater))2423 return false;2424 }2425 parseSquare(/*LambdaIntroducer=*/true);2426 return true;2427}2428 2429void UnwrappedLineParser::tryToParseJSFunction() {2430 assert(FormatTok->is(Keywords.kw_function));2431 if (FormatTok->is(Keywords.kw_async))2432 nextToken();2433 // Consume "function".2434 nextToken();2435 2436 // Consume * (generator function). Treat it like C++'s overloaded operators.2437 if (FormatTok->is(tok::star)) {2438 FormatTok->setFinalizedType(TT_OverloadedOperator);2439 nextToken();2440 }2441 2442 // Consume function name.2443 if (FormatTok->is(tok::identifier))2444 nextToken();2445 2446 if (FormatTok->isNot(tok::l_paren))2447 return;2448 2449 // Parse formal parameter list.2450 parseParens();2451 2452 if (FormatTok->is(tok::colon)) {2453 // Parse a type definition.2454 nextToken();2455 2456 // Eat the type declaration. For braced inline object types, balance braces,2457 // otherwise just parse until finding an l_brace for the function body.2458 if (FormatTok->is(tok::l_brace))2459 tryToParseBracedList();2460 else2461 while (FormatTok->isNoneOf(tok::l_brace, tok::semi) && !eof())2462 nextToken();2463 }2464 2465 if (FormatTok->is(tok::semi))2466 return;2467 2468 parseChildBlock();2469}2470 2471bool UnwrappedLineParser::tryToParseBracedList() {2472 if (FormatTok->is(BK_Unknown))2473 calculateBraceTypes();2474 assert(FormatTok->isNot(BK_Unknown));2475 if (FormatTok->is(BK_Block))2476 return false;2477 nextToken();2478 parseBracedList();2479 return true;2480}2481 2482bool UnwrappedLineParser::tryToParseChildBlock() {2483 assert(Style.isJavaScript() || Style.isCSharp());2484 assert(FormatTok->is(TT_FatArrow));2485 // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType TT_FatArrow.2486 // They always start an expression or a child block if followed by a curly2487 // brace.2488 nextToken();2489 if (FormatTok->isNot(tok::l_brace))2490 return false;2491 parseChildBlock();2492 return true;2493}2494 2495bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {2496 assert(!IsAngleBracket || !IsEnum);2497 bool HasError = false;2498 2499 // FIXME: Once we have an expression parser in the UnwrappedLineParser,2500 // replace this by using parseAssignmentExpression() inside.2501 do {2502 if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&2503 tryToParseChildBlock()) {2504 continue;2505 }2506 if (Style.isJavaScript()) {2507 if (FormatTok->is(Keywords.kw_function)) {2508 tryToParseJSFunction();2509 continue;2510 }2511 if (FormatTok->is(tok::l_brace)) {2512 // Could be a method inside of a braced list `{a() { return 1; }}`.2513 if (tryToParseBracedList())2514 continue;2515 parseChildBlock();2516 }2517 }2518 if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {2519 if (IsEnum) {2520 FormatTok->setBlockKind(BK_Block);2521 if (!Style.AllowShortEnumsOnASingleLine)2522 addUnwrappedLine();2523 }2524 nextToken();2525 return !HasError;2526 }2527 switch (FormatTok->Tok.getKind()) {2528 case tok::l_square:2529 if (Style.isCSharp())2530 parseSquare();2531 else2532 tryToParseLambda();2533 break;2534 case tok::l_paren:2535 parseParens();2536 // JavaScript can just have free standing methods and getters/setters in2537 // object literals. Detect them by a "{" following ")".2538 if (Style.isJavaScript()) {2539 if (FormatTok->is(tok::l_brace))2540 parseChildBlock();2541 break;2542 }2543 break;2544 case tok::l_brace:2545 // Assume there are no blocks inside a braced init list apart2546 // from the ones we explicitly parse out (like lambdas).2547 FormatTok->setBlockKind(BK_BracedInit);2548 if (!IsAngleBracket) {2549 auto *Prev = FormatTok->Previous;2550 if (Prev && Prev->is(tok::greater))2551 Prev->setFinalizedType(TT_TemplateCloser);2552 }2553 nextToken();2554 parseBracedList();2555 break;2556 case tok::less:2557 nextToken();2558 if (IsAngleBracket)2559 parseBracedList(/*IsAngleBracket=*/true);2560 break;2561 case tok::semi:2562 // JavaScript (or more precisely TypeScript) can have semicolons in braced2563 // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be2564 // used for error recovery if we have otherwise determined that this is2565 // a braced list.2566 if (Style.isJavaScript()) {2567 nextToken();2568 break;2569 }2570 HasError = true;2571 if (!IsEnum)2572 return false;2573 nextToken();2574 break;2575 case tok::comma:2576 nextToken();2577 if (IsEnum && !Style.AllowShortEnumsOnASingleLine)2578 addUnwrappedLine();2579 break;2580 case tok::kw_requires:2581 parseRequiresExpression();2582 break;2583 default:2584 nextToken();2585 break;2586 }2587 } while (!eof());2588 return false;2589}2590 2591/// Parses a pair of parentheses (and everything between them).2592/// \param AmpAmpTokenType If different than TT_Unknown sets this type for all2593/// double ampersands. This applies for all nested scopes as well.2594///2595/// Returns whether there is a `=` token between the parentheses.2596bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType,2597 bool InMacroCall) {2598 assert(FormatTok->is(tok::l_paren) && "'(' expected.");2599 auto *LParen = FormatTok;2600 auto *Prev = FormatTok->Previous;2601 bool SeenComma = false;2602 bool SeenEqual = false;2603 bool MightBeFoldExpr = false;2604 nextToken();2605 const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);2606 if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))2607 InMacroCall = true;2608 do {2609 switch (FormatTok->Tok.getKind()) {2610 case tok::l_paren:2611 if (parseParens(AmpAmpTokenType, InMacroCall))2612 SeenEqual = true;2613 if (Style.isJava() && FormatTok->is(tok::l_brace))2614 parseChildBlock();2615 break;2616 case tok::r_paren: {2617 auto *RParen = FormatTok;2618 nextToken();2619 if (Prev) {2620 auto OptionalParens = [&] {2621 if (MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||2622 Line->InMacroBody ||2623 Style.RemoveParentheses == FormatStyle::RPS_Leave ||2624 RParen->getPreviousNonComment() == LParen) {2625 return false;2626 }2627 const bool DoubleParens =2628 Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);2629 if (DoubleParens) {2630 const auto *PrevPrev = Prev->getPreviousNonComment();2631 const bool Excluded =2632 PrevPrev &&2633 (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||2634 (SeenEqual &&2635 (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||2636 PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));2637 if (!Excluded)2638 return true;2639 } else {2640 const bool CommaSeparated =2641 Prev->isOneOf(tok::l_paren, tok::comma) &&2642 FormatTok->isOneOf(tok::comma, tok::r_paren);2643 if (CommaSeparated &&2644 // LParen is not preceded by ellipsis, comma.2645 !Prev->endsSequence(tok::comma, tok::ellipsis) &&2646 // RParen is not followed by comma, ellipsis.2647 !(FormatTok->is(tok::comma) &&2648 Tokens->peekNextToken()->is(tok::ellipsis))) {2649 return true;2650 }2651 const bool ReturnParens =2652 Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&2653 ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||2654 (!NestedLambdas.empty() && !NestedLambdas.back())) &&2655 Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&2656 FormatTok->is(tok::semi);2657 if (ReturnParens)2658 return true;2659 }2660 return false;2661 };2662 if (Prev->is(TT_TypenameMacro)) {2663 LParen->setFinalizedType(TT_TypeDeclarationParen);2664 RParen->setFinalizedType(TT_TypeDeclarationParen);2665 } else if (Prev->is(tok::greater) && RParen->Previous == LParen) {2666 Prev->setFinalizedType(TT_TemplateCloser);2667 } else if (OptionalParens()) {2668 LParen->Optional = true;2669 RParen->Optional = true;2670 }2671 }2672 return SeenEqual;2673 }2674 case tok::r_brace:2675 // A "}" inside parenthesis is an error if there wasn't a matching "{".2676 return SeenEqual;2677 case tok::l_square:2678 tryToParseLambda();2679 break;2680 case tok::l_brace:2681 if (!tryToParseBracedList())2682 parseChildBlock();2683 break;2684 case tok::at:2685 nextToken();2686 if (FormatTok->is(tok::l_brace)) {2687 nextToken();2688 parseBracedList();2689 }2690 break;2691 case tok::comma:2692 SeenComma = true;2693 nextToken();2694 break;2695 case tok::ellipsis:2696 MightBeFoldExpr = true;2697 nextToken();2698 break;2699 case tok::equal:2700 SeenEqual = true;2701 if (Style.isCSharp() && FormatTok->is(TT_FatArrow))2702 tryToParseChildBlock();2703 else2704 nextToken();2705 break;2706 case tok::kw_class:2707 if (Style.isJavaScript())2708 parseRecord(/*ParseAsExpr=*/true);2709 else2710 nextToken();2711 break;2712 case tok::identifier:2713 if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))2714 tryToParseJSFunction();2715 else2716 nextToken();2717 break;2718 case tok::kw_switch:2719 if (Style.isJava())2720 parseSwitch(/*IsExpr=*/true);2721 else2722 nextToken();2723 break;2724 case tok::kw_requires:2725 parseRequiresExpression();2726 break;2727 case tok::ampamp:2728 if (AmpAmpTokenType != TT_Unknown)2729 FormatTok->setFinalizedType(AmpAmpTokenType);2730 [[fallthrough]];2731 default:2732 nextToken();2733 break;2734 }2735 } while (!eof());2736 return SeenEqual;2737}2738 2739void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {2740 if (!LambdaIntroducer) {2741 assert(FormatTok->is(tok::l_square) && "'[' expected.");2742 if (tryToParseLambda())2743 return;2744 }2745 do {2746 switch (FormatTok->Tok.getKind()) {2747 case tok::l_paren:2748 parseParens();2749 break;2750 case tok::r_square:2751 nextToken();2752 return;2753 case tok::r_brace:2754 // A "}" inside parenthesis is an error if there wasn't a matching "{".2755 return;2756 case tok::l_square:2757 parseSquare();2758 break;2759 case tok::l_brace: {2760 if (!tryToParseBracedList())2761 parseChildBlock();2762 break;2763 }2764 case tok::at:2765 case tok::colon:2766 nextToken();2767 if (FormatTok->is(tok::l_brace)) {2768 nextToken();2769 parseBracedList();2770 }2771 break;2772 default:2773 nextToken();2774 break;2775 }2776 } while (!eof());2777}2778 2779void UnwrappedLineParser::keepAncestorBraces() {2780 if (!Style.RemoveBracesLLVM)2781 return;2782 2783 const int MaxNestingLevels = 2;2784 const int Size = NestedTooDeep.size();2785 if (Size >= MaxNestingLevels)2786 NestedTooDeep[Size - MaxNestingLevels] = true;2787 NestedTooDeep.push_back(false);2788}2789 2790static FormatToken *getLastNonComment(const UnwrappedLine &Line) {2791 for (const auto &Token : llvm::reverse(Line.Tokens))2792 if (Token.Tok->isNot(tok::comment))2793 return Token.Tok;2794 2795 return nullptr;2796}2797 2798void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {2799 FormatToken *Tok = nullptr;2800 2801 if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() &&2802 PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {2803 Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never2804 ? getLastNonComment(*Line)2805 : Line->Tokens.back().Tok;2806 assert(Tok);2807 if (Tok->BraceCount < 0) {2808 assert(Tok->BraceCount == -1);2809 Tok = nullptr;2810 } else {2811 Tok->BraceCount = -1;2812 }2813 }2814 2815 addUnwrappedLine();2816 ++Line->Level;2817 ++Line->UnbracedBodyLevel;2818 parseStructuralElement();2819 --Line->UnbracedBodyLevel;2820 2821 if (Tok) {2822 assert(!Line->InPPDirective);2823 Tok = nullptr;2824 for (const auto &L : llvm::reverse(*CurrentLines)) {2825 if (!L.InPPDirective && getLastNonComment(L)) {2826 Tok = L.Tokens.back().Tok;2827 break;2828 }2829 }2830 assert(Tok);2831 ++Tok->BraceCount;2832 }2833 2834 if (CheckEOF && eof())2835 addUnwrappedLine();2836 2837 --Line->Level;2838}2839 2840static void markOptionalBraces(FormatToken *LeftBrace) {2841 if (!LeftBrace)2842 return;2843 2844 assert(LeftBrace->is(tok::l_brace));2845 2846 FormatToken *RightBrace = LeftBrace->MatchingParen;2847 if (!RightBrace) {2848 assert(!LeftBrace->Optional);2849 return;2850 }2851 2852 assert(RightBrace->is(tok::r_brace));2853 assert(RightBrace->MatchingParen == LeftBrace);2854 assert(LeftBrace->Optional == RightBrace->Optional);2855 2856 LeftBrace->Optional = true;2857 RightBrace->Optional = true;2858}2859 2860void UnwrappedLineParser::handleAttributes() {2861 // Handle AttributeMacro, e.g. `if (x) UNLIKELY`.2862 if (FormatTok->isAttribute())2863 nextToken();2864 else if (FormatTok->is(tok::l_square))2865 handleCppAttributes();2866}2867 2868bool UnwrappedLineParser::handleCppAttributes() {2869 // Handle [[likely]] / [[unlikely]] attributes.2870 assert(FormatTok->is(tok::l_square));2871 if (!tryToParseSimpleAttribute())2872 return false;2873 parseSquare();2874 return true;2875}2876 2877/// Returns whether \c Tok begins a block.2878bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const {2879 // FIXME: rename the function or make2880 // Tok.isOneOf(tok::l_brace, TT_MacroBlockBegin) work.2881 return Style.isVerilog() ? Keywords.isVerilogBegin(Tok)2882 : Tok.is(tok::l_brace);2883}2884 2885FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,2886 bool KeepBraces,2887 bool IsVerilogAssert) {2888 assert((FormatTok->is(tok::kw_if) ||2889 (Style.isVerilog() &&2890 FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,2891 Keywords.kw_assume, Keywords.kw_cover))) &&2892 "'if' expected");2893 nextToken();2894 2895 if (IsVerilogAssert) {2896 // Handle `assert #0` and `assert final`.2897 if (FormatTok->is(Keywords.kw_verilogHash)) {2898 nextToken();2899 if (FormatTok->is(tok::numeric_constant))2900 nextToken();2901 } else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,2902 Keywords.kw_sequence)) {2903 nextToken();2904 }2905 }2906 2907 // TableGen's if statement has the form of `if <cond> then { ... }`.2908 if (Style.isTableGen()) {2909 while (!eof() && FormatTok->isNot(Keywords.kw_then)) {2910 // Simply skip until then. This range only contains a value.2911 nextToken();2912 }2913 }2914 2915 // Handle `if !consteval`.2916 if (FormatTok->is(tok::exclaim))2917 nextToken();2918 2919 bool KeepIfBraces = true;2920 if (FormatTok->is(tok::kw_consteval)) {2921 nextToken();2922 } else {2923 KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;2924 if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))2925 nextToken();2926 if (FormatTok->is(tok::l_paren)) {2927 FormatTok->setFinalizedType(TT_ConditionLParen);2928 parseParens();2929 }2930 }2931 handleAttributes();2932 // The then action is optional in Verilog assert statements.2933 if (IsVerilogAssert && FormatTok->is(tok::semi)) {2934 nextToken();2935 addUnwrappedLine();2936 return nullptr;2937 }2938 2939 bool NeedsUnwrappedLine = false;2940 keepAncestorBraces();2941 2942 FormatToken *IfLeftBrace = nullptr;2943 IfStmtKind IfBlockKind = IfStmtKind::NotIf;2944 2945 if (isBlockBegin(*FormatTok)) {2946 FormatTok->setFinalizedType(TT_ControlStatementLBrace);2947 IfLeftBrace = FormatTok;2948 CompoundStatementIndenter Indenter(this, Style, Line->Level);2949 parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,2950 /*MunchSemi=*/true, KeepIfBraces, &IfBlockKind);2951 setPreviousRBraceType(TT_ControlStatementRBrace);2952 if (Style.BraceWrapping.BeforeElse)2953 addUnwrappedLine();2954 else2955 NeedsUnwrappedLine = true;2956 } else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {2957 addUnwrappedLine();2958 } else {2959 parseUnbracedBody();2960 }2961 2962 if (Style.RemoveBracesLLVM) {2963 assert(!NestedTooDeep.empty());2964 KeepIfBraces = KeepIfBraces ||2965 (IfLeftBrace && !IfLeftBrace->MatchingParen) ||2966 NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||2967 IfBlockKind == IfStmtKind::IfElseIf;2968 }2969 2970 bool KeepElseBraces = KeepIfBraces;2971 FormatToken *ElseLeftBrace = nullptr;2972 IfStmtKind Kind = IfStmtKind::IfOnly;2973 2974 if (FormatTok->is(tok::kw_else)) {2975 if (Style.RemoveBracesLLVM) {2976 NestedTooDeep.back() = false;2977 Kind = IfStmtKind::IfElse;2978 }2979 nextToken();2980 handleAttributes();2981 if (isBlockBegin(*FormatTok)) {2982 const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);2983 FormatTok->setFinalizedType(TT_ElseLBrace);2984 ElseLeftBrace = FormatTok;2985 CompoundStatementIndenter Indenter(this, Style, Line->Level);2986 IfStmtKind ElseBlockKind = IfStmtKind::NotIf;2987 FormatToken *IfLBrace =2988 parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,2989 /*MunchSemi=*/true, KeepElseBraces, &ElseBlockKind);2990 setPreviousRBraceType(TT_ElseRBrace);2991 if (FormatTok->is(tok::kw_else)) {2992 KeepElseBraces = KeepElseBraces ||2993 ElseBlockKind == IfStmtKind::IfOnly ||2994 ElseBlockKind == IfStmtKind::IfElseIf;2995 } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {2996 KeepElseBraces = true;2997 assert(ElseLeftBrace->MatchingParen);2998 markOptionalBraces(ElseLeftBrace);2999 }3000 addUnwrappedLine();3001 } else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {3002 const FormatToken *Previous = Tokens->getPreviousToken();3003 assert(Previous);3004 const bool IsPrecededByComment = Previous->is(tok::comment);3005 if (IsPrecededByComment) {3006 addUnwrappedLine();3007 ++Line->Level;3008 }3009 bool TooDeep = true;3010 if (Style.RemoveBracesLLVM) {3011 Kind = IfStmtKind::IfElseIf;3012 TooDeep = NestedTooDeep.pop_back_val();3013 }3014 ElseLeftBrace = parseIfThenElse(/*IfKind=*/nullptr, KeepIfBraces);3015 if (Style.RemoveBracesLLVM)3016 NestedTooDeep.push_back(TooDeep);3017 if (IsPrecededByComment)3018 --Line->Level;3019 } else {3020 parseUnbracedBody(/*CheckEOF=*/true);3021 }3022 } else {3023 KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;3024 if (NeedsUnwrappedLine)3025 addUnwrappedLine();3026 }3027 3028 if (!Style.RemoveBracesLLVM)3029 return nullptr;3030 3031 assert(!NestedTooDeep.empty());3032 KeepElseBraces = KeepElseBraces ||3033 (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||3034 NestedTooDeep.back();3035 3036 NestedTooDeep.pop_back();3037 3038 if (!KeepIfBraces && !KeepElseBraces) {3039 markOptionalBraces(IfLeftBrace);3040 markOptionalBraces(ElseLeftBrace);3041 } else if (IfLeftBrace) {3042 FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;3043 if (IfRightBrace) {3044 assert(IfRightBrace->MatchingParen == IfLeftBrace);3045 assert(!IfLeftBrace->Optional);3046 assert(!IfRightBrace->Optional);3047 IfLeftBrace->MatchingParen = nullptr;3048 IfRightBrace->MatchingParen = nullptr;3049 }3050 }3051 3052 if (IfKind)3053 *IfKind = Kind;3054 3055 return IfLeftBrace;3056}3057 3058void UnwrappedLineParser::parseTryCatch() {3059 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");3060 nextToken();3061 bool NeedsUnwrappedLine = false;3062 bool HasCtorInitializer = false;3063 if (FormatTok->is(tok::colon)) {3064 auto *Colon = FormatTok;3065 // We are in a function try block, what comes is an initializer list.3066 nextToken();3067 if (FormatTok->is(tok::identifier)) {3068 HasCtorInitializer = true;3069 Colon->setFinalizedType(TT_CtorInitializerColon);3070 }3071 3072 // In case identifiers were removed by clang-tidy, what might follow is3073 // multiple commas in sequence - before the first identifier.3074 while (FormatTok->is(tok::comma))3075 nextToken();3076 3077 while (FormatTok->is(tok::identifier)) {3078 nextToken();3079 if (FormatTok->is(tok::l_paren)) {3080 parseParens();3081 } else if (FormatTok->is(tok::l_brace)) {3082 nextToken();3083 parseBracedList();3084 }3085 3086 // In case identifiers were removed by clang-tidy, what might follow is3087 // multiple commas in sequence - after the first identifier.3088 while (FormatTok->is(tok::comma))3089 nextToken();3090 }3091 }3092 // Parse try with resource.3093 if (Style.isJava() && FormatTok->is(tok::l_paren))3094 parseParens();3095 3096 keepAncestorBraces();3097 3098 if (FormatTok->is(tok::l_brace)) {3099 if (HasCtorInitializer)3100 FormatTok->setFinalizedType(TT_FunctionLBrace);3101 CompoundStatementIndenter Indenter(this, Style, Line->Level);3102 parseBlock();3103 if (Style.BraceWrapping.BeforeCatch)3104 addUnwrappedLine();3105 else3106 NeedsUnwrappedLine = true;3107 } else if (FormatTok->isNot(tok::kw_catch)) {3108 // The C++ standard requires a compound-statement after a try.3109 // If there's none, we try to assume there's a structuralElement3110 // and try to continue.3111 addUnwrappedLine();3112 ++Line->Level;3113 parseStructuralElement();3114 --Line->Level;3115 }3116 for (bool SeenCatch = false;;) {3117 if (FormatTok->is(tok::at))3118 nextToken();3119 if (FormatTok->isNoneOf(tok::kw_catch, Keywords.kw___except,3120 tok::kw___finally, tok::objc_catch,3121 tok::objc_finally) &&3122 !((Style.isJava() || Style.isJavaScript()) &&3123 FormatTok->is(Keywords.kw_finally))) {3124 break;3125 }3126 if (FormatTok->is(tok::kw_catch))3127 SeenCatch = true;3128 nextToken();3129 while (FormatTok->isNot(tok::l_brace)) {3130 if (FormatTok->is(tok::l_paren)) {3131 parseParens();3132 continue;3133 }3134 if (FormatTok->isOneOf(tok::semi, tok::r_brace) || eof()) {3135 if (Style.RemoveBracesLLVM)3136 NestedTooDeep.pop_back();3137 return;3138 }3139 nextToken();3140 }3141 if (SeenCatch) {3142 FormatTok->setFinalizedType(TT_ControlStatementLBrace);3143 SeenCatch = false;3144 }3145 NeedsUnwrappedLine = false;3146 Line->MustBeDeclaration = false;3147 CompoundStatementIndenter Indenter(this, Style, Line->Level);3148 parseBlock();3149 if (Style.BraceWrapping.BeforeCatch)3150 addUnwrappedLine();3151 else3152 NeedsUnwrappedLine = true;3153 }3154 3155 if (Style.RemoveBracesLLVM)3156 NestedTooDeep.pop_back();3157 3158 if (NeedsUnwrappedLine)3159 addUnwrappedLine();3160}3161 3162void UnwrappedLineParser::parseNamespaceOrExportBlock(unsigned AddLevels) {3163 bool ManageWhitesmithsBraces =3164 AddLevels == 0u && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;3165 3166 // If we're in Whitesmiths mode, indent the brace if we're not indenting3167 // the whole block.3168 if (ManageWhitesmithsBraces)3169 ++Line->Level;3170 3171 // Munch the semicolon after the block. This is more common than one would3172 // think. Putting the semicolon into its own line is very ugly.3173 parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true,3174 /*KeepBraces=*/true, /*IfKind=*/nullptr, ManageWhitesmithsBraces);3175 3176 addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);3177 3178 if (ManageWhitesmithsBraces)3179 --Line->Level;3180}3181 3182void UnwrappedLineParser::parseNamespace() {3183 assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&3184 "'namespace' expected");3185 3186 const FormatToken &InitialToken = *FormatTok;3187 nextToken();3188 if (InitialToken.is(TT_NamespaceMacro)) {3189 parseParens();3190 } else {3191 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,3192 tok::l_square, tok::period, tok::l_paren) ||3193 (Style.isCSharp() && FormatTok->is(tok::kw_union))) {3194 if (FormatTok->is(tok::l_square))3195 parseSquare();3196 else if (FormatTok->is(tok::l_paren))3197 parseParens();3198 else3199 nextToken();3200 }3201 }3202 if (FormatTok->is(tok::l_brace)) {3203 FormatTok->setFinalizedType(TT_NamespaceLBrace);3204 3205 if (ShouldBreakBeforeBrace(Style, InitialToken, /*IsJavaRecord=*/false))3206 addUnwrappedLine();3207 3208 unsigned AddLevels =3209 Style.NamespaceIndentation == FormatStyle::NI_All ||3210 (Style.NamespaceIndentation == FormatStyle::NI_Inner &&3211 DeclarationScopeStack.size() > 1)3212 ? 1u3213 : 0u;3214 parseNamespaceOrExportBlock(AddLevels);3215 }3216 // FIXME: Add error handling.3217}3218 3219void UnwrappedLineParser::parseCppExportBlock() {3220 parseNamespaceOrExportBlock(/*AddLevels=*/Style.IndentExportBlock ? 1 : 0);3221}3222 3223void UnwrappedLineParser::parseNew() {3224 assert(FormatTok->is(tok::kw_new) && "'new' expected");3225 nextToken();3226 3227 if (Style.isCSharp()) {3228 do {3229 // Handle constructor invocation, e.g. `new(field: value)`.3230 if (FormatTok->is(tok::l_paren))3231 parseParens();3232 3233 // Handle array initialization syntax, e.g. `new[] {10, 20, 30}`.3234 if (FormatTok->is(tok::l_brace))3235 parseBracedList();3236 3237 if (FormatTok->isOneOf(tok::semi, tok::comma))3238 return;3239 3240 nextToken();3241 } while (!eof());3242 }3243 3244 if (!Style.isJava())3245 return;3246 3247 // In Java, we can parse everything up to the parens, which aren't optional.3248 do {3249 // There should not be a ;, { or } before the new's open paren.3250 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))3251 return;3252 3253 // Consume the parens.3254 if (FormatTok->is(tok::l_paren)) {3255 parseParens();3256 3257 // If there is a class body of an anonymous class, consume that as child.3258 if (FormatTok->is(tok::l_brace))3259 parseChildBlock();3260 return;3261 }3262 nextToken();3263 } while (!eof());3264}3265 3266void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {3267 keepAncestorBraces();3268 3269 if (isBlockBegin(*FormatTok)) {3270 FormatTok->setFinalizedType(TT_ControlStatementLBrace);3271 FormatToken *LeftBrace = FormatTok;3272 CompoundStatementIndenter Indenter(this, Style, Line->Level);3273 parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,3274 /*MunchSemi=*/true, KeepBraces);3275 setPreviousRBraceType(TT_ControlStatementRBrace);3276 if (!KeepBraces) {3277 assert(!NestedTooDeep.empty());3278 if (!NestedTooDeep.back())3279 markOptionalBraces(LeftBrace);3280 }3281 if (WrapRightBrace)3282 addUnwrappedLine();3283 } else {3284 parseUnbracedBody();3285 }3286 3287 if (!KeepBraces)3288 NestedTooDeep.pop_back();3289}3290 3291void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) {3292 assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||3293 (Style.isVerilog() &&3294 FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,3295 Keywords.kw_always_ff, Keywords.kw_always_latch,3296 Keywords.kw_final, Keywords.kw_initial,3297 Keywords.kw_foreach, Keywords.kw_forever,3298 Keywords.kw_repeat))) &&3299 "'for', 'while' or foreach macro expected");3300 const bool KeepBraces = !Style.RemoveBracesLLVM ||3301 FormatTok->isNoneOf(tok::kw_for, tok::kw_while);3302 3303 nextToken();3304 // JS' for await ( ...3305 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))3306 nextToken();3307 if (IsCpp && FormatTok->is(tok::kw_co_await))3308 nextToken();3309 if (HasParens && FormatTok->is(tok::l_paren)) {3310 // The type is only set for Verilog basically because we were afraid to3311 // change the existing behavior for loops. See the discussion on D121756 for3312 // details.3313 if (Style.isVerilog())3314 FormatTok->setFinalizedType(TT_ConditionLParen);3315 parseParens();3316 }3317 3318 if (Style.isVerilog()) {3319 // Event control.3320 parseVerilogSensitivityList();3321 } else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&3322 Tokens->getPreviousToken()->is(tok::r_paren)) {3323 nextToken();3324 addUnwrappedLine();3325 return;3326 }3327 3328 handleAttributes();3329 parseLoopBody(KeepBraces, /*WrapRightBrace=*/true);3330}3331 3332void UnwrappedLineParser::parseDoWhile() {3333 assert(FormatTok->is(tok::kw_do) && "'do' expected");3334 nextToken();3335 3336 parseLoopBody(/*KeepBraces=*/true, Style.BraceWrapping.BeforeWhile);3337 3338 // FIXME: Add error handling.3339 if (FormatTok->isNot(tok::kw_while)) {3340 addUnwrappedLine();3341 return;3342 }3343 3344 FormatTok->setFinalizedType(TT_DoWhile);3345 3346 // If in Whitesmiths mode, the line with the while() needs to be indented3347 // to the same level as the block.3348 if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)3349 ++Line->Level;3350 3351 nextToken();3352 parseStructuralElement();3353}3354 3355void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {3356 nextToken();3357 unsigned OldLineLevel = Line->Level;3358 3359 if (LeftAlignLabel)3360 Line->Level = 0;3361 else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))3362 --Line->Level;3363 3364 if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&3365 FormatTok->is(tok::l_brace)) {3366 3367 CompoundStatementIndenter Indenter(this, Line->Level,3368 Style.BraceWrapping.AfterCaseLabel,3369 Style.BraceWrapping.IndentBraces);3370 parseBlock();3371 if (FormatTok->is(tok::kw_break)) {3372 if (Style.BraceWrapping.AfterControlStatement ==3373 FormatStyle::BWACS_Always) {3374 addUnwrappedLine();3375 if (!Style.IndentCaseBlocks &&3376 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {3377 ++Line->Level;3378 }3379 }3380 parseStructuralElement();3381 }3382 addUnwrappedLine();3383 } else {3384 if (FormatTok->is(tok::semi))3385 nextToken();3386 addUnwrappedLine();3387 }3388 Line->Level = OldLineLevel;3389 if (FormatTok->isNot(tok::l_brace)) {3390 parseStructuralElement();3391 addUnwrappedLine();3392 }3393}3394 3395void UnwrappedLineParser::parseCaseLabel() {3396 assert(FormatTok->is(tok::kw_case) && "'case' expected");3397 auto *Case = FormatTok;3398 3399 // FIXME: fix handling of complex expressions here.3400 do {3401 nextToken();3402 if (FormatTok->is(tok::colon)) {3403 FormatTok->setFinalizedType(TT_CaseLabelColon);3404 break;3405 }3406 if (Style.isJava() && FormatTok->is(tok::arrow)) {3407 FormatTok->setFinalizedType(TT_CaseLabelArrow);3408 Case->setFinalizedType(TT_SwitchExpressionLabel);3409 break;3410 }3411 } while (!eof());3412 parseLabel();3413}3414 3415void UnwrappedLineParser::parseSwitch(bool IsExpr) {3416 assert(FormatTok->is(tok::kw_switch) && "'switch' expected");3417 nextToken();3418 if (FormatTok->is(tok::l_paren))3419 parseParens();3420 3421 keepAncestorBraces();3422 3423 if (FormatTok->is(tok::l_brace)) {3424 CompoundStatementIndenter Indenter(this, Style, Line->Level);3425 FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace3426 : TT_ControlStatementLBrace);3427 if (IsExpr)3428 parseChildBlock();3429 else3430 parseBlock();3431 setPreviousRBraceType(TT_ControlStatementRBrace);3432 if (!IsExpr)3433 addUnwrappedLine();3434 } else {3435 addUnwrappedLine();3436 ++Line->Level;3437 parseStructuralElement();3438 --Line->Level;3439 }3440 3441 if (Style.RemoveBracesLLVM)3442 NestedTooDeep.pop_back();3443}3444 3445void UnwrappedLineParser::parseAccessSpecifier() {3446 nextToken();3447 // Understand Qt's slots.3448 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))3449 nextToken();3450 // Otherwise, we don't know what it is, and we'd better keep the next token.3451 if (FormatTok->is(tok::colon))3452 nextToken();3453 addUnwrappedLine();3454}3455 3456/// Parses a requires, decides if it is a clause or an expression.3457/// \pre The current token has to be the requires keyword.3458/// \returns true if it parsed a clause.3459bool UnwrappedLineParser::parseRequires(bool SeenEqual) {3460 assert(FormatTok->is(tok::kw_requires) && "'requires' expected");3461 3462 // We try to guess if it is a requires clause, or a requires expression. For3463 // that we first check the next token.3464 switch (Tokens->peekNextToken(/*SkipComment=*/true)->Tok.getKind()) {3465 case tok::l_brace:3466 // This can only be an expression, never a clause.3467 parseRequiresExpression();3468 return false;3469 case tok::l_paren:3470 // Clauses and expression can start with a paren, it's unclear what we have.3471 break;3472 default:3473 // All other tokens can only be a clause.3474 parseRequiresClause();3475 return true;3476 }3477 3478 // Looking forward we would have to decide if there are function declaration3479 // like arguments to the requires expression:3480 // requires (T t) {3481 // Or there is a constraint expression for the requires clause:3482 // requires (C<T> && ...3483 3484 // But first let's look behind.3485 auto *PreviousNonComment = FormatTok->getPreviousNonComment();3486 3487 if (!PreviousNonComment ||3488 PreviousNonComment->is(TT_RequiresExpressionLBrace)) {3489 // If there is no token, or an expression left brace, we are a requires3490 // clause within a requires expression.3491 parseRequiresClause();3492 return true;3493 }3494 3495 switch (PreviousNonComment->Tok.getKind()) {3496 case tok::greater:3497 case tok::r_paren:3498 case tok::kw_noexcept:3499 case tok::kw_const:3500 case tok::star:3501 case tok::amp:3502 // This is a requires clause.3503 parseRequiresClause();3504 return true;3505 case tok::ampamp: {3506 // This can be either:3507 // if (... && requires (T t) ...)3508 // Or3509 // void member(...) && requires (C<T> ...3510 // We check the one token before that for a const:3511 // void member(...) const && requires (C<T> ...3512 auto PrevPrev = PreviousNonComment->getPreviousNonComment();3513 if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {3514 parseRequiresClause();3515 return true;3516 }3517 break;3518 }3519 default:3520 if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {3521 // This is a requires clause.3522 parseRequiresClause();3523 return true;3524 }3525 // It's an expression.3526 parseRequiresExpression();3527 return false;3528 }3529 3530 // Now we look forward and try to check if the paren content is a parameter3531 // list. The parameters can be cv-qualified and contain references or3532 // pointers.3533 // So we want basically to check for TYPE NAME, but TYPE can contain all kinds3534 // of stuff: typename, const, *, &, &&, ::, identifiers.3535 3536 unsigned StoredPosition = Tokens->getPosition();3537 FormatToken *NextToken = Tokens->getNextToken();3538 int Lookahead = 0;3539 auto PeekNext = [&Lookahead, &NextToken, this] {3540 ++Lookahead;3541 NextToken = Tokens->getNextToken();3542 };3543 3544 bool FoundType = false;3545 bool LastWasColonColon = false;3546 int OpenAngles = 0;3547 3548 for (; Lookahead < 50; PeekNext()) {3549 switch (NextToken->Tok.getKind()) {3550 case tok::kw_volatile:3551 case tok::kw_const:3552 case tok::comma:3553 if (OpenAngles == 0) {3554 FormatTok = Tokens->setPosition(StoredPosition);3555 parseRequiresExpression();3556 return false;3557 }3558 break;3559 case tok::eof:3560 // Break out of the loop.3561 Lookahead = 50;3562 break;3563 case tok::coloncolon:3564 LastWasColonColon = true;3565 break;3566 case tok::kw_decltype:3567 case tok::identifier:3568 if (FoundType && !LastWasColonColon && OpenAngles == 0) {3569 FormatTok = Tokens->setPosition(StoredPosition);3570 parseRequiresExpression();3571 return false;3572 }3573 FoundType = true;3574 LastWasColonColon = false;3575 break;3576 case tok::less:3577 ++OpenAngles;3578 break;3579 case tok::greater:3580 --OpenAngles;3581 break;3582 default:3583 if (NextToken->isTypeName(LangOpts)) {3584 FormatTok = Tokens->setPosition(StoredPosition);3585 parseRequiresExpression();3586 return false;3587 }3588 break;3589 }3590 }3591 // This seems to be a complicated expression, just assume it's a clause.3592 FormatTok = Tokens->setPosition(StoredPosition);3593 parseRequiresClause();3594 return true;3595}3596 3597/// Parses a requires clause.3598/// \sa parseRequiresExpression3599///3600/// Returns if it either has finished parsing the clause, or it detects, that3601/// the clause is incorrect.3602void UnwrappedLineParser::parseRequiresClause() {3603 assert(FormatTok->is(tok::kw_requires) && "'requires' expected");3604 3605 // If there is no previous token, we are within a requires expression,3606 // otherwise we will always have the template or function declaration in front3607 // of it.3608 bool InRequiresExpression =3609 !FormatTok->Previous ||3610 FormatTok->Previous->is(TT_RequiresExpressionLBrace);3611 3612 FormatTok->setFinalizedType(InRequiresExpression3613 ? TT_RequiresClauseInARequiresExpression3614 : TT_RequiresClause);3615 nextToken();3616 3617 // NOTE: parseConstraintExpression is only ever called from this function.3618 // It could be inlined into here.3619 parseConstraintExpression();3620 3621 if (!InRequiresExpression && FormatTok->Previous)3622 FormatTok->Previous->ClosesRequiresClause = true;3623}3624 3625/// Parses a requires expression.3626/// \sa parseRequiresClause3627///3628/// Returns if it either has finished parsing the expression, or it detects,3629/// that the expression is incorrect.3630void UnwrappedLineParser::parseRequiresExpression() {3631 assert(FormatTok->is(tok::kw_requires) && "'requires' expected");3632 3633 FormatTok->setFinalizedType(TT_RequiresExpression);3634 nextToken();3635 3636 if (FormatTok->is(tok::l_paren)) {3637 FormatTok->setFinalizedType(TT_RequiresExpressionLParen);3638 parseParens();3639 }3640 3641 if (FormatTok->is(tok::l_brace)) {3642 FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);3643 parseChildBlock();3644 }3645}3646 3647/// Parses a constraint expression.3648///3649/// This is the body of a requires clause. It returns, when the parsing is3650/// complete, or the expression is incorrect.3651void UnwrappedLineParser::parseConstraintExpression() {3652 // The special handling for lambdas is needed since tryToParseLambda() eats a3653 // token and if a requires expression is the last part of a requires clause3654 // and followed by an attribute like [[nodiscard]] the ClosesRequiresClause is3655 // not set on the correct token. Thus we need to be aware if we even expect a3656 // lambda to be possible.3657 // template <typename T> requires requires { ... } [[nodiscard]] ...;3658 bool LambdaNextTimeAllowed = true;3659 3660 // Within lambda declarations, it is permitted to put a requires clause after3661 // its template parameter list, which would place the requires clause right3662 // before the parentheses of the parameters of the lambda declaration. Thus,3663 // we track if we expect to see grouping parentheses at all.3664 // Without this check, `requires foo<T> (T t)` in the below example would be3665 // seen as the whole requires clause, accidentally eating the parameters of3666 // the lambda.3667 // [&]<typename T> requires foo<T> (T t) { ... };3668 bool TopLevelParensAllowed = true;3669 3670 do {3671 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false);3672 3673 switch (FormatTok->Tok.getKind()) {3674 case tok::kw_requires:3675 parseRequiresExpression();3676 break;3677 3678 case tok::l_paren:3679 if (!TopLevelParensAllowed)3680 return;3681 parseParens(/*AmpAmpTokenType=*/TT_BinaryOperator);3682 TopLevelParensAllowed = false;3683 break;3684 3685 case tok::l_square:3686 if (!LambdaThisTimeAllowed || !tryToParseLambda())3687 return;3688 break;3689 3690 case tok::kw_const:3691 case tok::semi:3692 case tok::kw_class:3693 case tok::kw_struct:3694 case tok::kw_union:3695 return;3696 3697 case tok::l_brace:3698 // Potential function body.3699 return;3700 3701 case tok::ampamp:3702 case tok::pipepipe:3703 FormatTok->setFinalizedType(TT_BinaryOperator);3704 nextToken();3705 LambdaNextTimeAllowed = true;3706 TopLevelParensAllowed = true;3707 break;3708 3709 case tok::comma:3710 case tok::comment:3711 LambdaNextTimeAllowed = LambdaThisTimeAllowed;3712 nextToken();3713 break;3714 3715 case tok::kw_sizeof:3716 case tok::greater:3717 case tok::greaterequal:3718 case tok::greatergreater:3719 case tok::less:3720 case tok::lessequal:3721 case tok::lessless:3722 case tok::equalequal:3723 case tok::exclaim:3724 case tok::exclaimequal:3725 case tok::plus:3726 case tok::minus:3727 case tok::star:3728 case tok::slash:3729 LambdaNextTimeAllowed = true;3730 TopLevelParensAllowed = true;3731 // Just eat them.3732 nextToken();3733 break;3734 3735 case tok::numeric_constant:3736 case tok::coloncolon:3737 case tok::kw_true:3738 case tok::kw_false:3739 TopLevelParensAllowed = false;3740 // Just eat them.3741 nextToken();3742 break;3743 3744 case tok::kw_static_cast:3745 case tok::kw_const_cast:3746 case tok::kw_reinterpret_cast:3747 case tok::kw_dynamic_cast:3748 nextToken();3749 if (FormatTok->isNot(tok::less))3750 return;3751 3752 nextToken();3753 parseBracedList(/*IsAngleBracket=*/true);3754 break;3755 3756 default:3757 if (!FormatTok->Tok.getIdentifierInfo()) {3758 // Identifiers are part of the default case, we check for more then3759 // tok::identifier to handle builtin type traits.3760 return;3761 }3762 3763 // We need to differentiate identifiers for a template deduction guide,3764 // variables, or function return types (the constraint expression has3765 // ended before that), and basically all other cases. But it's easier to3766 // check the other way around.3767 assert(FormatTok->Previous);3768 switch (FormatTok->Previous->Tok.getKind()) {3769 case tok::coloncolon: // Nested identifier.3770 case tok::ampamp: // Start of a function or variable for the3771 case tok::pipepipe: // constraint expression. (binary)3772 case tok::exclaim: // The same as above, but unary.3773 case tok::kw_requires: // Initial identifier of a requires clause.3774 case tok::equal: // Initial identifier of a concept declaration.3775 break;3776 default:3777 return;3778 }3779 3780 // Read identifier with optional template declaration.3781 nextToken();3782 if (FormatTok->is(tok::less)) {3783 nextToken();3784 parseBracedList(/*IsAngleBracket=*/true);3785 }3786 TopLevelParensAllowed = false;3787 break;3788 }3789 } while (!eof());3790}3791 3792bool UnwrappedLineParser::parseEnum() {3793 const FormatToken &InitialToken = *FormatTok;3794 3795 // Won't be 'enum' for NS_ENUMs.3796 if (FormatTok->is(tok::kw_enum))3797 nextToken();3798 3799 // In TypeScript, "enum" can also be used as property name, e.g. in interface3800 // declarations. An "enum" keyword followed by a colon would be a syntax3801 // error and thus assume it is just an identifier.3802 if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))3803 return false;3804 3805 // In protobuf, "enum" can be used as a field name.3806 if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))3807 return false;3808 3809 if (IsCpp) {3810 // Eat up enum class ...3811 if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))3812 nextToken();3813 while (FormatTok->is(tok::l_square))3814 if (!handleCppAttributes())3815 return false;3816 }3817 3818 while (FormatTok->Tok.getIdentifierInfo() ||3819 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,3820 tok::greater, tok::comma, tok::question,3821 tok::l_square)) {3822 if (Style.isVerilog()) {3823 FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);3824 nextToken();3825 // In Verilog the base type can have dimensions.3826 while (FormatTok->is(tok::l_square))3827 parseSquare();3828 } else {3829 nextToken();3830 }3831 // We can have macros or attributes in between 'enum' and the enum name.3832 if (FormatTok->is(tok::l_paren))3833 parseParens();3834 if (FormatTok->is(tok::identifier)) {3835 nextToken();3836 // If there are two identifiers in a row, this is likely an elaborate3837 // return type. In Java, this can be "implements", etc.3838 if (IsCpp && FormatTok->is(tok::identifier))3839 return false;3840 }3841 }3842 3843 // Just a declaration or something is wrong.3844 if (FormatTok->isNot(tok::l_brace))3845 return true;3846 FormatTok->setFinalizedType(TT_EnumLBrace);3847 FormatTok->setBlockKind(BK_Block);3848 3849 if (Style.isJava()) {3850 // Java enums are different.3851 parseJavaEnumBody();3852 return true;3853 }3854 if (Style.Language == FormatStyle::LK_Proto) {3855 parseBlock(/*MustBeDeclaration=*/true);3856 return true;3857 }3858 3859 if (!Style.AllowShortEnumsOnASingleLine &&3860 ShouldBreakBeforeBrace(Style, InitialToken, /*IsJavaRecord=*/false)) {3861 addUnwrappedLine();3862 }3863 // Parse enum body.3864 nextToken();3865 if (!Style.AllowShortEnumsOnASingleLine) {3866 addUnwrappedLine();3867 Line->Level += 1;3868 }3869 bool HasError = !parseBracedList(/*IsAngleBracket=*/false, /*IsEnum=*/true);3870 if (!Style.AllowShortEnumsOnASingleLine)3871 Line->Level -= 1;3872 if (HasError) {3873 if (FormatTok->is(tok::semi))3874 nextToken();3875 addUnwrappedLine();3876 }3877 setPreviousRBraceType(TT_EnumRBrace);3878 return true;3879 3880 // There is no addUnwrappedLine() here so that we fall through to parsing a3881 // structural element afterwards. Thus, in "enum A {} n, m;",3882 // "} n, m;" will end up in one unwrapped line.3883}3884 3885bool UnwrappedLineParser::parseStructLike() {3886 // parseRecord falls through and does not yet add an unwrapped line as a3887 // record declaration or definition can start a structural element.3888 parseRecord();3889 // This does not apply to Java, JavaScript and C#.3890 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) {3891 if (FormatTok->is(tok::semi))3892 nextToken();3893 addUnwrappedLine();3894 return true;3895 }3896 return false;3897}3898 3899namespace {3900// A class used to set and restore the Token position when peeking3901// ahead in the token source.3902class ScopedTokenPosition {3903 unsigned StoredPosition;3904 FormatTokenSource *Tokens;3905 3906public:3907 ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {3908 assert(Tokens && "Tokens expected to not be null");3909 StoredPosition = Tokens->getPosition();3910 }3911 3912 ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }3913};3914} // namespace3915 3916// Look to see if we have [[ by looking ahead, if3917// its not then rewind to the original position.3918bool UnwrappedLineParser::tryToParseSimpleAttribute() {3919 ScopedTokenPosition AutoPosition(Tokens);3920 FormatToken *Tok = Tokens->getNextToken();3921 // We already read the first [ check for the second.3922 if (Tok->isNot(tok::l_square))3923 return false;3924 // Double check that the attribute is just something3925 // fairly simple.3926 while (Tok->isNot(tok::eof)) {3927 if (Tok->is(tok::r_square))3928 break;3929 Tok = Tokens->getNextToken();3930 }3931 if (Tok->is(tok::eof))3932 return false;3933 Tok = Tokens->getNextToken();3934 if (Tok->isNot(tok::r_square))3935 return false;3936 Tok = Tokens->getNextToken();3937 if (Tok->is(tok::semi))3938 return false;3939 return true;3940}3941 3942void UnwrappedLineParser::parseJavaEnumBody() {3943 assert(FormatTok->is(tok::l_brace));3944 const FormatToken *OpeningBrace = FormatTok;3945 3946 // Determine whether the enum is simple, i.e. does not have a semicolon or3947 // constants with class bodies. Simple enums can be formatted like braced3948 // lists, contracted to a single line, etc.3949 unsigned StoredPosition = Tokens->getPosition();3950 bool IsSimple = true;3951 FormatToken *Tok = Tokens->getNextToken();3952 while (Tok->isNot(tok::eof)) {3953 if (Tok->is(tok::r_brace))3954 break;3955 if (Tok->isOneOf(tok::l_brace, tok::semi)) {3956 IsSimple = false;3957 break;3958 }3959 // FIXME: This will also mark enums with braces in the arguments to enum3960 // constants as "not simple". This is probably fine in practice, though.3961 Tok = Tokens->getNextToken();3962 }3963 FormatTok = Tokens->setPosition(StoredPosition);3964 3965 if (IsSimple) {3966 nextToken();3967 parseBracedList();3968 addUnwrappedLine();3969 return;3970 }3971 3972 // Parse the body of a more complex enum.3973 // First add a line for everything up to the "{".3974 nextToken();3975 addUnwrappedLine();3976 ++Line->Level;3977 3978 // Parse the enum constants.3979 while (!eof()) {3980 if (FormatTok->is(tok::l_brace)) {3981 // Parse the constant's class body.3982 parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u,3983 /*MunchSemi=*/false);3984 } else if (FormatTok->is(tok::l_paren)) {3985 parseParens();3986 } else if (FormatTok->is(tok::comma)) {3987 nextToken();3988 addUnwrappedLine();3989 } else if (FormatTok->is(tok::semi)) {3990 nextToken();3991 addUnwrappedLine();3992 break;3993 } else if (FormatTok->is(tok::r_brace)) {3994 addUnwrappedLine();3995 break;3996 } else {3997 nextToken();3998 }3999 }4000 4001 // Parse the class body after the enum's ";" if any.4002 parseLevel(OpeningBrace);4003 nextToken();4004 --Line->Level;4005 addUnwrappedLine();4006}4007 4008void UnwrappedLineParser::parseRecord(bool ParseAsExpr, bool IsJavaRecord) {4009 assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record));4010 const FormatToken &InitialToken = *FormatTok;4011 nextToken();4012 4013 FormatToken *ClassName =4014 IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok : nullptr;4015 bool IsDerived = false;4016 auto IsNonMacroIdentifier = [](const FormatToken *Tok) {4017 return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();4018 };4019 // JavaScript/TypeScript supports anonymous classes like:4020 // a = class extends foo { }4021 bool JSPastExtendsOrImplements = false;4022 // The actual identifier can be a nested name specifier, and in macros4023 // it is often token-pasted.4024 // An [[attribute]] can be before the identifier.4025 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,4026 tok::kw_alignas, tok::l_square) ||4027 FormatTok->isAttribute() ||4028 ((Style.isJava() || Style.isJavaScript()) &&4029 FormatTok->isOneOf(tok::period, tok::comma))) {4030 if (Style.isJavaScript() &&4031 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {4032 JSPastExtendsOrImplements = true;4033 // JavaScript/TypeScript supports inline object types in4034 // extends/implements positions:4035 // class Foo implements {bar: number} { }4036 nextToken();4037 if (FormatTok->is(tok::l_brace)) {4038 tryToParseBracedList();4039 continue;4040 }4041 }4042 if (FormatTok->is(tok::l_square) && handleCppAttributes())4043 continue;4044 auto *Previous = FormatTok;4045 nextToken();4046 switch (FormatTok->Tok.getKind()) {4047 case tok::l_paren:4048 // We can have macros in between 'class' and the class name.4049 if (IsJavaRecord || !IsNonMacroIdentifier(Previous) ||4050 // e.g. `struct macro(a) S { int i; };`4051 Previous->Previous == &InitialToken) {4052 parseParens();4053 }4054 break;4055 case tok::coloncolon:4056 case tok::hashhash:4057 break;4058 default:4059 if (JSPastExtendsOrImplements || ClassName ||4060 Previous->isNot(tok::identifier) || Previous->is(TT_AttributeMacro)) {4061 break;4062 }4063 if (const auto Text = Previous->TokenText;4064 Text.size() == 1 || Text != Text.upper()) {4065 ClassName = Previous;4066 }4067 }4068 }4069 4070 auto IsListInitialization = [&] {4071 if (!ClassName || IsDerived || JSPastExtendsOrImplements)4072 return false;4073 assert(FormatTok->is(tok::l_brace));4074 const auto *Prev = FormatTok->getPreviousNonComment();4075 assert(Prev);4076 return Prev != ClassName && Prev->is(tok::identifier) &&4077 Prev->isNot(Keywords.kw_final) && tryToParseBracedList();4078 };4079 4080 if (FormatTok->isOneOf(tok::colon, tok::less)) {4081 int AngleNestingLevel = 0;4082 do {4083 if (FormatTok->is(tok::less))4084 ++AngleNestingLevel;4085 else if (FormatTok->is(tok::greater))4086 --AngleNestingLevel;4087 4088 if (AngleNestingLevel == 0) {4089 if (FormatTok->is(tok::colon)) {4090 IsDerived = true;4091 } else if (!IsDerived && FormatTok->is(tok::identifier) &&4092 FormatTok->Previous->is(tok::coloncolon)) {4093 ClassName = FormatTok;4094 } else if (FormatTok->is(tok::l_paren) &&4095 IsNonMacroIdentifier(FormatTok->Previous)) {4096 break;4097 }4098 }4099 if (FormatTok->is(tok::l_brace)) {4100 if (AngleNestingLevel == 0 && IsListInitialization())4101 return;4102 calculateBraceTypes(/*ExpectClassBody=*/true);4103 if (!tryToParseBracedList())4104 break;4105 }4106 if (FormatTok->is(tok::l_square)) {4107 FormatToken *Previous = FormatTok->Previous;4108 if (!Previous || (Previous->isNot(tok::r_paren) &&4109 !Previous->isTypeOrIdentifier(LangOpts))) {4110 // Don't try parsing a lambda if we had a closing parenthesis before,4111 // it was probably a pointer to an array: int (*)[].4112 if (!tryToParseLambda())4113 continue;4114 } else {4115 parseSquare();4116 continue;4117 }4118 }4119 if (FormatTok->is(tok::semi))4120 return;4121 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {4122 addUnwrappedLine();4123 nextToken();4124 parseCSharpGenericTypeConstraint();4125 break;4126 }4127 nextToken();4128 } while (!eof());4129 }4130 4131 auto GetBraceTypes =4132 [](const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {4133 switch (RecordTok.Tok.getKind()) {4134 case tok::kw_class:4135 return {TT_ClassLBrace, TT_ClassRBrace};4136 case tok::kw_struct:4137 return {TT_StructLBrace, TT_StructRBrace};4138 case tok::kw_union:4139 return {TT_UnionLBrace, TT_UnionRBrace};4140 default:4141 // Useful for e.g. interface.4142 return {TT_RecordLBrace, TT_RecordRBrace};4143 }4144 };4145 if (FormatTok->is(tok::l_brace)) {4146 if (IsListInitialization())4147 return;4148 if (ClassName)4149 ClassName->setFinalizedType(TT_ClassHeadName);4150 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);4151 FormatTok->setFinalizedType(OpenBraceType);4152 if (ParseAsExpr) {4153 parseChildBlock();4154 } else {4155 if (ShouldBreakBeforeBrace(Style, InitialToken, IsJavaRecord))4156 addUnwrappedLine();4157 4158 unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;4159 parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/false);4160 }4161 setPreviousRBraceType(ClosingBraceType);4162 }4163 // There is no addUnwrappedLine() here so that we fall through to parsing a4164 // structural element afterwards. Thus, in "class A {} n, m;",4165 // "} n, m;" will end up in one unwrapped line.4166}4167 4168void UnwrappedLineParser::parseObjCMethod() {4169 assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&4170 "'(' or identifier expected.");4171 do {4172 if (FormatTok->is(tok::semi)) {4173 nextToken();4174 addUnwrappedLine();4175 return;4176 } else if (FormatTok->is(tok::l_brace)) {4177 if (Style.BraceWrapping.AfterFunction)4178 addUnwrappedLine();4179 parseBlock();4180 addUnwrappedLine();4181 return;4182 } else {4183 nextToken();4184 }4185 } while (!eof());4186}4187 4188void UnwrappedLineParser::parseObjCProtocolList() {4189 assert(FormatTok->is(tok::less) && "'<' expected.");4190 do {4191 nextToken();4192 // Early exit in case someone forgot a close angle.4193 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))4194 return;4195 } while (!eof() && FormatTok->isNot(tok::greater));4196 nextToken(); // Skip '>'.4197}4198 4199void UnwrappedLineParser::parseObjCUntilAtEnd() {4200 do {4201 if (FormatTok->is(tok::objc_end)) {4202 nextToken();4203 addUnwrappedLine();4204 break;4205 }4206 if (FormatTok->is(tok::l_brace)) {4207 parseBlock();4208 // In ObjC interfaces, nothing should be following the "}".4209 addUnwrappedLine();4210 } else if (FormatTok->is(tok::r_brace)) {4211 // Ignore stray "}". parseStructuralElement doesn't consume them.4212 nextToken();4213 addUnwrappedLine();4214 } else if (FormatTok->isOneOf(tok::minus, tok::plus)) {4215 nextToken();4216 parseObjCMethod();4217 } else {4218 parseStructuralElement();4219 }4220 } while (!eof());4221}4222 4223void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {4224 assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation));4225 nextToken();4226 nextToken(); // interface name4227 4228 // @interface can be followed by a lightweight generic4229 // specialization list, then either a base class or a category.4230 if (FormatTok->is(tok::less))4231 parseObjCLightweightGenerics();4232 if (FormatTok->is(tok::colon)) {4233 nextToken();4234 nextToken(); // base class name4235 // The base class can also have lightweight generics applied to it.4236 if (FormatTok->is(tok::less))4237 parseObjCLightweightGenerics();4238 } else if (FormatTok->is(tok::l_paren)) {4239 // Skip category, if present.4240 parseParens();4241 }4242 4243 if (FormatTok->is(tok::less))4244 parseObjCProtocolList();4245 4246 if (FormatTok->is(tok::l_brace)) {4247 if (Style.BraceWrapping.AfterObjCDeclaration)4248 addUnwrappedLine();4249 parseBlock(/*MustBeDeclaration=*/true);4250 }4251 4252 // With instance variables, this puts '}' on its own line. Without instance4253 // variables, this ends the @interface line.4254 addUnwrappedLine();4255 4256 parseObjCUntilAtEnd();4257}4258 4259void UnwrappedLineParser::parseObjCLightweightGenerics() {4260 assert(FormatTok->is(tok::less));4261 // Unlike protocol lists, generic parameterizations support4262 // nested angles:4263 //4264 // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :4265 // NSObject <NSCopying, NSSecureCoding>4266 //4267 // so we need to count how many open angles we have left.4268 unsigned NumOpenAngles = 1;4269 do {4270 nextToken();4271 // Early exit in case someone forgot a close angle.4272 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))4273 break;4274 if (FormatTok->is(tok::less)) {4275 ++NumOpenAngles;4276 } else if (FormatTok->is(tok::greater)) {4277 assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");4278 --NumOpenAngles;4279 }4280 } while (!eof() && NumOpenAngles != 0);4281 nextToken(); // Skip '>'.4282}4283 4284// Returns true for the declaration/definition form of @protocol,4285// false for the expression form.4286bool UnwrappedLineParser::parseObjCProtocol() {4287 assert(FormatTok->is(tok::objc_protocol));4288 nextToken();4289 4290 if (FormatTok->is(tok::l_paren)) {4291 // The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);".4292 return false;4293 }4294 4295 // The definition/declaration form,4296 // @protocol Foo4297 // - (int)someMethod;4298 // @end4299 4300 nextToken(); // protocol name4301 4302 if (FormatTok->is(tok::less))4303 parseObjCProtocolList();4304 4305 // Check for protocol declaration.4306 if (FormatTok->is(tok::semi)) {4307 nextToken();4308 addUnwrappedLine();4309 return true;4310 }4311 4312 addUnwrappedLine();4313 parseObjCUntilAtEnd();4314 return true;4315}4316 4317void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {4318 bool IsImport = FormatTok->is(Keywords.kw_import);4319 assert(IsImport || FormatTok->is(tok::kw_export));4320 nextToken();4321 4322 // Consume the "default" in "export default class/function".4323 if (FormatTok->is(tok::kw_default))4324 nextToken();4325 4326 // Consume "async function", "function" and "default function", so that these4327 // get parsed as free-standing JS functions, i.e. do not require a trailing4328 // semicolon.4329 if (FormatTok->is(Keywords.kw_async))4330 nextToken();4331 if (FormatTok->is(Keywords.kw_function)) {4332 nextToken();4333 return;4334 }4335 4336 // For imports, `export *`, `export {...}`, consume the rest of the line up4337 // to the terminating `;`. For everything else, just return and continue4338 // parsing the structural element, i.e. the declaration or expression for4339 // `export default`.4340 if (!IsImport && FormatTok->isNoneOf(tok::l_brace, tok::star) &&4341 !FormatTok->isStringLiteral() &&4342 !(FormatTok->is(Keywords.kw_type) &&4343 Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {4344 return;4345 }4346 4347 while (!eof()) {4348 if (FormatTok->is(tok::semi))4349 return;4350 if (Line->Tokens.empty()) {4351 // Common issue: Automatic Semicolon Insertion wrapped the line, so the4352 // import statement should terminate.4353 return;4354 }4355 if (FormatTok->is(tok::l_brace)) {4356 FormatTok->setBlockKind(BK_Block);4357 nextToken();4358 parseBracedList();4359 } else {4360 nextToken();4361 }4362 }4363}4364 4365void UnwrappedLineParser::parseStatementMacro() {4366 nextToken();4367 if (FormatTok->is(tok::l_paren))4368 parseParens();4369 if (FormatTok->is(tok::semi))4370 nextToken();4371 addUnwrappedLine();4372}4373 4374void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {4375 // consume things like a::`b.c[d:e] or a::*4376 while (true) {4377 if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,4378 tok::coloncolon, tok::hash) ||4379 Keywords.isVerilogIdentifier(*FormatTok)) {4380 nextToken();4381 } else if (FormatTok->is(tok::l_square)) {4382 parseSquare();4383 } else {4384 break;4385 }4386 }4387}4388 4389void UnwrappedLineParser::parseVerilogSensitivityList() {4390 if (FormatTok->isNot(tok::at))4391 return;4392 nextToken();4393 // A block event expression has 2 at signs.4394 if (FormatTok->is(tok::at))4395 nextToken();4396 switch (FormatTok->Tok.getKind()) {4397 case tok::star:4398 nextToken();4399 break;4400 case tok::l_paren:4401 parseParens();4402 break;4403 default:4404 parseVerilogHierarchyIdentifier();4405 break;4406 }4407}4408 4409unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {4410 unsigned AddLevels = 0;4411 4412 if (FormatTok->is(Keywords.kw_clocking)) {4413 nextToken();4414 if (Keywords.isVerilogIdentifier(*FormatTok))4415 nextToken();4416 parseVerilogSensitivityList();4417 if (FormatTok->is(tok::semi))4418 nextToken();4419 } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,4420 Keywords.kw_casez, Keywords.kw_randcase,4421 Keywords.kw_randsequence)) {4422 if (Style.IndentCaseLabels)4423 AddLevels++;4424 nextToken();4425 if (FormatTok->is(tok::l_paren)) {4426 FormatTok->setFinalizedType(TT_ConditionLParen);4427 parseParens();4428 }4429 if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))4430 nextToken();4431 // The case header has no semicolon.4432 } else {4433 // "module" etc.4434 nextToken();4435 // all the words like the name of the module and specifiers like4436 // "automatic" and the width of function return type4437 while (true) {4438 if (FormatTok->is(tok::l_square)) {4439 auto Prev = FormatTok->getPreviousNonComment();4440 if (Prev && Keywords.isVerilogIdentifier(*Prev))4441 Prev->setFinalizedType(TT_VerilogDimensionedTypeName);4442 parseSquare();4443 } else if (Keywords.isVerilogIdentifier(*FormatTok) ||4444 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,4445 Keywords.kw_automatic, tok::kw_static)) {4446 nextToken();4447 } else {4448 break;4449 }4450 }4451 4452 auto NewLine = [this]() {4453 addUnwrappedLine();4454 Line->IsContinuation = true;4455 };4456 4457 // package imports4458 while (FormatTok->is(Keywords.kw_import)) {4459 NewLine();4460 nextToken();4461 parseVerilogHierarchyIdentifier();4462 if (FormatTok->is(tok::semi))4463 nextToken();4464 }4465 4466 // parameters and ports4467 if (FormatTok->is(Keywords.kw_verilogHash)) {4468 NewLine();4469 nextToken();4470 if (FormatTok->is(tok::l_paren)) {4471 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);4472 parseParens();4473 }4474 }4475 if (FormatTok->is(tok::l_paren)) {4476 NewLine();4477 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);4478 parseParens();4479 }4480 4481 // extends and implements4482 if (FormatTok->is(Keywords.kw_extends)) {4483 NewLine();4484 nextToken();4485 parseVerilogHierarchyIdentifier();4486 if (FormatTok->is(tok::l_paren))4487 parseParens();4488 }4489 if (FormatTok->is(Keywords.kw_implements)) {4490 NewLine();4491 do {4492 nextToken();4493 parseVerilogHierarchyIdentifier();4494 } while (FormatTok->is(tok::comma));4495 }4496 4497 // Coverage event for cover groups.4498 if (FormatTok->is(tok::at)) {4499 NewLine();4500 parseVerilogSensitivityList();4501 }4502 4503 if (FormatTok->is(tok::semi))4504 nextToken(/*LevelDifference=*/1);4505 addUnwrappedLine();4506 }4507 4508 return AddLevels;4509}4510 4511void UnwrappedLineParser::parseVerilogTable() {4512 assert(FormatTok->is(Keywords.kw_table));4513 nextToken(/*LevelDifference=*/1);4514 addUnwrappedLine();4515 4516 auto InitialLevel = Line->Level++;4517 while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) {4518 FormatToken *Tok = FormatTok;4519 nextToken();4520 if (Tok->is(tok::semi))4521 addUnwrappedLine();4522 else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus))4523 Tok->setFinalizedType(TT_VerilogTableItem);4524 }4525 Line->Level = InitialLevel;4526 nextToken(/*LevelDifference=*/-1);4527 addUnwrappedLine();4528}4529 4530void UnwrappedLineParser::parseVerilogCaseLabel() {4531 // The label will get unindented in AnnotatingParser. If there are no leading4532 // spaces, indent the rest here so that things inside the block will be4533 // indented relative to things outside. We don't use parseLabel because we4534 // don't know whether this colon is a label or a ternary expression at this4535 // point.4536 auto OrigLevel = Line->Level;4537 auto FirstLine = CurrentLines->size();4538 if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1))4539 ++Line->Level;4540 else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))4541 --Line->Level;4542 parseStructuralElement();4543 // Restore the indentation in both the new line and the line that has the4544 // label.4545 if (CurrentLines->size() > FirstLine)4546 (*CurrentLines)[FirstLine].Level = OrigLevel;4547 Line->Level = OrigLevel;4548}4549 4550void UnwrappedLineParser::parseVerilogExtern() {4551 assert(4552 FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));4553 nextToken();4554 // "DPI-C"4555 if (FormatTok->is(tok::string_literal))4556 nextToken();4557 if (FormatTok->isOneOf(Keywords.kw_context, Keywords.kw_pure))4558 nextToken();4559 if (Keywords.isVerilogIdentifier(*FormatTok))4560 nextToken();4561 if (FormatTok->is(tok::equal))4562 nextToken();4563 if (Keywords.isVerilogHierarchy(*FormatTok))4564 parseVerilogHierarchyHeader();4565}4566 4567bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const {4568 for (const auto &N : Line.Tokens) {4569 if (N.Tok->MacroCtx)4570 return true;4571 for (const UnwrappedLine &Child : N.Children)4572 if (containsExpansion(Child))4573 return true;4574 }4575 return false;4576}4577 4578void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {4579 if (Line->Tokens.empty())4580 return;4581 LLVM_DEBUG({4582 if (!parsingPPDirective()) {4583 llvm::dbgs() << "Adding unwrapped line:\n";4584 printDebugInfo(*Line);4585 }4586 });4587 4588 // If this line closes a block when in Whitesmiths mode, remember that4589 // information so that the level can be decreased after the line is added.4590 // This has to happen after the addition of the line since the line itself4591 // needs to be indented.4592 bool ClosesWhitesmithsBlock =4593 Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&4594 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;4595 4596 // If the current line was expanded from a macro call, we use it to4597 // reconstruct an unwrapped line from the structure of the expanded unwrapped4598 // line and the unexpanded token stream.4599 if (!parsingPPDirective() && !InExpansion && containsExpansion(*Line)) {4600 if (!Reconstruct)4601 Reconstruct.emplace(Line->Level, Unexpanded);4602 Reconstruct->addLine(*Line);4603 4604 // While the reconstructed unexpanded lines are stored in the normal4605 // flow of lines, the expanded lines are stored on the side to be analyzed4606 // in an extra step.4607 CurrentExpandedLines.push_back(std::move(*Line));4608 4609 if (Reconstruct->finished()) {4610 UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();4611 assert(!Reconstructed.Tokens.empty() &&4612 "Reconstructed must at least contain the macro identifier.");4613 assert(!parsingPPDirective());4614 LLVM_DEBUG({4615 llvm::dbgs() << "Adding unexpanded line:\n";4616 printDebugInfo(Reconstructed);4617 });4618 ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;4619 Lines.push_back(std::move(Reconstructed));4620 CurrentExpandedLines.clear();4621 Reconstruct.reset();4622 }4623 } else {4624 // At the top level we only get here when no unexpansion is going on, or4625 // when conditional formatting led to unfinished macro reconstructions.4626 assert(!Reconstruct || (CurrentLines != &Lines) || !PPStack.empty());4627 CurrentLines->push_back(std::move(*Line));4628 }4629 Line->Tokens.clear();4630 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;4631 Line->FirstStartColumn = 0;4632 Line->IsContinuation = false;4633 Line->SeenDecltypeAuto = false;4634 4635 if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)4636 --Line->Level;4637 if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {4638 CurrentLines->append(4639 std::make_move_iterator(PreprocessorDirectives.begin()),4640 std::make_move_iterator(PreprocessorDirectives.end()));4641 PreprocessorDirectives.clear();4642 }4643 // Disconnect the current token from the last token on the previous line.4644 FormatTok->Previous = nullptr;4645}4646 4647bool UnwrappedLineParser::eof() const { return FormatTok->is(tok::eof); }4648 4649bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {4650 return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&4651 FormatTok.NewlinesBefore > 0;4652}4653 4654// Checks if \p FormatTok is a line comment that continues the line comment4655// section on \p Line.4656static bool4657continuesLineCommentSection(const FormatToken &FormatTok,4658 const UnwrappedLine &Line, const FormatStyle &Style,4659 const llvm::Regex &CommentPragmasRegex) {4660 if (Line.Tokens.empty() || Style.ReflowComments != FormatStyle::RCS_Always)4661 return false;4662 4663 StringRef IndentContent = FormatTok.TokenText;4664 if (FormatTok.TokenText.starts_with("//") ||4665 FormatTok.TokenText.starts_with("/*")) {4666 IndentContent = FormatTok.TokenText.substr(2);4667 }4668 if (CommentPragmasRegex.match(IndentContent))4669 return false;4670 4671 // If Line starts with a line comment, then FormatTok continues the comment4672 // section if its original column is greater or equal to the original start4673 // column of the line.4674 //4675 // Define the min column token of a line as follows: if a line ends in '{' or4676 // contains a '{' followed by a line comment, then the min column token is4677 // that '{'. Otherwise, the min column token of the line is the first token of4678 // the line.4679 //4680 // If Line starts with a token other than a line comment, then FormatTok4681 // continues the comment section if its original column is greater than the4682 // original start column of the min column token of the line.4683 //4684 // For example, the second line comment continues the first in these cases:4685 //4686 // // first line4687 // // second line4688 //4689 // and:4690 //4691 // // first line4692 // // second line4693 //4694 // and:4695 //4696 // int i; // first line4697 // // second line4698 //4699 // and:4700 //4701 // do { // first line4702 // // second line4703 // int i;4704 // } while (true);4705 //4706 // and:4707 //4708 // enum {4709 // a, // first line4710 // // second line4711 // b4712 // };4713 //4714 // The second line comment doesn't continue the first in these cases:4715 //4716 // // first line4717 // // second line4718 //4719 // and:4720 //4721 // int i; // first line4722 // // second line4723 //4724 // and:4725 //4726 // do { // first line4727 // // second line4728 // int i;4729 // } while (true);4730 //4731 // and:4732 //4733 // enum {4734 // a, // first line4735 // // second line4736 // };4737 const FormatToken *MinColumnToken = Line.Tokens.front().Tok;4738 4739 // Scan for '{//'. If found, use the column of '{' as a min column for line4740 // comment section continuation.4741 const FormatToken *PreviousToken = nullptr;4742 for (const UnwrappedLineNode &Node : Line.Tokens) {4743 if (PreviousToken && PreviousToken->is(tok::l_brace) &&4744 isLineComment(*Node.Tok)) {4745 MinColumnToken = PreviousToken;4746 break;4747 }4748 PreviousToken = Node.Tok;4749 4750 // Grab the last newline preceding a token in this unwrapped line.4751 if (Node.Tok->NewlinesBefore > 0)4752 MinColumnToken = Node.Tok;4753 }4754 if (PreviousToken && PreviousToken->is(tok::l_brace))4755 MinColumnToken = PreviousToken;4756 4757 return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,4758 MinColumnToken);4759}4760 4761void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {4762 bool JustComments = Line->Tokens.empty();4763 for (FormatToken *Tok : CommentsBeforeNextToken) {4764 // Line comments that belong to the same line comment section are put on the4765 // same line since later we might want to reflow content between them.4766 // Additional fine-grained breaking of line comment sections is controlled4767 // by the class BreakableLineCommentSection in case it is desirable to keep4768 // several line comment sections in the same unwrapped line.4769 //4770 // FIXME: Consider putting separate line comment sections as children to the4771 // unwrapped line instead.4772 Tok->ContinuesLineCommentSection =4773 continuesLineCommentSection(*Tok, *Line, Style, CommentPragmasRegex);4774 if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection)4775 addUnwrappedLine();4776 pushToken(Tok);4777 }4778 if (NewlineBeforeNext && JustComments)4779 addUnwrappedLine();4780 CommentsBeforeNextToken.clear();4781}4782 4783void UnwrappedLineParser::nextToken(int LevelDifference) {4784 if (eof())4785 return;4786 flushComments(isOnNewLine(*FormatTok));4787 pushToken(FormatTok);4788 FormatToken *Previous = FormatTok;4789 if (!Style.isJavaScript())4790 readToken(LevelDifference);4791 else4792 readTokenWithJavaScriptASI();4793 FormatTok->Previous = Previous;4794 if (Style.isVerilog()) {4795 // Blocks in Verilog can have `begin` and `end` instead of braces. For4796 // keywords like `begin`, we can't treat them the same as left braces4797 // because some contexts require one of them. For example structs use4798 // braces and if blocks use keywords, and a left brace can occur in an if4799 // statement, but it is not a block. For keywords like `end`, we simply4800 // treat them the same as right braces.4801 if (Keywords.isVerilogEnd(*FormatTok))4802 FormatTok->Tok.setKind(tok::r_brace);4803 }4804}4805 4806void UnwrappedLineParser::distributeComments(4807 const ArrayRef<FormatToken *> &Comments, const FormatToken *NextTok) {4808 // Whether or not a line comment token continues a line is controlled by4809 // the method continuesLineCommentSection, with the following caveat:4810 //4811 // Define a trail of Comments to be a nonempty proper postfix of Comments such4812 // that each comment line from the trail is aligned with the next token, if4813 // the next token exists. If a trail exists, the beginning of the maximal4814 // trail is marked as a start of a new comment section.4815 //4816 // For example in this code:4817 //4818 // int a; // line about a4819 // // line 1 about b4820 // // line 2 about b4821 // int b;4822 //4823 // the two lines about b form a maximal trail, so there are two sections, the4824 // first one consisting of the single comment "// line about a" and the4825 // second one consisting of the next two comments.4826 if (Comments.empty())4827 return;4828 bool ShouldPushCommentsInCurrentLine = true;4829 bool HasTrailAlignedWithNextToken = false;4830 unsigned StartOfTrailAlignedWithNextToken = 0;4831 if (NextTok) {4832 // We are skipping the first element intentionally.4833 for (unsigned i = Comments.size() - 1; i > 0; --i) {4834 if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) {4835 HasTrailAlignedWithNextToken = true;4836 StartOfTrailAlignedWithNextToken = i;4837 }4838 }4839 }4840 for (unsigned i = 0, e = Comments.size(); i < e; ++i) {4841 FormatToken *FormatTok = Comments[i];4842 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {4843 FormatTok->ContinuesLineCommentSection = false;4844 } else {4845 FormatTok->ContinuesLineCommentSection = continuesLineCommentSection(4846 *FormatTok, *Line, Style, CommentPragmasRegex);4847 }4848 if (!FormatTok->ContinuesLineCommentSection &&4849 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {4850 ShouldPushCommentsInCurrentLine = false;4851 }4852 if (ShouldPushCommentsInCurrentLine)4853 pushToken(FormatTok);4854 else4855 CommentsBeforeNextToken.push_back(FormatTok);4856 }4857}4858 4859void UnwrappedLineParser::readToken(int LevelDifference) {4860 SmallVector<FormatToken *, 1> Comments;4861 bool PreviousWasComment = false;4862 bool FirstNonCommentOnLine = false;4863 do {4864 FormatTok = Tokens->getNextToken();4865 assert(FormatTok);4866 while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,4867 TT_ConflictAlternative)) {4868 if (FormatTok->is(TT_ConflictStart))4869 conditionalCompilationStart(/*Unreachable=*/false);4870 else if (FormatTok->is(TT_ConflictAlternative))4871 conditionalCompilationAlternative();4872 else if (FormatTok->is(TT_ConflictEnd))4873 conditionalCompilationEnd();4874 FormatTok = Tokens->getNextToken();4875 FormatTok->MustBreakBefore = true;4876 FormatTok->MustBreakBeforeFinalized = true;4877 }4878 4879 auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine,4880 const FormatToken &Tok,4881 bool PreviousWasComment) {4882 auto IsFirstOnLine = [](const FormatToken &Tok) {4883 return Tok.HasUnescapedNewline || Tok.IsFirst;4884 };4885 4886 // Consider preprocessor directives preceded by block comments as first4887 // on line.4888 if (PreviousWasComment)4889 return FirstNonCommentOnLine || IsFirstOnLine(Tok);4890 return IsFirstOnLine(Tok);4891 };4892 4893 FirstNonCommentOnLine = IsFirstNonCommentOnLine(4894 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);4895 PreviousWasComment = FormatTok->is(tok::comment);4896 4897 while (!Line->InPPDirective && FormatTok->is(tok::hash) &&4898 FirstNonCommentOnLine) {4899 // In Verilog, the backtick is used for macro invocations. In TableGen,4900 // the single hash is used for the paste operator.4901 const auto *Next = Tokens->peekNextToken();4902 if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*Next)) ||4903 (Style.isTableGen() &&4904 Next->isNoneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef,4905 tok::pp_ifndef, tok::pp_endif))) {4906 break;4907 }4908 distributeComments(Comments, FormatTok);4909 Comments.clear();4910 // If there is an unfinished unwrapped line, we flush the preprocessor4911 // directives only after that unwrapped line was finished later.4912 bool SwitchToPreprocessorLines = !Line->Tokens.empty();4913 ScopedLineState BlockState(*this, SwitchToPreprocessorLines);4914 assert((LevelDifference >= 0 ||4915 static_cast<unsigned>(-LevelDifference) <= Line->Level) &&4916 "LevelDifference makes Line->Level negative");4917 Line->Level += LevelDifference;4918 // Comments stored before the preprocessor directive need to be output4919 // before the preprocessor directive, at the same level as the4920 // preprocessor directive, as we consider them to apply to the directive.4921 if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&4922 PPBranchLevel > 0) {4923 Line->Level += PPBranchLevel;4924 }4925 assert(Line->Level >= Line->UnbracedBodyLevel);4926 Line->Level -= Line->UnbracedBodyLevel;4927 flushComments(isOnNewLine(*FormatTok));4928 parsePPDirective();4929 PreviousWasComment = FormatTok->is(tok::comment);4930 FirstNonCommentOnLine = IsFirstNonCommentOnLine(4931 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);4932 }4933 4934 if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&4935 !Line->InPPDirective) {4936 continue;4937 }4938 4939 if (FormatTok->is(tok::identifier) &&4940 Macros.defined(FormatTok->TokenText) &&4941 // FIXME: Allow expanding macros in preprocessor directives.4942 !Line->InPPDirective) {4943 FormatToken *ID = FormatTok;4944 unsigned Position = Tokens->getPosition();4945 4946 // To correctly parse the code, we need to replace the tokens of the macro4947 // call with its expansion.4948 auto PreCall = std::move(Line);4949 Line.reset(new UnwrappedLine);4950 bool OldInExpansion = InExpansion;4951 InExpansion = true;4952 // We parse the macro call into a new line.4953 auto Args = parseMacroCall();4954 InExpansion = OldInExpansion;4955 assert(Line->Tokens.front().Tok == ID);4956 // And remember the unexpanded macro call tokens.4957 auto UnexpandedLine = std::move(Line);4958 // Reset to the old line.4959 Line = std::move(PreCall);4960 4961 LLVM_DEBUG({4962 llvm::dbgs() << "Macro call: " << ID->TokenText << "(";4963 if (Args) {4964 llvm::dbgs() << "(";4965 for (const auto &Arg : Args.value())4966 for (const auto &T : Arg)4967 llvm::dbgs() << T->TokenText << " ";4968 llvm::dbgs() << ")";4969 }4970 llvm::dbgs() << "\n";4971 });4972 if (Macros.objectLike(ID->TokenText) && Args &&4973 !Macros.hasArity(ID->TokenText, Args->size())) {4974 // The macro is either4975 // - object-like, but we got argumnets, or4976 // - overloaded to be both object-like and function-like, but none of4977 // the function-like arities match the number of arguments.4978 // Thus, expand as object-like macro.4979 LLVM_DEBUG(llvm::dbgs()4980 << "Macro \"" << ID->TokenText4981 << "\" not overloaded for arity " << Args->size()4982 << "or not function-like, using object-like overload.");4983 Args.reset();4984 UnexpandedLine->Tokens.resize(1);4985 Tokens->setPosition(Position);4986 nextToken();4987 assert(!Args && Macros.objectLike(ID->TokenText));4988 }4989 if ((!Args && Macros.objectLike(ID->TokenText)) ||4990 (Args && Macros.hasArity(ID->TokenText, Args->size()))) {4991 // Next, we insert the expanded tokens in the token stream at the4992 // current position, and continue parsing.4993 Unexpanded[ID] = std::move(UnexpandedLine);4994 SmallVector<FormatToken *, 8> Expansion =4995 Macros.expand(ID, std::move(Args));4996 if (!Expansion.empty())4997 FormatTok = Tokens->insertTokens(Expansion);4998 4999 LLVM_DEBUG({5000 llvm::dbgs() << "Expanded: ";5001 for (const auto &T : Expansion)5002 llvm::dbgs() << T->TokenText << " ";5003 llvm::dbgs() << "\n";5004 });5005 } else {5006 LLVM_DEBUG({5007 llvm::dbgs() << "Did not expand macro \"" << ID->TokenText5008 << "\", because it was used ";5009 if (Args)5010 llvm::dbgs() << "with " << Args->size();5011 else5012 llvm::dbgs() << "without";5013 llvm::dbgs() << " arguments, which doesn't match any definition.\n";5014 });5015 Tokens->setPosition(Position);5016 FormatTok = ID;5017 }5018 }5019 5020 if (FormatTok->isNot(tok::comment)) {5021 distributeComments(Comments, FormatTok);5022 Comments.clear();5023 return;5024 }5025 5026 Comments.push_back(FormatTok);5027 } while (!eof());5028 5029 distributeComments(Comments, nullptr);5030 Comments.clear();5031}5032 5033namespace {5034template <typename Iterator>5035void pushTokens(Iterator Begin, Iterator End,5036 SmallVectorImpl<FormatToken *> &Into) {5037 for (auto I = Begin; I != End; ++I) {5038 Into.push_back(I->Tok);5039 for (const auto &Child : I->Children)5040 pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);5041 }5042}5043} // namespace5044 5045std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>5046UnwrappedLineParser::parseMacroCall() {5047 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;5048 assert(Line->Tokens.empty());5049 nextToken();5050 if (FormatTok->isNot(tok::l_paren))5051 return Args;5052 unsigned Position = Tokens->getPosition();5053 FormatToken *Tok = FormatTok;5054 nextToken();5055 Args.emplace();5056 auto ArgStart = std::prev(Line->Tokens.end());5057 5058 int Parens = 0;5059 do {5060 switch (FormatTok->Tok.getKind()) {5061 case tok::l_paren:5062 ++Parens;5063 nextToken();5064 break;5065 case tok::r_paren: {5066 if (Parens > 0) {5067 --Parens;5068 nextToken();5069 break;5070 }5071 Args->push_back({});5072 pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());5073 nextToken();5074 return Args;5075 }5076 case tok::comma: {5077 if (Parens > 0) {5078 nextToken();5079 break;5080 }5081 Args->push_back({});5082 pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());5083 nextToken();5084 ArgStart = std::prev(Line->Tokens.end());5085 break;5086 }5087 default:5088 nextToken();5089 break;5090 }5091 } while (!eof());5092 Line->Tokens.resize(1);5093 Tokens->setPosition(Position);5094 FormatTok = Tok;5095 return {};5096}5097 5098void UnwrappedLineParser::pushToken(FormatToken *Tok) {5099 Line->Tokens.push_back(UnwrappedLineNode(Tok));5100 if (AtEndOfPPLine) {5101 auto &Tok = *Line->Tokens.back().Tok;5102 Tok.MustBreakBefore = true;5103 Tok.MustBreakBeforeFinalized = true;5104 Tok.FirstAfterPPLine = true;5105 AtEndOfPPLine = false;5106 }5107}5108 5109} // end namespace format5110} // end namespace clang5111