Path: blob/main/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
35234 views
//===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file contains the implementation of the UnwrappedLineParser,10/// which turns a stream of tokens into UnwrappedLines.11///12//===----------------------------------------------------------------------===//1314#include "UnwrappedLineParser.h"15#include "FormatToken.h"16#include "FormatTokenLexer.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"2627#include <algorithm>28#include <utility>2930#define DEBUG_TYPE "format-parser"3132namespace clang {33namespace format {3435namespace {3637void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,38StringRef Prefix = "", bool PrintText = false) {39OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn40<< ")" << (Line.InPPDirective ? " MACRO" : "") << ": ";41bool NewLine = false;42for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),43E = Line.Tokens.end();44I != E; ++I) {45if (NewLine) {46OS << Prefix;47NewLine = false;48}49OS << I->Tok->Tok.getName() << "["50<< "T=" << (unsigned)I->Tok->getType()51<< ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText52<< "\"] ";53for (SmallVectorImpl<UnwrappedLine>::const_iterator54CI = I->Children.begin(),55CE = I->Children.end();56CI != CE; ++CI) {57OS << "\n";58printLine(OS, *CI, (Prefix + " ").str());59NewLine = true;60}61}62if (!NewLine)63OS << "\n";64}6566LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line) {67printLine(llvm::dbgs(), Line);68}6970class ScopedDeclarationState {71public:72ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack,73bool MustBeDeclaration)74: Line(Line), Stack(Stack) {75Line.MustBeDeclaration = MustBeDeclaration;76Stack.push_back(MustBeDeclaration);77}78~ScopedDeclarationState() {79Stack.pop_back();80if (!Stack.empty())81Line.MustBeDeclaration = Stack.back();82else83Line.MustBeDeclaration = true;84}8586private:87UnwrappedLine &Line;88llvm::BitVector &Stack;89};9091} // end anonymous namespace9293std::ostream &operator<<(std::ostream &Stream, const UnwrappedLine &Line) {94llvm::raw_os_ostream OS(Stream);95printLine(OS, Line);96return Stream;97}9899class ScopedLineState {100public:101ScopedLineState(UnwrappedLineParser &Parser,102bool SwitchToPreprocessorLines = false)103: Parser(Parser), OriginalLines(Parser.CurrentLines) {104if (SwitchToPreprocessorLines)105Parser.CurrentLines = &Parser.PreprocessorDirectives;106else if (!Parser.Line->Tokens.empty())107Parser.CurrentLines = &Parser.Line->Tokens.back().Children;108PreBlockLine = std::move(Parser.Line);109Parser.Line = std::make_unique<UnwrappedLine>();110Parser.Line->Level = PreBlockLine->Level;111Parser.Line->PPLevel = PreBlockLine->PPLevel;112Parser.Line->InPPDirective = PreBlockLine->InPPDirective;113Parser.Line->InMacroBody = PreBlockLine->InMacroBody;114Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel;115}116117~ScopedLineState() {118if (!Parser.Line->Tokens.empty())119Parser.addUnwrappedLine();120assert(Parser.Line->Tokens.empty());121Parser.Line = std::move(PreBlockLine);122if (Parser.CurrentLines == &Parser.PreprocessorDirectives)123Parser.MustBreakBeforeNextToken = true;124Parser.CurrentLines = OriginalLines;125}126127private:128UnwrappedLineParser &Parser;129130std::unique_ptr<UnwrappedLine> PreBlockLine;131SmallVectorImpl<UnwrappedLine> *OriginalLines;132};133134class CompoundStatementIndenter {135public:136CompoundStatementIndenter(UnwrappedLineParser *Parser,137const FormatStyle &Style, unsigned &LineLevel)138: CompoundStatementIndenter(Parser, LineLevel,139Style.BraceWrapping.AfterControlStatement,140Style.BraceWrapping.IndentBraces) {}141CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel,142bool WrapBrace, bool IndentBrace)143: LineLevel(LineLevel), OldLineLevel(LineLevel) {144if (WrapBrace)145Parser->addUnwrappedLine();146if (IndentBrace)147++LineLevel;148}149~CompoundStatementIndenter() { LineLevel = OldLineLevel; }150151private:152unsigned &LineLevel;153unsigned OldLineLevel;154};155156UnwrappedLineParser::UnwrappedLineParser(157SourceManager &SourceMgr, const FormatStyle &Style,158const AdditionalKeywords &Keywords, unsigned FirstStartColumn,159ArrayRef<FormatToken *> Tokens, UnwrappedLineConsumer &Callback,160llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,161IdentifierTable &IdentTable)162: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),163CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()),164LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),165CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),166Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),167IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None168? IG_Rejected169: IG_Inited),170IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn),171Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {172assert(IsCpp == LangOpts.CXXOperatorNames);173}174175void UnwrappedLineParser::reset() {176PPBranchLevel = -1;177IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None178? IG_Rejected179: IG_Inited;180IncludeGuardToken = nullptr;181Line.reset(new UnwrappedLine);182CommentsBeforeNextToken.clear();183FormatTok = nullptr;184MustBreakBeforeNextToken = false;185IsDecltypeAutoFunction = false;186PreprocessorDirectives.clear();187CurrentLines = &Lines;188DeclarationScopeStack.clear();189NestedTooDeep.clear();190NestedLambdas.clear();191PPStack.clear();192Line->FirstStartColumn = FirstStartColumn;193194if (!Unexpanded.empty())195for (FormatToken *Token : AllTokens)196Token->MacroCtx.reset();197CurrentExpandedLines.clear();198ExpandedLines.clear();199Unexpanded.clear();200InExpansion = false;201Reconstruct.reset();202}203204void UnwrappedLineParser::parse() {205IndexedTokenSource TokenSource(AllTokens);206Line->FirstStartColumn = FirstStartColumn;207do {208LLVM_DEBUG(llvm::dbgs() << "----\n");209reset();210Tokens = &TokenSource;211TokenSource.reset();212213readToken();214parseFile();215216// If we found an include guard then all preprocessor directives (other than217// the guard) are over-indented by one.218if (IncludeGuard == IG_Found) {219for (auto &Line : Lines)220if (Line.InPPDirective && Line.Level > 0)221--Line.Level;222}223224// Create line with eof token.225assert(eof());226pushToken(FormatTok);227addUnwrappedLine();228229// In a first run, format everything with the lines containing macro calls230// replaced by the expansion.231if (!ExpandedLines.empty()) {232LLVM_DEBUG(llvm::dbgs() << "Expanded lines:\n");233for (const auto &Line : Lines) {234if (!Line.Tokens.empty()) {235auto it = ExpandedLines.find(Line.Tokens.begin()->Tok);236if (it != ExpandedLines.end()) {237for (const auto &Expanded : it->second) {238LLVM_DEBUG(printDebugInfo(Expanded));239Callback.consumeUnwrappedLine(Expanded);240}241continue;242}243}244LLVM_DEBUG(printDebugInfo(Line));245Callback.consumeUnwrappedLine(Line);246}247Callback.finishRun();248}249250LLVM_DEBUG(llvm::dbgs() << "Unwrapped lines:\n");251for (const UnwrappedLine &Line : Lines) {252LLVM_DEBUG(printDebugInfo(Line));253Callback.consumeUnwrappedLine(Line);254}255Callback.finishRun();256Lines.clear();257while (!PPLevelBranchIndex.empty() &&258PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {259PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);260PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);261}262if (!PPLevelBranchIndex.empty()) {263++PPLevelBranchIndex.back();264assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());265assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());266}267} while (!PPLevelBranchIndex.empty());268}269270void UnwrappedLineParser::parseFile() {271// The top-level context in a file always has declarations, except for pre-272// processor directives and JavaScript files.273bool MustBeDeclaration = !Line->InPPDirective && !Style.isJavaScript();274ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,275MustBeDeclaration);276if (Style.Language == FormatStyle::LK_TextProto)277parseBracedList();278else279parseLevel();280// Make sure to format the remaining tokens.281//282// LK_TextProto is special since its top-level is parsed as the body of a283// braced list, which does not necessarily have natural line separators such284// as a semicolon. Comments after the last entry that have been determined to285// not belong to that line, as in:286// key: value287// // endfile comment288// do not have a chance to be put on a line of their own until this point.289// Here we add this newline before end-of-file comments.290if (Style.Language == FormatStyle::LK_TextProto &&291!CommentsBeforeNextToken.empty()) {292addUnwrappedLine();293}294flushComments(true);295addUnwrappedLine();296}297298void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {299do {300switch (FormatTok->Tok.getKind()) {301case tok::l_brace:302return;303default:304if (FormatTok->is(Keywords.kw_where)) {305addUnwrappedLine();306nextToken();307parseCSharpGenericTypeConstraint();308break;309}310nextToken();311break;312}313} while (!eof());314}315316void UnwrappedLineParser::parseCSharpAttribute() {317int UnpairedSquareBrackets = 1;318do {319switch (FormatTok->Tok.getKind()) {320case tok::r_square:321nextToken();322--UnpairedSquareBrackets;323if (UnpairedSquareBrackets == 0) {324addUnwrappedLine();325return;326}327break;328case tok::l_square:329++UnpairedSquareBrackets;330nextToken();331break;332default:333nextToken();334break;335}336} while (!eof());337}338339bool UnwrappedLineParser::precededByCommentOrPPDirective() const {340if (!Lines.empty() && Lines.back().InPPDirective)341return true;342343const FormatToken *Previous = Tokens->getPreviousToken();344return Previous && Previous->is(tok::comment) &&345(Previous->IsMultiline || Previous->NewlinesBefore > 0);346}347348/// \brief Parses a level, that is ???.349/// \param OpeningBrace Opening brace (\p nullptr if absent) of that level.350/// \param IfKind The \p if statement kind in the level.351/// \param IfLeftBrace The left brace of the \p if block in the level.352/// \returns true if a simple block of if/else/for/while, or false otherwise.353/// (A simple block has a single statement.)354bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,355IfStmtKind *IfKind,356FormatToken **IfLeftBrace) {357const bool InRequiresExpression =358OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);359const bool IsPrecededByCommentOrPPDirective =360!Style.RemoveBracesLLVM || precededByCommentOrPPDirective();361FormatToken *IfLBrace = nullptr;362bool HasDoWhile = false;363bool HasLabel = false;364unsigned StatementCount = 0;365bool SwitchLabelEncountered = false;366367do {368if (FormatTok->isAttribute()) {369nextToken();370if (FormatTok->is(tok::l_paren))371parseParens();372continue;373}374tok::TokenKind Kind = FormatTok->Tok.getKind();375if (FormatTok->is(TT_MacroBlockBegin))376Kind = tok::l_brace;377else if (FormatTok->is(TT_MacroBlockEnd))378Kind = tok::r_brace;379380auto ParseDefault = [this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,381&HasLabel, &StatementCount] {382parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,383HasDoWhile ? nullptr : &HasDoWhile,384HasLabel ? nullptr : &HasLabel);385++StatementCount;386assert(StatementCount > 0 && "StatementCount overflow!");387};388389switch (Kind) {390case tok::comment:391nextToken();392addUnwrappedLine();393break;394case tok::l_brace:395if (InRequiresExpression) {396FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);397} else if (FormatTok->Previous &&398FormatTok->Previous->ClosesRequiresClause) {399// We need the 'default' case here to correctly parse a function400// l_brace.401ParseDefault();402continue;403}404if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {405if (tryToParseBracedList())406continue;407FormatTok->setFinalizedType(TT_BlockLBrace);408}409parseBlock();410++StatementCount;411assert(StatementCount > 0 && "StatementCount overflow!");412addUnwrappedLine();413break;414case tok::r_brace:415if (OpeningBrace) {416if (!Style.RemoveBracesLLVM || Line->InPPDirective ||417!OpeningBrace->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {418return false;419}420if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||421HasDoWhile || IsPrecededByCommentOrPPDirective ||422precededByCommentOrPPDirective()) {423return false;424}425const FormatToken *Next = Tokens->peekNextToken();426if (Next->is(tok::comment) && Next->NewlinesBefore == 0)427return false;428if (IfLeftBrace)429*IfLeftBrace = IfLBrace;430return true;431}432nextToken();433addUnwrappedLine();434break;435case tok::kw_default: {436unsigned StoredPosition = Tokens->getPosition();437auto *Next = Tokens->getNextNonComment();438FormatTok = Tokens->setPosition(StoredPosition);439if (!Next->isOneOf(tok::colon, tok::arrow)) {440// default not followed by `:` or `->` is not a case label; treat it441// like an identifier.442parseStructuralElement();443break;444}445// Else, if it is 'default:', fall through to the case handling.446[[fallthrough]];447}448case tok::kw_case:449if (Style.Language == FormatStyle::LK_Proto || Style.isVerilog() ||450(Style.isJavaScript() && Line->MustBeDeclaration)) {451// Proto: there are no switch/case statements452// Verilog: Case labels don't have this word. We handle case453// labels including default in TokenAnnotator.454// JavaScript: A 'case: string' style field declaration.455ParseDefault();456break;457}458if (!SwitchLabelEncountered &&459(Style.IndentCaseLabels ||460(OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||461(Line->InPPDirective && Line->Level == 1))) {462++Line->Level;463}464SwitchLabelEncountered = true;465parseStructuralElement();466break;467case tok::l_square:468if (Style.isCSharp()) {469nextToken();470parseCSharpAttribute();471break;472}473if (handleCppAttributes())474break;475[[fallthrough]];476default:477ParseDefault();478break;479}480} while (!eof());481482return false;483}484485void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {486// We'll parse forward through the tokens until we hit487// a closing brace or eof - note that getNextToken() will488// parse macros, so this will magically work inside macro489// definitions, too.490unsigned StoredPosition = Tokens->getPosition();491FormatToken *Tok = FormatTok;492const FormatToken *PrevTok = Tok->Previous;493// Keep a stack of positions of lbrace tokens. We will494// update information about whether an lbrace starts a495// braced init list or a different block during the loop.496struct StackEntry {497FormatToken *Tok;498const FormatToken *PrevTok;499};500SmallVector<StackEntry, 8> LBraceStack;501assert(Tok->is(tok::l_brace));502503do {504auto *NextTok = Tokens->getNextNonComment();505506if (!Line->InMacroBody && !Style.isTableGen()) {507// Skip PPDirective lines and comments.508while (NextTok->is(tok::hash)) {509NextTok = Tokens->getNextToken();510if (NextTok->is(tok::pp_not_keyword))511break;512do {513NextTok = Tokens->getNextToken();514} while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));515516while (NextTok->is(tok::comment))517NextTok = Tokens->getNextToken();518}519}520521switch (Tok->Tok.getKind()) {522case tok::l_brace:523if (Style.isJavaScript() && PrevTok) {524if (PrevTok->isOneOf(tok::colon, tok::less)) {525// A ':' indicates this code is in a type, or a braced list526// following a label in an object literal ({a: {b: 1}}).527// A '<' could be an object used in a comparison, but that is nonsense528// code (can never return true), so more likely it is a generic type529// argument (`X<{a: string; b: number}>`).530// The code below could be confused by semicolons between the531// individual members in a type member list, which would normally532// trigger BK_Block. In both cases, this must be parsed as an inline533// braced init.534Tok->setBlockKind(BK_BracedInit);535} else if (PrevTok->is(tok::r_paren)) {536// `) { }` can only occur in function or method declarations in JS.537Tok->setBlockKind(BK_Block);538}539} else {540Tok->setBlockKind(BK_Unknown);541}542LBraceStack.push_back({Tok, PrevTok});543break;544case tok::r_brace:545if (LBraceStack.empty())546break;547if (auto *LBrace = LBraceStack.back().Tok; LBrace->is(BK_Unknown)) {548bool ProbablyBracedList = false;549if (Style.Language == FormatStyle::LK_Proto) {550ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);551} else if (LBrace->isNot(TT_EnumLBrace)) {552// Using OriginalColumn to distinguish between ObjC methods and553// binary operators is a bit hacky.554bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&555NextTok->OriginalColumn == 0;556557// Try to detect a braced list. Note that regardless how we mark inner558// braces here, we will overwrite the BlockKind later if we parse a559// braced list (where all blocks inside are by default braced lists),560// or when we explicitly detect blocks (for example while parsing561// lambdas).562563// If we already marked the opening brace as braced list, the closing564// must also be part of it.565ProbablyBracedList = LBrace->is(TT_BracedListLBrace);566567ProbablyBracedList = ProbablyBracedList ||568(Style.isJavaScript() &&569NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,570Keywords.kw_as));571ProbablyBracedList =572ProbablyBracedList || (IsCpp && (PrevTok->Tok.isLiteral() ||573NextTok->is(tok::l_paren)));574575// If there is a comma, semicolon or right paren after the closing576// brace, we assume this is a braced initializer list.577// FIXME: Some of these do not apply to JS, e.g. "} {" can never be a578// braced list in JS.579ProbablyBracedList =580ProbablyBracedList ||581NextTok->isOneOf(tok::comma, tok::period, tok::colon,582tok::r_paren, tok::r_square, tok::ellipsis);583584// Distinguish between braced list in a constructor initializer list585// followed by constructor body, or just adjacent blocks.586ProbablyBracedList =587ProbablyBracedList ||588(NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&589LBraceStack.back().PrevTok->isOneOf(tok::identifier,590tok::greater));591592ProbablyBracedList =593ProbablyBracedList ||594(NextTok->is(tok::identifier) &&595!PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace));596597ProbablyBracedList = ProbablyBracedList ||598(NextTok->is(tok::semi) &&599(!ExpectClassBody || LBraceStack.size() != 1));600601ProbablyBracedList =602ProbablyBracedList ||603(NextTok->isBinaryOperator() && !NextIsObjCMethod);604605if (!Style.isCSharp() && NextTok->is(tok::l_square)) {606// We can have an array subscript after a braced init607// list, but C++11 attributes are expected after blocks.608NextTok = Tokens->getNextToken();609ProbablyBracedList = NextTok->isNot(tok::l_square);610}611612// Cpp macro definition body that is a nonempty braced list or block:613if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&614!FormatTok->Previous && NextTok->is(tok::eof) &&615// A statement can end with only `;` (simple statement), a block616// closing brace (compound statement), or `:` (label statement).617// If PrevTok is a block opening brace, Tok ends an empty block.618!PrevTok->isOneOf(tok::semi, BK_Block, tok::colon)) {619ProbablyBracedList = true;620}621}622const auto BlockKind = ProbablyBracedList ? BK_BracedInit : BK_Block;623Tok->setBlockKind(BlockKind);624LBrace->setBlockKind(BlockKind);625}626LBraceStack.pop_back();627break;628case tok::identifier:629if (Tok->isNot(TT_StatementMacro))630break;631[[fallthrough]];632case tok::at:633case tok::semi:634case tok::kw_if:635case tok::kw_while:636case tok::kw_for:637case tok::kw_switch:638case tok::kw_try:639case tok::kw___try:640if (!LBraceStack.empty() && LBraceStack.back().Tok->is(BK_Unknown))641LBraceStack.back().Tok->setBlockKind(BK_Block);642break;643default:644break;645}646647PrevTok = Tok;648Tok = NextTok;649} while (Tok->isNot(tok::eof) && !LBraceStack.empty());650651// Assume other blocks for all unclosed opening braces.652for (const auto &Entry : LBraceStack)653if (Entry.Tok->is(BK_Unknown))654Entry.Tok->setBlockKind(BK_Block);655656FormatTok = Tokens->setPosition(StoredPosition);657}658659// Sets the token type of the directly previous right brace.660void UnwrappedLineParser::setPreviousRBraceType(TokenType Type) {661if (auto Prev = FormatTok->getPreviousNonComment();662Prev && Prev->is(tok::r_brace)) {663Prev->setFinalizedType(Type);664}665}666667template <class T>668static inline void hash_combine(std::size_t &seed, const T &v) {669std::hash<T> hasher;670seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);671}672673size_t UnwrappedLineParser::computePPHash() const {674size_t h = 0;675for (const auto &i : PPStack) {676hash_combine(h, size_t(i.Kind));677hash_combine(h, i.Line);678}679return h;680}681682// Checks whether \p ParsedLine might fit on a single line. If \p OpeningBrace683// is not null, subtracts its length (plus the preceding space) when computing684// the length of \p ParsedLine. We must clone the tokens of \p ParsedLine before685// running the token annotator on it so that we can restore them afterward.686bool UnwrappedLineParser::mightFitOnOneLine(687UnwrappedLine &ParsedLine, const FormatToken *OpeningBrace) const {688const auto ColumnLimit = Style.ColumnLimit;689if (ColumnLimit == 0)690return true;691692auto &Tokens = ParsedLine.Tokens;693assert(!Tokens.empty());694695const auto *LastToken = Tokens.back().Tok;696assert(LastToken);697698SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());699700int Index = 0;701for (const auto &Token : Tokens) {702assert(Token.Tok);703auto &SavedToken = SavedTokens[Index++];704SavedToken.Tok = new FormatToken;705SavedToken.Tok->copyFrom(*Token.Tok);706SavedToken.Children = std::move(Token.Children);707}708709AnnotatedLine Line(ParsedLine);710assert(Line.Last == LastToken);711712TokenAnnotator Annotator(Style, Keywords);713Annotator.annotate(Line);714Annotator.calculateFormattingInformation(Line);715716auto Length = LastToken->TotalLength;717if (OpeningBrace) {718assert(OpeningBrace != Tokens.front().Tok);719if (auto Prev = OpeningBrace->Previous;720Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {721Length -= ColumnLimit;722}723Length -= OpeningBrace->TokenText.size() + 1;724}725726if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {727assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));728Length -= FirstToken->TokenText.size() + 1;729}730731Index = 0;732for (auto &Token : Tokens) {733const auto &SavedToken = SavedTokens[Index++];734Token.Tok->copyFrom(*SavedToken.Tok);735Token.Children = std::move(SavedToken.Children);736delete SavedToken.Tok;737}738739// If these change PPLevel needs to be used for get correct indentation.740assert(!Line.InMacroBody);741assert(!Line.InPPDirective);742return Line.Level * Style.IndentWidth + Length <= ColumnLimit;743}744745FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration,746unsigned AddLevels, bool MunchSemi,747bool KeepBraces,748IfStmtKind *IfKind,749bool UnindentWhitesmithsBraces) {750auto HandleVerilogBlockLabel = [this]() {751// ":" name752if (Style.isVerilog() && FormatTok->is(tok::colon)) {753nextToken();754if (Keywords.isVerilogIdentifier(*FormatTok))755nextToken();756}757};758759// Whether this is a Verilog-specific block that has a special header like a760// module.761const bool VerilogHierarchy =762Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);763assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||764(Style.isVerilog() &&765(Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&766"'{' or macro block token expected");767FormatToken *Tok = FormatTok;768const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);769auto Index = CurrentLines->size();770const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);771FormatTok->setBlockKind(BK_Block);772773// For Whitesmiths mode, jump to the next level prior to skipping over the774// braces.775if (!VerilogHierarchy && AddLevels > 0 &&776Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {777++Line->Level;778}779780size_t PPStartHash = computePPHash();781782const unsigned InitialLevel = Line->Level;783if (VerilogHierarchy) {784AddLevels += parseVerilogHierarchyHeader();785} else {786nextToken(/*LevelDifference=*/AddLevels);787HandleVerilogBlockLabel();788}789790// Bail out if there are too many levels. Otherwise, the stack might overflow.791if (Line->Level > 300)792return nullptr;793794if (MacroBlock && FormatTok->is(tok::l_paren))795parseParens();796797size_t NbPreprocessorDirectives =798!parsingPPDirective() ? PreprocessorDirectives.size() : 0;799addUnwrappedLine();800size_t OpeningLineIndex =801CurrentLines->empty()802? (UnwrappedLine::kInvalidIndex)803: (CurrentLines->size() - 1 - NbPreprocessorDirectives);804805// Whitesmiths is weird here. The brace needs to be indented for the namespace806// block, but the block itself may not be indented depending on the style807// settings. This allows the format to back up one level in those cases.808if (UnindentWhitesmithsBraces)809--Line->Level;810811ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,812MustBeDeclaration);813if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)814Line->Level += AddLevels;815816FormatToken *IfLBrace = nullptr;817const bool SimpleBlock = parseLevel(Tok, IfKind, &IfLBrace);818819if (eof())820return IfLBrace;821822if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)823: FormatTok->isNot(tok::r_brace)) {824Line->Level = InitialLevel;825FormatTok->setBlockKind(BK_Block);826return IfLBrace;827}828829if (FormatTok->is(tok::r_brace)) {830FormatTok->setBlockKind(BK_Block);831if (Tok->is(TT_NamespaceLBrace))832FormatTok->setFinalizedType(TT_NamespaceRBrace);833}834835const bool IsFunctionRBrace =836FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);837838auto RemoveBraces = [=]() mutable {839if (!SimpleBlock)840return false;841assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));842assert(FormatTok->is(tok::r_brace));843const bool WrappedOpeningBrace = !Tok->Previous;844if (WrappedOpeningBrace && FollowedByComment)845return false;846const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;847if (KeepBraces && !HasRequiredIfBraces)848return false;849if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {850const FormatToken *Previous = Tokens->getPreviousToken();851assert(Previous);852if (Previous->is(tok::r_brace) && !Previous->Optional)853return false;854}855assert(!CurrentLines->empty());856auto &LastLine = CurrentLines->back();857if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))858return false;859if (Tok->is(TT_ElseLBrace))860return true;861if (WrappedOpeningBrace) {862assert(Index > 0);863--Index; // The line above the wrapped l_brace.864Tok = nullptr;865}866return mightFitOnOneLine((*CurrentLines)[Index], Tok);867};868if (RemoveBraces()) {869Tok->MatchingParen = FormatTok;870FormatTok->MatchingParen = Tok;871}872873size_t PPEndHash = computePPHash();874875// Munch the closing brace.876nextToken(/*LevelDifference=*/-AddLevels);877878// When this is a function block and there is an unnecessary semicolon879// afterwards then mark it as optional (so the RemoveSemi pass can get rid of880// it later).881if (Style.RemoveSemicolon && IsFunctionRBrace) {882while (FormatTok->is(tok::semi)) {883FormatTok->Optional = true;884nextToken();885}886}887888HandleVerilogBlockLabel();889890if (MacroBlock && FormatTok->is(tok::l_paren))891parseParens();892893Line->Level = InitialLevel;894895if (FormatTok->is(tok::kw_noexcept)) {896// A noexcept in a requires expression.897nextToken();898}899900if (FormatTok->is(tok::arrow)) {901// Following the } or noexcept we can find a trailing return type arrow902// as part of an implicit conversion constraint.903nextToken();904parseStructuralElement();905}906907if (MunchSemi && FormatTok->is(tok::semi))908nextToken();909910if (PPStartHash == PPEndHash) {911Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;912if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {913// Update the opening line to add the forward reference as well914(*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =915CurrentLines->size() - 1;916}917}918919return IfLBrace;920}921922static bool isGoogScope(const UnwrappedLine &Line) {923// FIXME: Closure-library specific stuff should not be hard-coded but be924// configurable.925if (Line.Tokens.size() < 4)926return false;927auto I = Line.Tokens.begin();928if (I->Tok->TokenText != "goog")929return false;930++I;931if (I->Tok->isNot(tok::period))932return false;933++I;934if (I->Tok->TokenText != "scope")935return false;936++I;937return I->Tok->is(tok::l_paren);938}939940static bool isIIFE(const UnwrappedLine &Line,941const AdditionalKeywords &Keywords) {942// Look for the start of an immediately invoked anonymous function.943// https://en.wikipedia.org/wiki/Immediately-invoked_function_expression944// This is commonly done in JavaScript to create a new, anonymous scope.945// Example: (function() { ... })()946if (Line.Tokens.size() < 3)947return false;948auto I = Line.Tokens.begin();949if (I->Tok->isNot(tok::l_paren))950return false;951++I;952if (I->Tok->isNot(Keywords.kw_function))953return false;954++I;955return I->Tok->is(tok::l_paren);956}957958static bool ShouldBreakBeforeBrace(const FormatStyle &Style,959const FormatToken &InitialToken) {960tok::TokenKind Kind = InitialToken.Tok.getKind();961if (InitialToken.is(TT_NamespaceMacro))962Kind = tok::kw_namespace;963964switch (Kind) {965case tok::kw_namespace:966return Style.BraceWrapping.AfterNamespace;967case tok::kw_class:968return Style.BraceWrapping.AfterClass;969case tok::kw_union:970return Style.BraceWrapping.AfterUnion;971case tok::kw_struct:972return Style.BraceWrapping.AfterStruct;973case tok::kw_enum:974return Style.BraceWrapping.AfterEnum;975default:976return false;977}978}979980void UnwrappedLineParser::parseChildBlock() {981assert(FormatTok->is(tok::l_brace));982FormatTok->setBlockKind(BK_Block);983const FormatToken *OpeningBrace = FormatTok;984nextToken();985{986bool SkipIndent = (Style.isJavaScript() &&987(isGoogScope(*Line) || isIIFE(*Line, Keywords)));988ScopedLineState LineState(*this);989ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,990/*MustBeDeclaration=*/false);991Line->Level += SkipIndent ? 0 : 1;992parseLevel(OpeningBrace);993flushComments(isOnNewLine(*FormatTok));994Line->Level -= SkipIndent ? 0 : 1;995}996nextToken();997}998999void UnwrappedLineParser::parsePPDirective() {1000assert(FormatTok->is(tok::hash) && "'#' expected");1001ScopedMacroState MacroState(*Line, Tokens, FormatTok);10021003nextToken();10041005if (!FormatTok->Tok.getIdentifierInfo()) {1006parsePPUnknown();1007return;1008}10091010switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {1011case tok::pp_define:1012parsePPDefine();1013return;1014case tok::pp_if:1015parsePPIf(/*IfDef=*/false);1016break;1017case tok::pp_ifdef:1018case tok::pp_ifndef:1019parsePPIf(/*IfDef=*/true);1020break;1021case tok::pp_else:1022case tok::pp_elifdef:1023case tok::pp_elifndef:1024case tok::pp_elif:1025parsePPElse();1026break;1027case tok::pp_endif:1028parsePPEndIf();1029break;1030case tok::pp_pragma:1031parsePPPragma();1032break;1033default:1034parsePPUnknown();1035break;1036}1037}10381039void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {1040size_t Line = CurrentLines->size();1041if (CurrentLines == &PreprocessorDirectives)1042Line += Lines.size();10431044if (Unreachable ||1045(!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) {1046PPStack.push_back({PP_Unreachable, Line});1047} else {1048PPStack.push_back({PP_Conditional, Line});1049}1050}10511052void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {1053++PPBranchLevel;1054assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());1055if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {1056PPLevelBranchIndex.push_back(0);1057PPLevelBranchCount.push_back(0);1058}1059PPChainBranchIndex.push(Unreachable ? -1 : 0);1060bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;1061conditionalCompilationCondition(Unreachable || Skip);1062}10631064void UnwrappedLineParser::conditionalCompilationAlternative() {1065if (!PPStack.empty())1066PPStack.pop_back();1067assert(PPBranchLevel < (int)PPLevelBranchIndex.size());1068if (!PPChainBranchIndex.empty())1069++PPChainBranchIndex.top();1070conditionalCompilationCondition(1071PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&1072PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());1073}10741075void UnwrappedLineParser::conditionalCompilationEnd() {1076assert(PPBranchLevel < (int)PPLevelBranchIndex.size());1077if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {1078if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel])1079PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;1080}1081// Guard against #endif's without #if.1082if (PPBranchLevel > -1)1083--PPBranchLevel;1084if (!PPChainBranchIndex.empty())1085PPChainBranchIndex.pop();1086if (!PPStack.empty())1087PPStack.pop_back();1088}10891090void UnwrappedLineParser::parsePPIf(bool IfDef) {1091bool IfNDef = FormatTok->is(tok::pp_ifndef);1092nextToken();1093bool Unreachable = false;1094if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0"))1095Unreachable = true;1096if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")1097Unreachable = true;1098conditionalCompilationStart(Unreachable);1099FormatToken *IfCondition = FormatTok;1100// If there's a #ifndef on the first line, and the only lines before it are1101// comments, it could be an include guard.1102bool MaybeIncludeGuard = IfNDef;1103if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {1104for (auto &Line : Lines) {1105if (Line.Tokens.front().Tok->isNot(tok::comment)) {1106MaybeIncludeGuard = false;1107IncludeGuard = IG_Rejected;1108break;1109}1110}1111}1112--PPBranchLevel;1113parsePPUnknown();1114++PPBranchLevel;1115if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {1116IncludeGuard = IG_IfNdefed;1117IncludeGuardToken = IfCondition;1118}1119}11201121void UnwrappedLineParser::parsePPElse() {1122// If a potential include guard has an #else, it's not an include guard.1123if (IncludeGuard == IG_Defined && PPBranchLevel == 0)1124IncludeGuard = IG_Rejected;1125// Don't crash when there is an #else without an #if.1126assert(PPBranchLevel >= -1);1127if (PPBranchLevel == -1)1128conditionalCompilationStart(/*Unreachable=*/true);1129conditionalCompilationAlternative();1130--PPBranchLevel;1131parsePPUnknown();1132++PPBranchLevel;1133}11341135void UnwrappedLineParser::parsePPEndIf() {1136conditionalCompilationEnd();1137parsePPUnknown();1138// If the #endif of a potential include guard is the last thing in the file,1139// then we found an include guard.1140if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&1141Style.IndentPPDirectives != FormatStyle::PPDIS_None) {1142IncludeGuard = IG_Found;1143}1144}11451146void UnwrappedLineParser::parsePPDefine() {1147nextToken();11481149if (!FormatTok->Tok.getIdentifierInfo()) {1150IncludeGuard = IG_Rejected;1151IncludeGuardToken = nullptr;1152parsePPUnknown();1153return;1154}11551156if (IncludeGuard == IG_IfNdefed &&1157IncludeGuardToken->TokenText == FormatTok->TokenText) {1158IncludeGuard = IG_Defined;1159IncludeGuardToken = nullptr;1160for (auto &Line : Lines) {1161if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {1162IncludeGuard = IG_Rejected;1163break;1164}1165}1166}11671168// In the context of a define, even keywords should be treated as normal1169// identifiers. Setting the kind to identifier is not enough, because we need1170// to treat additional keywords like __except as well, which are already1171// identifiers. Setting the identifier info to null interferes with include1172// guard processing above, and changes preprocessing nesting.1173FormatTok->Tok.setKind(tok::identifier);1174FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);1175nextToken();1176if (FormatTok->Tok.getKind() == tok::l_paren &&1177!FormatTok->hasWhitespaceBefore()) {1178parseParens();1179}1180if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)1181Line->Level += PPBranchLevel + 1;1182addUnwrappedLine();1183++Line->Level;11841185Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);1186assert((int)Line->PPLevel >= 0);1187Line->InMacroBody = true;11881189if (Style.SkipMacroDefinitionBody) {1190while (!eof()) {1191FormatTok->Finalized = true;1192FormatTok = Tokens->getNextToken();1193}1194addUnwrappedLine();1195return;1196}11971198// Errors during a preprocessor directive can only affect the layout of the1199// preprocessor directive, and thus we ignore them. An alternative approach1200// would be to use the same approach we use on the file level (no1201// re-indentation if there was a structural error) within the macro1202// definition.1203parseFile();1204}12051206void UnwrappedLineParser::parsePPPragma() {1207Line->InPragmaDirective = true;1208parsePPUnknown();1209}12101211void UnwrappedLineParser::parsePPUnknown() {1212do {1213nextToken();1214} while (!eof());1215if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)1216Line->Level += PPBranchLevel + 1;1217addUnwrappedLine();1218}12191220// Here we exclude certain tokens that are not usually the first token in an1221// unwrapped line. This is used in attempt to distinguish macro calls without1222// trailing semicolons from other constructs split to several lines.1223static bool tokenCanStartNewLine(const FormatToken &Tok) {1224// Semicolon can be a null-statement, l_square can be a start of a macro or1225// a C++11 attribute, but this doesn't seem to be common.1226return !Tok.isOneOf(tok::semi, tok::l_brace,1227// Tokens that can only be used as binary operators and a1228// part of overloaded operator names.1229tok::period, tok::periodstar, tok::arrow, tok::arrowstar,1230tok::less, tok::greater, tok::slash, tok::percent,1231tok::lessless, tok::greatergreater, tok::equal,1232tok::plusequal, tok::minusequal, tok::starequal,1233tok::slashequal, tok::percentequal, tok::ampequal,1234tok::pipeequal, tok::caretequal, tok::greatergreaterequal,1235tok::lesslessequal,1236// Colon is used in labels, base class lists, initializer1237// lists, range-based for loops, ternary operator, but1238// should never be the first token in an unwrapped line.1239tok::colon,1240// 'noexcept' is a trailing annotation.1241tok::kw_noexcept);1242}12431244static bool mustBeJSIdent(const AdditionalKeywords &Keywords,1245const FormatToken *FormatTok) {1246// FIXME: This returns true for C/C++ keywords like 'struct'.1247return FormatTok->is(tok::identifier) &&1248(!FormatTok->Tok.getIdentifierInfo() ||1249!FormatTok->isOneOf(1250Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async,1251Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally,1252Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,1253Keywords.kw_let, Keywords.kw_var, tok::kw_const,1254Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,1255Keywords.kw_instanceof, Keywords.kw_interface,1256Keywords.kw_override, Keywords.kw_throws, Keywords.kw_from));1257}12581259static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,1260const FormatToken *FormatTok) {1261return FormatTok->Tok.isLiteral() ||1262FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||1263mustBeJSIdent(Keywords, FormatTok);1264}12651266// isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement1267// when encountered after a value (see mustBeJSIdentOrValue).1268static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,1269const FormatToken *FormatTok) {1270return FormatTok->isOneOf(1271tok::kw_return, Keywords.kw_yield,1272// conditionals1273tok::kw_if, tok::kw_else,1274// loops1275tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,1276// switch/case1277tok::kw_switch, tok::kw_case,1278// exceptions1279tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,1280// declaration1281tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,1282Keywords.kw_async, Keywords.kw_function,1283// import/export1284Keywords.kw_import, tok::kw_export);1285}12861287// Checks whether a token is a type in K&R C (aka C78).1288static bool isC78Type(const FormatToken &Tok) {1289return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,1290tok::kw_unsigned, tok::kw_float, tok::kw_double,1291tok::identifier);1292}12931294// This function checks whether a token starts the first parameter declaration1295// in a K&R C (aka C78) function definition, e.g.:1296// int f(a, b)1297// short a, b;1298// {1299// return a + b;1300// }1301static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next,1302const FormatToken *FuncName) {1303assert(Tok);1304assert(Next);1305assert(FuncName);13061307if (FuncName->isNot(tok::identifier))1308return false;13091310const FormatToken *Prev = FuncName->Previous;1311if (!Prev || (Prev->isNot(tok::star) && !isC78Type(*Prev)))1312return false;13131314if (!isC78Type(*Tok) &&1315!Tok->isOneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {1316return false;1317}13181319if (Next->isNot(tok::star) && !Next->Tok.getIdentifierInfo())1320return false;13211322Tok = Tok->Previous;1323if (!Tok || Tok->isNot(tok::r_paren))1324return false;13251326Tok = Tok->Previous;1327if (!Tok || Tok->isNot(tok::identifier))1328return false;13291330return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);1331}13321333bool UnwrappedLineParser::parseModuleImport() {1334assert(FormatTok->is(Keywords.kw_import) && "'import' expected");13351336if (auto Token = Tokens->peekNextToken(/*SkipComment=*/true);1337!Token->Tok.getIdentifierInfo() &&1338!Token->isOneOf(tok::colon, tok::less, tok::string_literal)) {1339return false;1340}13411342nextToken();1343while (!eof()) {1344if (FormatTok->is(tok::colon)) {1345FormatTok->setFinalizedType(TT_ModulePartitionColon);1346}1347// Handle import <foo/bar.h> as we would an include statement.1348else if (FormatTok->is(tok::less)) {1349nextToken();1350while (!FormatTok->isOneOf(tok::semi, tok::greater, tok::eof)) {1351// Mark tokens up to the trailing line comments as implicit string1352// literals.1353if (FormatTok->isNot(tok::comment) &&1354!FormatTok->TokenText.starts_with("//")) {1355FormatTok->setFinalizedType(TT_ImplicitStringLiteral);1356}1357nextToken();1358}1359}1360if (FormatTok->is(tok::semi)) {1361nextToken();1362break;1363}1364nextToken();1365}13661367addUnwrappedLine();1368return true;1369}13701371// readTokenWithJavaScriptASI reads the next token and terminates the current1372// line if JavaScript Automatic Semicolon Insertion must1373// happen between the current token and the next token.1374//1375// This method is conservative - it cannot cover all edge cases of JavaScript,1376// but only aims to correctly handle certain well known cases. It *must not*1377// return true in speculative cases.1378void UnwrappedLineParser::readTokenWithJavaScriptASI() {1379FormatToken *Previous = FormatTok;1380readToken();1381FormatToken *Next = FormatTok;13821383bool IsOnSameLine =1384CommentsBeforeNextToken.empty()1385? Next->NewlinesBefore == 01386: CommentsBeforeNextToken.front()->NewlinesBefore == 0;1387if (IsOnSameLine)1388return;13891390bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);1391bool PreviousStartsTemplateExpr =1392Previous->is(TT_TemplateString) && Previous->TokenText.ends_with("${");1393if (PreviousMustBeValue || Previous->is(tok::r_paren)) {1394// If the line contains an '@' sign, the previous token might be an1395// annotation, which can precede another identifier/value.1396bool HasAt = llvm::any_of(Line->Tokens, [](UnwrappedLineNode &LineNode) {1397return LineNode.Tok->is(tok::at);1398});1399if (HasAt)1400return;1401}1402if (Next->is(tok::exclaim) && PreviousMustBeValue)1403return addUnwrappedLine();1404bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);1405bool NextEndsTemplateExpr =1406Next->is(TT_TemplateString) && Next->TokenText.starts_with("}");1407if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&1408(PreviousMustBeValue ||1409Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,1410tok::minusminus))) {1411return addUnwrappedLine();1412}1413if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&1414isJSDeclOrStmt(Keywords, Next)) {1415return addUnwrappedLine();1416}1417}14181419void UnwrappedLineParser::parseStructuralElement(1420const FormatToken *OpeningBrace, IfStmtKind *IfKind,1421FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) {1422if (Style.Language == FormatStyle::LK_TableGen &&1423FormatTok->is(tok::pp_include)) {1424nextToken();1425if (FormatTok->is(tok::string_literal))1426nextToken();1427addUnwrappedLine();1428return;1429}14301431if (IsCpp) {1432while (FormatTok->is(tok::l_square) && handleCppAttributes()) {1433}1434} else if (Style.isVerilog()) {1435if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {1436parseForOrWhileLoop(/*HasParens=*/false);1437return;1438}1439if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {1440parseForOrWhileLoop();1441return;1442}1443if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,1444Keywords.kw_assume, Keywords.kw_cover)) {1445parseIfThenElse(IfKind, /*KeepBraces=*/false, /*IsVerilogAssert=*/true);1446return;1447}14481449// Skip things that can exist before keywords like 'if' and 'case'.1450while (true) {1451if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,1452Keywords.kw_unique0)) {1453nextToken();1454} else if (FormatTok->is(tok::l_paren) &&1455Tokens->peekNextToken()->is(tok::star)) {1456parseParens();1457} else {1458break;1459}1460}1461}14621463// Tokens that only make sense at the beginning of a line.1464if (FormatTok->isAccessSpecifierKeyword()) {1465if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||1466Style.isCSharp()) {1467nextToken();1468} else {1469parseAccessSpecifier();1470}1471return;1472}1473switch (FormatTok->Tok.getKind()) {1474case tok::kw_asm:1475nextToken();1476if (FormatTok->is(tok::l_brace)) {1477FormatTok->setFinalizedType(TT_InlineASMBrace);1478nextToken();1479while (FormatTok && !eof()) {1480if (FormatTok->is(tok::r_brace)) {1481FormatTok->setFinalizedType(TT_InlineASMBrace);1482nextToken();1483addUnwrappedLine();1484break;1485}1486FormatTok->Finalized = true;1487nextToken();1488}1489}1490break;1491case tok::kw_namespace:1492parseNamespace();1493return;1494case tok::kw_if: {1495if (Style.isJavaScript() && Line->MustBeDeclaration) {1496// field/method declaration.1497break;1498}1499FormatToken *Tok = parseIfThenElse(IfKind);1500if (IfLeftBrace)1501*IfLeftBrace = Tok;1502return;1503}1504case tok::kw_for:1505case tok::kw_while:1506if (Style.isJavaScript() && Line->MustBeDeclaration) {1507// field/method declaration.1508break;1509}1510parseForOrWhileLoop();1511return;1512case tok::kw_do:1513if (Style.isJavaScript() && Line->MustBeDeclaration) {1514// field/method declaration.1515break;1516}1517parseDoWhile();1518if (HasDoWhile)1519*HasDoWhile = true;1520return;1521case tok::kw_switch:1522if (Style.isJavaScript() && Line->MustBeDeclaration) {1523// 'switch: string' field declaration.1524break;1525}1526parseSwitch(/*IsExpr=*/false);1527return;1528case tok::kw_default: {1529// In Verilog default along with other labels are handled in the next loop.1530if (Style.isVerilog())1531break;1532if (Style.isJavaScript() && Line->MustBeDeclaration) {1533// 'default: string' field declaration.1534break;1535}1536auto *Default = FormatTok;1537nextToken();1538if (FormatTok->is(tok::colon)) {1539FormatTok->setFinalizedType(TT_CaseLabelColon);1540parseLabel();1541return;1542}1543if (FormatTok->is(tok::arrow)) {1544FormatTok->setFinalizedType(TT_CaseLabelArrow);1545Default->setFinalizedType(TT_SwitchExpressionLabel);1546parseLabel();1547return;1548}1549// e.g. "default void f() {}" in a Java interface.1550break;1551}1552case tok::kw_case:1553// Proto: there are no switch/case statements.1554if (Style.Language == FormatStyle::LK_Proto) {1555nextToken();1556return;1557}1558if (Style.isVerilog()) {1559parseBlock();1560addUnwrappedLine();1561return;1562}1563if (Style.isJavaScript() && Line->MustBeDeclaration) {1564// 'case: string' field declaration.1565nextToken();1566break;1567}1568parseCaseLabel();1569return;1570case tok::kw_try:1571case tok::kw___try:1572if (Style.isJavaScript() && Line->MustBeDeclaration) {1573// field/method declaration.1574break;1575}1576parseTryCatch();1577return;1578case tok::kw_extern:1579nextToken();1580if (Style.isVerilog()) {1581// In Verilog and extern module declaration looks like a start of module.1582// But there is no body and endmodule. So we handle it separately.1583if (Keywords.isVerilogHierarchy(*FormatTok)) {1584parseVerilogHierarchyHeader();1585return;1586}1587} else if (FormatTok->is(tok::string_literal)) {1588nextToken();1589if (FormatTok->is(tok::l_brace)) {1590if (Style.BraceWrapping.AfterExternBlock)1591addUnwrappedLine();1592// Either we indent or for backwards compatibility we follow the1593// AfterExternBlock style.1594unsigned AddLevels =1595(Style.IndentExternBlock == FormatStyle::IEBS_Indent) ||1596(Style.BraceWrapping.AfterExternBlock &&1597Style.IndentExternBlock ==1598FormatStyle::IEBS_AfterExternBlock)1599? 1u1600: 0u;1601parseBlock(/*MustBeDeclaration=*/true, AddLevels);1602addUnwrappedLine();1603return;1604}1605}1606break;1607case tok::kw_export:1608if (Style.isJavaScript()) {1609parseJavaScriptEs6ImportExport();1610return;1611}1612if (IsCpp) {1613nextToken();1614if (FormatTok->is(tok::kw_namespace)) {1615parseNamespace();1616return;1617}1618if (FormatTok->is(Keywords.kw_import) && parseModuleImport())1619return;1620}1621break;1622case tok::kw_inline:1623nextToken();1624if (FormatTok->is(tok::kw_namespace)) {1625parseNamespace();1626return;1627}1628break;1629case tok::identifier:1630if (FormatTok->is(TT_ForEachMacro)) {1631parseForOrWhileLoop();1632return;1633}1634if (FormatTok->is(TT_MacroBlockBegin)) {1635parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,1636/*MunchSemi=*/false);1637return;1638}1639if (FormatTok->is(Keywords.kw_import)) {1640if (Style.isJavaScript()) {1641parseJavaScriptEs6ImportExport();1642return;1643}1644if (Style.Language == FormatStyle::LK_Proto) {1645nextToken();1646if (FormatTok->is(tok::kw_public))1647nextToken();1648if (FormatTok->isNot(tok::string_literal))1649return;1650nextToken();1651if (FormatTok->is(tok::semi))1652nextToken();1653addUnwrappedLine();1654return;1655}1656if (IsCpp && parseModuleImport())1657return;1658}1659if (IsCpp && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,1660Keywords.kw_slots, Keywords.kw_qslots)) {1661nextToken();1662if (FormatTok->is(tok::colon)) {1663nextToken();1664addUnwrappedLine();1665return;1666}1667}1668if (IsCpp && FormatTok->is(TT_StatementMacro)) {1669parseStatementMacro();1670return;1671}1672if (IsCpp && FormatTok->is(TT_NamespaceMacro)) {1673parseNamespace();1674return;1675}1676// In Verilog labels can be any expression, so we don't do them here.1677// JS doesn't have macros, and within classes colons indicate fields, not1678// labels.1679// TableGen doesn't have labels.1680if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&1681Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) {1682nextToken();1683if (!Line->InMacroBody || CurrentLines->size() > 1)1684Line->Tokens.begin()->Tok->MustBreakBefore = true;1685FormatTok->setFinalizedType(TT_GotoLabelColon);1686parseLabel(!Style.IndentGotoLabels);1687if (HasLabel)1688*HasLabel = true;1689return;1690}1691// In all other cases, parse the declaration.1692break;1693default:1694break;1695}16961697for (const bool InRequiresExpression =1698OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);1699!eof();) {1700if (IsCpp && FormatTok->isCppAlternativeOperatorKeyword()) {1701if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true);1702Next && Next->isBinaryOperator()) {1703FormatTok->Tok.setKind(tok::identifier);1704}1705}1706const FormatToken *Previous = FormatTok->Previous;1707switch (FormatTok->Tok.getKind()) {1708case tok::at:1709nextToken();1710if (FormatTok->is(tok::l_brace)) {1711nextToken();1712parseBracedList();1713break;1714} else if (Style.Language == FormatStyle::LK_Java &&1715FormatTok->is(Keywords.kw_interface)) {1716nextToken();1717break;1718}1719switch (FormatTok->Tok.getObjCKeywordID()) {1720case tok::objc_public:1721case tok::objc_protected:1722case tok::objc_package:1723case tok::objc_private:1724return parseAccessSpecifier();1725case tok::objc_interface:1726case tok::objc_implementation:1727return parseObjCInterfaceOrImplementation();1728case tok::objc_protocol:1729if (parseObjCProtocol())1730return;1731break;1732case tok::objc_end:1733return; // Handled by the caller.1734case tok::objc_optional:1735case tok::objc_required:1736nextToken();1737addUnwrappedLine();1738return;1739case tok::objc_autoreleasepool:1740nextToken();1741if (FormatTok->is(tok::l_brace)) {1742if (Style.BraceWrapping.AfterControlStatement ==1743FormatStyle::BWACS_Always) {1744addUnwrappedLine();1745}1746parseBlock();1747}1748addUnwrappedLine();1749return;1750case tok::objc_synchronized:1751nextToken();1752if (FormatTok->is(tok::l_paren)) {1753// Skip synchronization object1754parseParens();1755}1756if (FormatTok->is(tok::l_brace)) {1757if (Style.BraceWrapping.AfterControlStatement ==1758FormatStyle::BWACS_Always) {1759addUnwrappedLine();1760}1761parseBlock();1762}1763addUnwrappedLine();1764return;1765case tok::objc_try:1766// This branch isn't strictly necessary (the kw_try case below would1767// do this too after the tok::at is parsed above). But be explicit.1768parseTryCatch();1769return;1770default:1771break;1772}1773break;1774case tok::kw_requires: {1775if (IsCpp) {1776bool ParsedClause = parseRequires();1777if (ParsedClause)1778return;1779} else {1780nextToken();1781}1782break;1783}1784case tok::kw_enum:1785// Ignore if this is part of "template <enum ..." or "... -> enum" or1786// "template <..., enum ...>".1787if (Previous && Previous->isOneOf(tok::less, tok::arrow, tok::comma)) {1788nextToken();1789break;1790}17911792// parseEnum falls through and does not yet add an unwrapped line as an1793// enum definition can start a structural element.1794if (!parseEnum())1795break;1796// This only applies to C++ and Verilog.1797if (!IsCpp && !Style.isVerilog()) {1798addUnwrappedLine();1799return;1800}1801break;1802case tok::kw_typedef:1803nextToken();1804if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,1805Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,1806Keywords.kw_CF_CLOSED_ENUM,1807Keywords.kw_NS_CLOSED_ENUM)) {1808parseEnum();1809}1810break;1811case tok::kw_class:1812if (Style.isVerilog()) {1813parseBlock();1814addUnwrappedLine();1815return;1816}1817if (Style.isTableGen()) {1818// Do nothing special. In this case the l_brace becomes FunctionLBrace.1819// This is same as def and so on.1820nextToken();1821break;1822}1823[[fallthrough]];1824case tok::kw_struct:1825case tok::kw_union:1826if (parseStructLike())1827return;1828break;1829case tok::kw_decltype:1830nextToken();1831if (FormatTok->is(tok::l_paren)) {1832parseParens();1833assert(FormatTok->Previous);1834if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,1835tok::l_paren)) {1836Line->SeenDecltypeAuto = true;1837}1838}1839break;1840case tok::period:1841nextToken();1842// In Java, classes have an implicit static member "class".1843if (Style.Language == FormatStyle::LK_Java && FormatTok &&1844FormatTok->is(tok::kw_class)) {1845nextToken();1846}1847if (Style.isJavaScript() && FormatTok &&1848FormatTok->Tok.getIdentifierInfo()) {1849// JavaScript only has pseudo keywords, all keywords are allowed to1850// appear in "IdentifierName" positions. See http://es5.github.io/#x7.61851nextToken();1852}1853break;1854case tok::semi:1855nextToken();1856addUnwrappedLine();1857return;1858case tok::r_brace:1859addUnwrappedLine();1860return;1861case tok::l_paren: {1862parseParens();1863// Break the unwrapped line if a K&R C function definition has a parameter1864// declaration.1865if (OpeningBrace || !IsCpp || !Previous || eof())1866break;1867if (isC78ParameterDecl(FormatTok,1868Tokens->peekNextToken(/*SkipComment=*/true),1869Previous)) {1870addUnwrappedLine();1871return;1872}1873break;1874}1875case tok::kw_operator:1876nextToken();1877if (FormatTok->isBinaryOperator())1878nextToken();1879break;1880case tok::caret:1881nextToken();1882// Block return type.1883if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {1884nextToken();1885// Return types: pointers are ok too.1886while (FormatTok->is(tok::star))1887nextToken();1888}1889// Block argument list.1890if (FormatTok->is(tok::l_paren))1891parseParens();1892// Block body.1893if (FormatTok->is(tok::l_brace))1894parseChildBlock();1895break;1896case tok::l_brace:1897if (InRequiresExpression)1898FormatTok->setFinalizedType(TT_BracedListLBrace);1899if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {1900IsDecltypeAutoFunction = Line->SeenDecltypeAuto;1901// A block outside of parentheses must be the last part of a1902// structural element.1903// FIXME: Figure out cases where this is not true, and add projections1904// for them (the one we know is missing are lambdas).1905if (Style.Language == FormatStyle::LK_Java &&1906Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {1907// If necessary, we could set the type to something different than1908// TT_FunctionLBrace.1909if (Style.BraceWrapping.AfterControlStatement ==1910FormatStyle::BWACS_Always) {1911addUnwrappedLine();1912}1913} else if (Style.BraceWrapping.AfterFunction) {1914addUnwrappedLine();1915}1916if (!Previous || Previous->isNot(TT_TypeDeclarationParen))1917FormatTok->setFinalizedType(TT_FunctionLBrace);1918parseBlock();1919IsDecltypeAutoFunction = false;1920addUnwrappedLine();1921return;1922}1923// Otherwise this was a braced init list, and the structural1924// element continues.1925break;1926case tok::kw_try:1927if (Style.isJavaScript() && Line->MustBeDeclaration) {1928// field/method declaration.1929nextToken();1930break;1931}1932// We arrive here when parsing function-try blocks.1933if (Style.BraceWrapping.AfterFunction)1934addUnwrappedLine();1935parseTryCatch();1936return;1937case tok::identifier: {1938if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&1939Line->MustBeDeclaration) {1940addUnwrappedLine();1941parseCSharpGenericTypeConstraint();1942break;1943}1944if (FormatTok->is(TT_MacroBlockEnd)) {1945addUnwrappedLine();1946return;1947}19481949// Function declarations (as opposed to function expressions) are parsed1950// on their own unwrapped line by continuing this loop. Function1951// expressions (functions that are not on their own line) must not create1952// a new unwrapped line, so they are special cased below.1953size_t TokenCount = Line->Tokens.size();1954if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&1955(TokenCount > 1 ||1956(TokenCount == 1 &&1957Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {1958tryToParseJSFunction();1959break;1960}1961if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) &&1962FormatTok->is(Keywords.kw_interface)) {1963if (Style.isJavaScript()) {1964// In JavaScript/TypeScript, "interface" can be used as a standalone1965// identifier, e.g. in `var interface = 1;`. If "interface" is1966// followed by another identifier, it is very like to be an actual1967// interface declaration.1968unsigned StoredPosition = Tokens->getPosition();1969FormatToken *Next = Tokens->getNextToken();1970FormatTok = Tokens->setPosition(StoredPosition);1971if (!mustBeJSIdent(Keywords, Next)) {1972nextToken();1973break;1974}1975}1976parseRecord();1977addUnwrappedLine();1978return;1979}19801981if (Style.isVerilog()) {1982if (FormatTok->is(Keywords.kw_table)) {1983parseVerilogTable();1984return;1985}1986if (Keywords.isVerilogBegin(*FormatTok) ||1987Keywords.isVerilogHierarchy(*FormatTok)) {1988parseBlock();1989addUnwrappedLine();1990return;1991}1992}19931994if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {1995if (parseStructLike())1996return;1997break;1998}19992000if (IsCpp && FormatTok->is(TT_StatementMacro)) {2001parseStatementMacro();2002return;2003}20042005// See if the following token should start a new unwrapped line.2006StringRef Text = FormatTok->TokenText;20072008FormatToken *PreviousToken = FormatTok;2009nextToken();20102011// JS doesn't have macros, and within classes colons indicate fields, not2012// labels.2013if (Style.isJavaScript())2014break;20152016auto OneTokenSoFar = [&]() {2017auto I = Line->Tokens.begin(), E = Line->Tokens.end();2018while (I != E && I->Tok->is(tok::comment))2019++I;2020if (Style.isVerilog())2021while (I != E && I->Tok->is(tok::hash))2022++I;2023return I != E && (++I == E);2024};2025if (OneTokenSoFar()) {2026// Recognize function-like macro usages without trailing semicolon as2027// well as free-standing macros like Q_OBJECT.2028bool FunctionLike = FormatTok->is(tok::l_paren);2029if (FunctionLike)2030parseParens();20312032bool FollowedByNewline =2033CommentsBeforeNextToken.empty()2034? FormatTok->NewlinesBefore > 02035: CommentsBeforeNextToken.front()->NewlinesBefore > 0;20362037if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&2038tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) {2039if (PreviousToken->isNot(TT_UntouchableMacroFunc))2040PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);2041addUnwrappedLine();2042return;2043}2044}2045break;2046}2047case tok::equal:2048if ((Style.isJavaScript() || Style.isCSharp()) &&2049FormatTok->is(TT_FatArrow)) {2050tryToParseChildBlock();2051break;2052}20532054nextToken();2055if (FormatTok->is(tok::l_brace)) {2056// Block kind should probably be set to BK_BracedInit for any language.2057// C# needs this change to ensure that array initialisers and object2058// initialisers are indented the same way.2059if (Style.isCSharp())2060FormatTok->setBlockKind(BK_BracedInit);2061// TableGen's defset statement has syntax of the form,2062// `defset <type> <name> = { <statement>... }`2063if (Style.isTableGen() &&2064Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {2065FormatTok->setFinalizedType(TT_FunctionLBrace);2066parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,2067/*MunchSemi=*/false);2068addUnwrappedLine();2069break;2070}2071nextToken();2072parseBracedList();2073} else if (Style.Language == FormatStyle::LK_Proto &&2074FormatTok->is(tok::less)) {2075nextToken();2076parseBracedList(/*IsAngleBracket=*/true);2077}2078break;2079case tok::l_square:2080parseSquare();2081break;2082case tok::kw_new:2083parseNew();2084break;2085case tok::kw_switch:2086if (Style.Language == FormatStyle::LK_Java)2087parseSwitch(/*IsExpr=*/true);2088else2089nextToken();2090break;2091case tok::kw_case:2092// Proto: there are no switch/case statements.2093if (Style.Language == FormatStyle::LK_Proto) {2094nextToken();2095return;2096}2097// In Verilog switch is called case.2098if (Style.isVerilog()) {2099parseBlock();2100addUnwrappedLine();2101return;2102}2103if (Style.isJavaScript() && Line->MustBeDeclaration) {2104// 'case: string' field declaration.2105nextToken();2106break;2107}2108parseCaseLabel();2109break;2110case tok::kw_default:2111nextToken();2112if (Style.isVerilog()) {2113if (FormatTok->is(tok::colon)) {2114// The label will be handled in the next iteration.2115break;2116}2117if (FormatTok->is(Keywords.kw_clocking)) {2118// A default clocking block.2119parseBlock();2120addUnwrappedLine();2121return;2122}2123parseVerilogCaseLabel();2124return;2125}2126break;2127case tok::colon:2128nextToken();2129if (Style.isVerilog()) {2130parseVerilogCaseLabel();2131return;2132}2133break;2134case tok::greater:2135nextToken();2136if (FormatTok->is(tok::l_brace))2137FormatTok->Previous->setFinalizedType(TT_TemplateCloser);2138break;2139default:2140nextToken();2141break;2142}2143}2144}21452146bool UnwrappedLineParser::tryToParsePropertyAccessor() {2147assert(FormatTok->is(tok::l_brace));2148if (!Style.isCSharp())2149return false;2150// See if it's a property accessor.2151if (FormatTok->Previous->isNot(tok::identifier))2152return false;21532154// See if we are inside a property accessor.2155//2156// Record the current tokenPosition so that we can advance and2157// reset the current token. `Next` is not set yet so we need2158// another way to advance along the token stream.2159unsigned int StoredPosition = Tokens->getPosition();2160FormatToken *Tok = Tokens->getNextToken();21612162// A trivial property accessor is of the form:2163// { [ACCESS_SPECIFIER] [get]; [ACCESS_SPECIFIER] [set|init] }2164// Track these as they do not require line breaks to be introduced.2165bool HasSpecialAccessor = false;2166bool IsTrivialPropertyAccessor = true;2167while (!eof()) {2168if (Tok->isAccessSpecifierKeyword() ||2169Tok->isOneOf(tok::semi, Keywords.kw_internal, Keywords.kw_get,2170Keywords.kw_init, Keywords.kw_set)) {2171if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set))2172HasSpecialAccessor = true;2173Tok = Tokens->getNextToken();2174continue;2175}2176if (Tok->isNot(tok::r_brace))2177IsTrivialPropertyAccessor = false;2178break;2179}21802181if (!HasSpecialAccessor) {2182Tokens->setPosition(StoredPosition);2183return false;2184}21852186// Try to parse the property accessor:2187// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties2188Tokens->setPosition(StoredPosition);2189if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)2190addUnwrappedLine();2191nextToken();2192do {2193switch (FormatTok->Tok.getKind()) {2194case tok::r_brace:2195nextToken();2196if (FormatTok->is(tok::equal)) {2197while (!eof() && FormatTok->isNot(tok::semi))2198nextToken();2199nextToken();2200}2201addUnwrappedLine();2202return true;2203case tok::l_brace:2204++Line->Level;2205parseBlock(/*MustBeDeclaration=*/true);2206addUnwrappedLine();2207--Line->Level;2208break;2209case tok::equal:2210if (FormatTok->is(TT_FatArrow)) {2211++Line->Level;2212do {2213nextToken();2214} while (!eof() && FormatTok->isNot(tok::semi));2215nextToken();2216addUnwrappedLine();2217--Line->Level;2218break;2219}2220nextToken();2221break;2222default:2223if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,2224Keywords.kw_set) &&2225!IsTrivialPropertyAccessor) {2226// Non-trivial get/set needs to be on its own line.2227addUnwrappedLine();2228}2229nextToken();2230}2231} while (!eof());22322233// Unreachable for well-formed code (paired '{' and '}').2234return true;2235}22362237bool UnwrappedLineParser::tryToParseLambda() {2238assert(FormatTok->is(tok::l_square));2239if (!IsCpp) {2240nextToken();2241return false;2242}2243FormatToken &LSquare = *FormatTok;2244if (!tryToParseLambdaIntroducer())2245return false;22462247bool SeenArrow = false;2248bool InTemplateParameterList = false;22492250while (FormatTok->isNot(tok::l_brace)) {2251if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {2252nextToken();2253continue;2254}2255switch (FormatTok->Tok.getKind()) {2256case tok::l_brace:2257break;2258case tok::l_paren:2259parseParens(/*AmpAmpTokenType=*/TT_PointerOrReference);2260break;2261case tok::l_square:2262parseSquare();2263break;2264case tok::less:2265assert(FormatTok->Previous);2266if (FormatTok->Previous->is(tok::r_square))2267InTemplateParameterList = true;2268nextToken();2269break;2270case tok::kw_auto:2271case tok::kw_class:2272case tok::kw_struct:2273case tok::kw_union:2274case tok::kw_template:2275case tok::kw_typename:2276case tok::amp:2277case tok::star:2278case tok::kw_const:2279case tok::kw_constexpr:2280case tok::kw_consteval:2281case tok::comma:2282case tok::greater:2283case tok::identifier:2284case tok::numeric_constant:2285case tok::coloncolon:2286case tok::kw_mutable:2287case tok::kw_noexcept:2288case tok::kw_static:2289nextToken();2290break;2291// Specialization of a template with an integer parameter can contain2292// arithmetic, logical, comparison and ternary operators.2293//2294// FIXME: This also accepts sequences of operators that are not in the scope2295// of a template argument list.2296//2297// In a C++ lambda a template type can only occur after an arrow. We use2298// this as an heuristic to distinguish between Objective-C expressions2299// followed by an `a->b` expression, such as:2300// ([obj func:arg] + a->b)2301// Otherwise the code below would parse as a lambda.2302case tok::plus:2303case tok::minus:2304case tok::exclaim:2305case tok::tilde:2306case tok::slash:2307case tok::percent:2308case tok::lessless:2309case tok::pipe:2310case tok::pipepipe:2311case tok::ampamp:2312case tok::caret:2313case tok::equalequal:2314case tok::exclaimequal:2315case tok::greaterequal:2316case tok::lessequal:2317case tok::question:2318case tok::colon:2319case tok::ellipsis:2320case tok::kw_true:2321case tok::kw_false:2322if (SeenArrow || InTemplateParameterList) {2323nextToken();2324break;2325}2326return true;2327case tok::arrow:2328// This might or might not actually be a lambda arrow (this could be an2329// ObjC method invocation followed by a dereferencing arrow). We might2330// reset this back to TT_Unknown in TokenAnnotator.2331FormatTok->setFinalizedType(TT_LambdaArrow);2332SeenArrow = true;2333nextToken();2334break;2335case tok::kw_requires: {2336auto *RequiresToken = FormatTok;2337nextToken();2338parseRequiresClause(RequiresToken);2339break;2340}2341case tok::equal:2342if (!InTemplateParameterList)2343return true;2344nextToken();2345break;2346default:2347return true;2348}2349}23502351FormatTok->setFinalizedType(TT_LambdaLBrace);2352LSquare.setFinalizedType(TT_LambdaLSquare);23532354NestedLambdas.push_back(Line->SeenDecltypeAuto);2355parseChildBlock();2356assert(!NestedLambdas.empty());2357NestedLambdas.pop_back();23582359return true;2360}23612362bool UnwrappedLineParser::tryToParseLambdaIntroducer() {2363const FormatToken *Previous = FormatTok->Previous;2364const FormatToken *LeftSquare = FormatTok;2365nextToken();2366if ((Previous && ((Previous->Tok.getIdentifierInfo() &&2367!Previous->isOneOf(tok::kw_return, tok::kw_co_await,2368tok::kw_co_yield, tok::kw_co_return)) ||2369Previous->closesScope())) ||2370LeftSquare->isCppStructuredBinding(IsCpp)) {2371return false;2372}2373if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))2374return false;2375if (FormatTok->is(tok::r_square)) {2376const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true);2377if (Next->is(tok::greater))2378return false;2379}2380parseSquare(/*LambdaIntroducer=*/true);2381return true;2382}23832384void UnwrappedLineParser::tryToParseJSFunction() {2385assert(FormatTok->is(Keywords.kw_function));2386if (FormatTok->is(Keywords.kw_async))2387nextToken();2388// Consume "function".2389nextToken();23902391// Consume * (generator function). Treat it like C++'s overloaded operators.2392if (FormatTok->is(tok::star)) {2393FormatTok->setFinalizedType(TT_OverloadedOperator);2394nextToken();2395}23962397// Consume function name.2398if (FormatTok->is(tok::identifier))2399nextToken();24002401if (FormatTok->isNot(tok::l_paren))2402return;24032404// Parse formal parameter list.2405parseParens();24062407if (FormatTok->is(tok::colon)) {2408// Parse a type definition.2409nextToken();24102411// Eat the type declaration. For braced inline object types, balance braces,2412// otherwise just parse until finding an l_brace for the function body.2413if (FormatTok->is(tok::l_brace))2414tryToParseBracedList();2415else2416while (!FormatTok->isOneOf(tok::l_brace, tok::semi) && !eof())2417nextToken();2418}24192420if (FormatTok->is(tok::semi))2421return;24222423parseChildBlock();2424}24252426bool UnwrappedLineParser::tryToParseBracedList() {2427if (FormatTok->is(BK_Unknown))2428calculateBraceTypes();2429assert(FormatTok->isNot(BK_Unknown));2430if (FormatTok->is(BK_Block))2431return false;2432nextToken();2433parseBracedList();2434return true;2435}24362437bool UnwrappedLineParser::tryToParseChildBlock() {2438assert(Style.isJavaScript() || Style.isCSharp());2439assert(FormatTok->is(TT_FatArrow));2440// Fat arrows (=>) have tok::TokenKind tok::equal but TokenType TT_FatArrow.2441// They always start an expression or a child block if followed by a curly2442// brace.2443nextToken();2444if (FormatTok->isNot(tok::l_brace))2445return false;2446parseChildBlock();2447return true;2448}24492450bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {2451assert(!IsAngleBracket || !IsEnum);2452bool HasError = false;24532454// FIXME: Once we have an expression parser in the UnwrappedLineParser,2455// replace this by using parseAssignmentExpression() inside.2456do {2457if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&2458tryToParseChildBlock()) {2459continue;2460}2461if (Style.isJavaScript()) {2462if (FormatTok->is(Keywords.kw_function)) {2463tryToParseJSFunction();2464continue;2465}2466if (FormatTok->is(tok::l_brace)) {2467// Could be a method inside of a braced list `{a() { return 1; }}`.2468if (tryToParseBracedList())2469continue;2470parseChildBlock();2471}2472}2473if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {2474if (IsEnum) {2475FormatTok->setBlockKind(BK_Block);2476if (!Style.AllowShortEnumsOnASingleLine)2477addUnwrappedLine();2478}2479nextToken();2480return !HasError;2481}2482switch (FormatTok->Tok.getKind()) {2483case tok::l_square:2484if (Style.isCSharp())2485parseSquare();2486else2487tryToParseLambda();2488break;2489case tok::l_paren:2490parseParens();2491// JavaScript can just have free standing methods and getters/setters in2492// object literals. Detect them by a "{" following ")".2493if (Style.isJavaScript()) {2494if (FormatTok->is(tok::l_brace))2495parseChildBlock();2496break;2497}2498break;2499case tok::l_brace:2500// Assume there are no blocks inside a braced init list apart2501// from the ones we explicitly parse out (like lambdas).2502FormatTok->setBlockKind(BK_BracedInit);2503if (!IsAngleBracket) {2504auto *Prev = FormatTok->Previous;2505if (Prev && Prev->is(tok::greater))2506Prev->setFinalizedType(TT_TemplateCloser);2507}2508nextToken();2509parseBracedList();2510break;2511case tok::less:2512nextToken();2513if (IsAngleBracket)2514parseBracedList(/*IsAngleBracket=*/true);2515break;2516case tok::semi:2517// JavaScript (or more precisely TypeScript) can have semicolons in braced2518// lists (in so-called TypeMemberLists). Thus, the semicolon cannot be2519// used for error recovery if we have otherwise determined that this is2520// a braced list.2521if (Style.isJavaScript()) {2522nextToken();2523break;2524}2525HasError = true;2526if (!IsEnum)2527return false;2528nextToken();2529break;2530case tok::comma:2531nextToken();2532if (IsEnum && !Style.AllowShortEnumsOnASingleLine)2533addUnwrappedLine();2534break;2535default:2536nextToken();2537break;2538}2539} while (!eof());2540return false;2541}25422543/// \brief Parses a pair of parentheses (and everything between them).2544/// \param AmpAmpTokenType If different than TT_Unknown sets this type for all2545/// double ampersands. This applies for all nested scopes as well.2546///2547/// Returns whether there is a `=` token between the parentheses.2548bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {2549assert(FormatTok->is(tok::l_paren) && "'(' expected.");2550auto *LeftParen = FormatTok;2551bool SeenEqual = false;2552bool MightBeFoldExpr = false;2553const bool MightBeStmtExpr = Tokens->peekNextToken()->is(tok::l_brace);2554nextToken();2555do {2556switch (FormatTok->Tok.getKind()) {2557case tok::l_paren:2558if (parseParens(AmpAmpTokenType))2559SeenEqual = true;2560if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace))2561parseChildBlock();2562break;2563case tok::r_paren: {2564auto *Prev = LeftParen->Previous;2565if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody &&2566Style.RemoveParentheses > FormatStyle::RPS_Leave) {2567const auto *Next = Tokens->peekNextToken();2568const bool DoubleParens =2569Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren);2570const auto *PrevPrev = Prev ? Prev->getPreviousNonComment() : nullptr;2571const bool Blacklisted =2572PrevPrev &&2573(PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||2574(SeenEqual &&2575(PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||2576PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));2577const bool ReturnParens =2578Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&2579((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||2580(!NestedLambdas.empty() && !NestedLambdas.back())) &&2581Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next &&2582Next->is(tok::semi);2583if ((DoubleParens && !Blacklisted) || ReturnParens) {2584LeftParen->Optional = true;2585FormatTok->Optional = true;2586}2587}2588if (Prev) {2589if (Prev->is(TT_TypenameMacro)) {2590LeftParen->setFinalizedType(TT_TypeDeclarationParen);2591FormatTok->setFinalizedType(TT_TypeDeclarationParen);2592} else if (Prev->is(tok::greater) && FormatTok->Previous == LeftParen) {2593Prev->setFinalizedType(TT_TemplateCloser);2594}2595}2596nextToken();2597return SeenEqual;2598}2599case tok::r_brace:2600// A "}" inside parenthesis is an error if there wasn't a matching "{".2601return SeenEqual;2602case tok::l_square:2603tryToParseLambda();2604break;2605case tok::l_brace:2606if (!tryToParseBracedList())2607parseChildBlock();2608break;2609case tok::at:2610nextToken();2611if (FormatTok->is(tok::l_brace)) {2612nextToken();2613parseBracedList();2614}2615break;2616case tok::ellipsis:2617MightBeFoldExpr = true;2618nextToken();2619break;2620case tok::equal:2621SeenEqual = true;2622if (Style.isCSharp() && FormatTok->is(TT_FatArrow))2623tryToParseChildBlock();2624else2625nextToken();2626break;2627case tok::kw_class:2628if (Style.isJavaScript())2629parseRecord(/*ParseAsExpr=*/true);2630else2631nextToken();2632break;2633case tok::identifier:2634if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))2635tryToParseJSFunction();2636else2637nextToken();2638break;2639case tok::kw_switch:2640if (Style.Language == FormatStyle::LK_Java)2641parseSwitch(/*IsExpr=*/true);2642else2643nextToken();2644break;2645case tok::kw_requires: {2646auto RequiresToken = FormatTok;2647nextToken();2648parseRequiresExpression(RequiresToken);2649break;2650}2651case tok::ampamp:2652if (AmpAmpTokenType != TT_Unknown)2653FormatTok->setFinalizedType(AmpAmpTokenType);2654[[fallthrough]];2655default:2656nextToken();2657break;2658}2659} while (!eof());2660return SeenEqual;2661}26622663void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {2664if (!LambdaIntroducer) {2665assert(FormatTok->is(tok::l_square) && "'[' expected.");2666if (tryToParseLambda())2667return;2668}2669do {2670switch (FormatTok->Tok.getKind()) {2671case tok::l_paren:2672parseParens();2673break;2674case tok::r_square:2675nextToken();2676return;2677case tok::r_brace:2678// A "}" inside parenthesis is an error if there wasn't a matching "{".2679return;2680case tok::l_square:2681parseSquare();2682break;2683case tok::l_brace: {2684if (!tryToParseBracedList())2685parseChildBlock();2686break;2687}2688case tok::at:2689case tok::colon:2690nextToken();2691if (FormatTok->is(tok::l_brace)) {2692nextToken();2693parseBracedList();2694}2695break;2696default:2697nextToken();2698break;2699}2700} while (!eof());2701}27022703void UnwrappedLineParser::keepAncestorBraces() {2704if (!Style.RemoveBracesLLVM)2705return;27062707const int MaxNestingLevels = 2;2708const int Size = NestedTooDeep.size();2709if (Size >= MaxNestingLevels)2710NestedTooDeep[Size - MaxNestingLevels] = true;2711NestedTooDeep.push_back(false);2712}27132714static FormatToken *getLastNonComment(const UnwrappedLine &Line) {2715for (const auto &Token : llvm::reverse(Line.Tokens))2716if (Token.Tok->isNot(tok::comment))2717return Token.Tok;27182719return nullptr;2720}27212722void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {2723FormatToken *Tok = nullptr;27242725if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() &&2726PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {2727Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never2728? getLastNonComment(*Line)2729: Line->Tokens.back().Tok;2730assert(Tok);2731if (Tok->BraceCount < 0) {2732assert(Tok->BraceCount == -1);2733Tok = nullptr;2734} else {2735Tok->BraceCount = -1;2736}2737}27382739addUnwrappedLine();2740++Line->Level;2741++Line->UnbracedBodyLevel;2742parseStructuralElement();2743--Line->UnbracedBodyLevel;27442745if (Tok) {2746assert(!Line->InPPDirective);2747Tok = nullptr;2748for (const auto &L : llvm::reverse(*CurrentLines)) {2749if (!L.InPPDirective && getLastNonComment(L)) {2750Tok = L.Tokens.back().Tok;2751break;2752}2753}2754assert(Tok);2755++Tok->BraceCount;2756}27572758if (CheckEOF && eof())2759addUnwrappedLine();27602761--Line->Level;2762}27632764static void markOptionalBraces(FormatToken *LeftBrace) {2765if (!LeftBrace)2766return;27672768assert(LeftBrace->is(tok::l_brace));27692770FormatToken *RightBrace = LeftBrace->MatchingParen;2771if (!RightBrace) {2772assert(!LeftBrace->Optional);2773return;2774}27752776assert(RightBrace->is(tok::r_brace));2777assert(RightBrace->MatchingParen == LeftBrace);2778assert(LeftBrace->Optional == RightBrace->Optional);27792780LeftBrace->Optional = true;2781RightBrace->Optional = true;2782}27832784void UnwrappedLineParser::handleAttributes() {2785// Handle AttributeMacro, e.g. `if (x) UNLIKELY`.2786if (FormatTok->isAttribute())2787nextToken();2788else if (FormatTok->is(tok::l_square))2789handleCppAttributes();2790}27912792bool UnwrappedLineParser::handleCppAttributes() {2793// Handle [[likely]] / [[unlikely]] attributes.2794assert(FormatTok->is(tok::l_square));2795if (!tryToParseSimpleAttribute())2796return false;2797parseSquare();2798return true;2799}28002801/// Returns whether \c Tok begins a block.2802bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const {2803// FIXME: rename the function or make2804// Tok.isOneOf(tok::l_brace, TT_MacroBlockBegin) work.2805return Style.isVerilog() ? Keywords.isVerilogBegin(Tok)2806: Tok.is(tok::l_brace);2807}28082809FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,2810bool KeepBraces,2811bool IsVerilogAssert) {2812assert((FormatTok->is(tok::kw_if) ||2813(Style.isVerilog() &&2814FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,2815Keywords.kw_assume, Keywords.kw_cover))) &&2816"'if' expected");2817nextToken();28182819if (IsVerilogAssert) {2820// Handle `assert #0` and `assert final`.2821if (FormatTok->is(Keywords.kw_verilogHash)) {2822nextToken();2823if (FormatTok->is(tok::numeric_constant))2824nextToken();2825} else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,2826Keywords.kw_sequence)) {2827nextToken();2828}2829}28302831// TableGen's if statement has the form of `if <cond> then { ... }`.2832if (Style.isTableGen()) {2833while (!eof() && FormatTok->isNot(Keywords.kw_then)) {2834// Simply skip until then. This range only contains a value.2835nextToken();2836}2837}28382839// Handle `if !consteval`.2840if (FormatTok->is(tok::exclaim))2841nextToken();28422843bool KeepIfBraces = true;2844if (FormatTok->is(tok::kw_consteval)) {2845nextToken();2846} else {2847KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;2848if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))2849nextToken();2850if (FormatTok->is(tok::l_paren)) {2851FormatTok->setFinalizedType(TT_ConditionLParen);2852parseParens();2853}2854}2855handleAttributes();2856// The then action is optional in Verilog assert statements.2857if (IsVerilogAssert && FormatTok->is(tok::semi)) {2858nextToken();2859addUnwrappedLine();2860return nullptr;2861}28622863bool NeedsUnwrappedLine = false;2864keepAncestorBraces();28652866FormatToken *IfLeftBrace = nullptr;2867IfStmtKind IfBlockKind = IfStmtKind::NotIf;28682869if (isBlockBegin(*FormatTok)) {2870FormatTok->setFinalizedType(TT_ControlStatementLBrace);2871IfLeftBrace = FormatTok;2872CompoundStatementIndenter Indenter(this, Style, Line->Level);2873parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,2874/*MunchSemi=*/true, KeepIfBraces, &IfBlockKind);2875setPreviousRBraceType(TT_ControlStatementRBrace);2876if (Style.BraceWrapping.BeforeElse)2877addUnwrappedLine();2878else2879NeedsUnwrappedLine = true;2880} else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {2881addUnwrappedLine();2882} else {2883parseUnbracedBody();2884}28852886if (Style.RemoveBracesLLVM) {2887assert(!NestedTooDeep.empty());2888KeepIfBraces = KeepIfBraces ||2889(IfLeftBrace && !IfLeftBrace->MatchingParen) ||2890NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||2891IfBlockKind == IfStmtKind::IfElseIf;2892}28932894bool KeepElseBraces = KeepIfBraces;2895FormatToken *ElseLeftBrace = nullptr;2896IfStmtKind Kind = IfStmtKind::IfOnly;28972898if (FormatTok->is(tok::kw_else)) {2899if (Style.RemoveBracesLLVM) {2900NestedTooDeep.back() = false;2901Kind = IfStmtKind::IfElse;2902}2903nextToken();2904handleAttributes();2905if (isBlockBegin(*FormatTok)) {2906const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);2907FormatTok->setFinalizedType(TT_ElseLBrace);2908ElseLeftBrace = FormatTok;2909CompoundStatementIndenter Indenter(this, Style, Line->Level);2910IfStmtKind ElseBlockKind = IfStmtKind::NotIf;2911FormatToken *IfLBrace =2912parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,2913/*MunchSemi=*/true, KeepElseBraces, &ElseBlockKind);2914setPreviousRBraceType(TT_ElseRBrace);2915if (FormatTok->is(tok::kw_else)) {2916KeepElseBraces = KeepElseBraces ||2917ElseBlockKind == IfStmtKind::IfOnly ||2918ElseBlockKind == IfStmtKind::IfElseIf;2919} else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {2920KeepElseBraces = true;2921assert(ElseLeftBrace->MatchingParen);2922markOptionalBraces(ElseLeftBrace);2923}2924addUnwrappedLine();2925} else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {2926const FormatToken *Previous = Tokens->getPreviousToken();2927assert(Previous);2928const bool IsPrecededByComment = Previous->is(tok::comment);2929if (IsPrecededByComment) {2930addUnwrappedLine();2931++Line->Level;2932}2933bool TooDeep = true;2934if (Style.RemoveBracesLLVM) {2935Kind = IfStmtKind::IfElseIf;2936TooDeep = NestedTooDeep.pop_back_val();2937}2938ElseLeftBrace = parseIfThenElse(/*IfKind=*/nullptr, KeepIfBraces);2939if (Style.RemoveBracesLLVM)2940NestedTooDeep.push_back(TooDeep);2941if (IsPrecededByComment)2942--Line->Level;2943} else {2944parseUnbracedBody(/*CheckEOF=*/true);2945}2946} else {2947KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;2948if (NeedsUnwrappedLine)2949addUnwrappedLine();2950}29512952if (!Style.RemoveBracesLLVM)2953return nullptr;29542955assert(!NestedTooDeep.empty());2956KeepElseBraces = KeepElseBraces ||2957(ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||2958NestedTooDeep.back();29592960NestedTooDeep.pop_back();29612962if (!KeepIfBraces && !KeepElseBraces) {2963markOptionalBraces(IfLeftBrace);2964markOptionalBraces(ElseLeftBrace);2965} else if (IfLeftBrace) {2966FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;2967if (IfRightBrace) {2968assert(IfRightBrace->MatchingParen == IfLeftBrace);2969assert(!IfLeftBrace->Optional);2970assert(!IfRightBrace->Optional);2971IfLeftBrace->MatchingParen = nullptr;2972IfRightBrace->MatchingParen = nullptr;2973}2974}29752976if (IfKind)2977*IfKind = Kind;29782979return IfLeftBrace;2980}29812982void UnwrappedLineParser::parseTryCatch() {2983assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");2984nextToken();2985bool NeedsUnwrappedLine = false;2986bool HasCtorInitializer = false;2987if (FormatTok->is(tok::colon)) {2988auto *Colon = FormatTok;2989// We are in a function try block, what comes is an initializer list.2990nextToken();2991if (FormatTok->is(tok::identifier)) {2992HasCtorInitializer = true;2993Colon->setFinalizedType(TT_CtorInitializerColon);2994}29952996// In case identifiers were removed by clang-tidy, what might follow is2997// multiple commas in sequence - before the first identifier.2998while (FormatTok->is(tok::comma))2999nextToken();30003001while (FormatTok->is(tok::identifier)) {3002nextToken();3003if (FormatTok->is(tok::l_paren)) {3004parseParens();3005} else if (FormatTok->is(tok::l_brace)) {3006nextToken();3007parseBracedList();3008}30093010// In case identifiers were removed by clang-tidy, what might follow is3011// multiple commas in sequence - after the first identifier.3012while (FormatTok->is(tok::comma))3013nextToken();3014}3015}3016// Parse try with resource.3017if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren))3018parseParens();30193020keepAncestorBraces();30213022if (FormatTok->is(tok::l_brace)) {3023if (HasCtorInitializer)3024FormatTok->setFinalizedType(TT_FunctionLBrace);3025CompoundStatementIndenter Indenter(this, Style, Line->Level);3026parseBlock();3027if (Style.BraceWrapping.BeforeCatch)3028addUnwrappedLine();3029else3030NeedsUnwrappedLine = true;3031} else if (FormatTok->isNot(tok::kw_catch)) {3032// The C++ standard requires a compound-statement after a try.3033// If there's none, we try to assume there's a structuralElement3034// and try to continue.3035addUnwrappedLine();3036++Line->Level;3037parseStructuralElement();3038--Line->Level;3039}3040while (true) {3041if (FormatTok->is(tok::at))3042nextToken();3043if (!(FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except,3044tok::kw___finally) ||3045((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&3046FormatTok->is(Keywords.kw_finally)) ||3047(FormatTok->isObjCAtKeyword(tok::objc_catch) ||3048FormatTok->isObjCAtKeyword(tok::objc_finally)))) {3049break;3050}3051nextToken();3052while (FormatTok->isNot(tok::l_brace)) {3053if (FormatTok->is(tok::l_paren)) {3054parseParens();3055continue;3056}3057if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof)) {3058if (Style.RemoveBracesLLVM)3059NestedTooDeep.pop_back();3060return;3061}3062nextToken();3063}3064NeedsUnwrappedLine = false;3065Line->MustBeDeclaration = false;3066CompoundStatementIndenter Indenter(this, Style, Line->Level);3067parseBlock();3068if (Style.BraceWrapping.BeforeCatch)3069addUnwrappedLine();3070else3071NeedsUnwrappedLine = true;3072}30733074if (Style.RemoveBracesLLVM)3075NestedTooDeep.pop_back();30763077if (NeedsUnwrappedLine)3078addUnwrappedLine();3079}30803081void UnwrappedLineParser::parseNamespace() {3082assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&3083"'namespace' expected");30843085const FormatToken &InitialToken = *FormatTok;3086nextToken();3087if (InitialToken.is(TT_NamespaceMacro)) {3088parseParens();3089} else {3090while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,3091tok::l_square, tok::period, tok::l_paren) ||3092(Style.isCSharp() && FormatTok->is(tok::kw_union))) {3093if (FormatTok->is(tok::l_square))3094parseSquare();3095else if (FormatTok->is(tok::l_paren))3096parseParens();3097else3098nextToken();3099}3100}3101if (FormatTok->is(tok::l_brace)) {3102FormatTok->setFinalizedType(TT_NamespaceLBrace);31033104if (ShouldBreakBeforeBrace(Style, InitialToken))3105addUnwrappedLine();31063107unsigned AddLevels =3108Style.NamespaceIndentation == FormatStyle::NI_All ||3109(Style.NamespaceIndentation == FormatStyle::NI_Inner &&3110DeclarationScopeStack.size() > 1)3111? 1u3112: 0u;3113bool ManageWhitesmithsBraces =3114AddLevels == 0u &&3115Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;31163117// If we're in Whitesmiths mode, indent the brace if we're not indenting3118// the whole block.3119if (ManageWhitesmithsBraces)3120++Line->Level;31213122// Munch the semicolon after a namespace. This is more common than one would3123// think. Putting the semicolon into its own line is very ugly.3124parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true,3125/*KeepBraces=*/true, /*IfKind=*/nullptr,3126ManageWhitesmithsBraces);31273128addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);31293130if (ManageWhitesmithsBraces)3131--Line->Level;3132}3133// FIXME: Add error handling.3134}31353136void UnwrappedLineParser::parseNew() {3137assert(FormatTok->is(tok::kw_new) && "'new' expected");3138nextToken();31393140if (Style.isCSharp()) {3141do {3142// Handle constructor invocation, e.g. `new(field: value)`.3143if (FormatTok->is(tok::l_paren))3144parseParens();31453146// Handle array initialization syntax, e.g. `new[] {10, 20, 30}`.3147if (FormatTok->is(tok::l_brace))3148parseBracedList();31493150if (FormatTok->isOneOf(tok::semi, tok::comma))3151return;31523153nextToken();3154} while (!eof());3155}31563157if (Style.Language != FormatStyle::LK_Java)3158return;31593160// In Java, we can parse everything up to the parens, which aren't optional.3161do {3162// There should not be a ;, { or } before the new's open paren.3163if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))3164return;31653166// Consume the parens.3167if (FormatTok->is(tok::l_paren)) {3168parseParens();31693170// If there is a class body of an anonymous class, consume that as child.3171if (FormatTok->is(tok::l_brace))3172parseChildBlock();3173return;3174}3175nextToken();3176} while (!eof());3177}31783179void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {3180keepAncestorBraces();31813182if (isBlockBegin(*FormatTok)) {3183FormatTok->setFinalizedType(TT_ControlStatementLBrace);3184FormatToken *LeftBrace = FormatTok;3185CompoundStatementIndenter Indenter(this, Style, Line->Level);3186parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,3187/*MunchSemi=*/true, KeepBraces);3188setPreviousRBraceType(TT_ControlStatementRBrace);3189if (!KeepBraces) {3190assert(!NestedTooDeep.empty());3191if (!NestedTooDeep.back())3192markOptionalBraces(LeftBrace);3193}3194if (WrapRightBrace)3195addUnwrappedLine();3196} else {3197parseUnbracedBody();3198}31993200if (!KeepBraces)3201NestedTooDeep.pop_back();3202}32033204void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) {3205assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||3206(Style.isVerilog() &&3207FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,3208Keywords.kw_always_ff, Keywords.kw_always_latch,3209Keywords.kw_final, Keywords.kw_initial,3210Keywords.kw_foreach, Keywords.kw_forever,3211Keywords.kw_repeat))) &&3212"'for', 'while' or foreach macro expected");3213const bool KeepBraces = !Style.RemoveBracesLLVM ||3214!FormatTok->isOneOf(tok::kw_for, tok::kw_while);32153216nextToken();3217// JS' for await ( ...3218if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))3219nextToken();3220if (IsCpp && FormatTok->is(tok::kw_co_await))3221nextToken();3222if (HasParens && FormatTok->is(tok::l_paren)) {3223// The type is only set for Verilog basically because we were afraid to3224// change the existing behavior for loops. See the discussion on D121756 for3225// details.3226if (Style.isVerilog())3227FormatTok->setFinalizedType(TT_ConditionLParen);3228parseParens();3229}32303231if (Style.isVerilog()) {3232// Event control.3233parseVerilogSensitivityList();3234} else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&3235Tokens->getPreviousToken()->is(tok::r_paren)) {3236nextToken();3237addUnwrappedLine();3238return;3239}32403241handleAttributes();3242parseLoopBody(KeepBraces, /*WrapRightBrace=*/true);3243}32443245void UnwrappedLineParser::parseDoWhile() {3246assert(FormatTok->is(tok::kw_do) && "'do' expected");3247nextToken();32483249parseLoopBody(/*KeepBraces=*/true, Style.BraceWrapping.BeforeWhile);32503251// FIXME: Add error handling.3252if (FormatTok->isNot(tok::kw_while)) {3253addUnwrappedLine();3254return;3255}32563257FormatTok->setFinalizedType(TT_DoWhile);32583259// If in Whitesmiths mode, the line with the while() needs to be indented3260// to the same level as the block.3261if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)3262++Line->Level;32633264nextToken();3265parseStructuralElement();3266}32673268void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {3269nextToken();3270unsigned OldLineLevel = Line->Level;32713272if (LeftAlignLabel)3273Line->Level = 0;3274else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))3275--Line->Level;32763277if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&3278FormatTok->is(tok::l_brace)) {32793280CompoundStatementIndenter Indenter(this, Line->Level,3281Style.BraceWrapping.AfterCaseLabel,3282Style.BraceWrapping.IndentBraces);3283parseBlock();3284if (FormatTok->is(tok::kw_break)) {3285if (Style.BraceWrapping.AfterControlStatement ==3286FormatStyle::BWACS_Always) {3287addUnwrappedLine();3288if (!Style.IndentCaseBlocks &&3289Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {3290++Line->Level;3291}3292}3293parseStructuralElement();3294}3295addUnwrappedLine();3296} else {3297if (FormatTok->is(tok::semi))3298nextToken();3299addUnwrappedLine();3300}3301Line->Level = OldLineLevel;3302if (FormatTok->isNot(tok::l_brace)) {3303parseStructuralElement();3304addUnwrappedLine();3305}3306}33073308void UnwrappedLineParser::parseCaseLabel() {3309assert(FormatTok->is(tok::kw_case) && "'case' expected");3310auto *Case = FormatTok;33113312// FIXME: fix handling of complex expressions here.3313do {3314nextToken();3315if (FormatTok->is(tok::colon)) {3316FormatTok->setFinalizedType(TT_CaseLabelColon);3317break;3318}3319if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::arrow)) {3320FormatTok->setFinalizedType(TT_CaseLabelArrow);3321Case->setFinalizedType(TT_SwitchExpressionLabel);3322break;3323}3324} while (!eof());3325parseLabel();3326}33273328void UnwrappedLineParser::parseSwitch(bool IsExpr) {3329assert(FormatTok->is(tok::kw_switch) && "'switch' expected");3330nextToken();3331if (FormatTok->is(tok::l_paren))3332parseParens();33333334keepAncestorBraces();33353336if (FormatTok->is(tok::l_brace)) {3337CompoundStatementIndenter Indenter(this, Style, Line->Level);3338FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace3339: TT_ControlStatementLBrace);3340if (IsExpr)3341parseChildBlock();3342else3343parseBlock();3344setPreviousRBraceType(TT_ControlStatementRBrace);3345if (!IsExpr)3346addUnwrappedLine();3347} else {3348addUnwrappedLine();3349++Line->Level;3350parseStructuralElement();3351--Line->Level;3352}33533354if (Style.RemoveBracesLLVM)3355NestedTooDeep.pop_back();3356}33573358// Operators that can follow a C variable.3359static bool isCOperatorFollowingVar(tok::TokenKind Kind) {3360switch (Kind) {3361case tok::ampamp:3362case tok::ampequal:3363case tok::arrow:3364case tok::caret:3365case tok::caretequal:3366case tok::comma:3367case tok::ellipsis:3368case tok::equal:3369case tok::equalequal:3370case tok::exclaim:3371case tok::exclaimequal:3372case tok::greater:3373case tok::greaterequal:3374case tok::greatergreater:3375case tok::greatergreaterequal:3376case tok::l_paren:3377case tok::l_square:3378case tok::less:3379case tok::lessequal:3380case tok::lessless:3381case tok::lesslessequal:3382case tok::minus:3383case tok::minusequal:3384case tok::minusminus:3385case tok::percent:3386case tok::percentequal:3387case tok::period:3388case tok::pipe:3389case tok::pipeequal:3390case tok::pipepipe:3391case tok::plus:3392case tok::plusequal:3393case tok::plusplus:3394case tok::question:3395case tok::r_brace:3396case tok::r_paren:3397case tok::r_square:3398case tok::semi:3399case tok::slash:3400case tok::slashequal:3401case tok::star:3402case tok::starequal:3403return true;3404default:3405return false;3406}3407}34083409void UnwrappedLineParser::parseAccessSpecifier() {3410FormatToken *AccessSpecifierCandidate = FormatTok;3411nextToken();3412// Understand Qt's slots.3413if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))3414nextToken();3415// Otherwise, we don't know what it is, and we'd better keep the next token.3416if (FormatTok->is(tok::colon)) {3417nextToken();3418addUnwrappedLine();3419} else if (FormatTok->isNot(tok::coloncolon) &&3420!isCOperatorFollowingVar(FormatTok->Tok.getKind())) {3421// Not a variable name nor namespace name.3422addUnwrappedLine();3423} else if (AccessSpecifierCandidate) {3424// Consider the access specifier to be a C identifier.3425AccessSpecifierCandidate->Tok.setKind(tok::identifier);3426}3427}34283429/// \brief Parses a requires, decides if it is a clause or an expression.3430/// \pre The current token has to be the requires keyword.3431/// \returns true if it parsed a clause.3432bool UnwrappedLineParser::parseRequires() {3433assert(FormatTok->is(tok::kw_requires) && "'requires' expected");3434auto RequiresToken = FormatTok;34353436// We try to guess if it is a requires clause, or a requires expression. For3437// that we first consume the keyword and check the next token.3438nextToken();34393440switch (FormatTok->Tok.getKind()) {3441case tok::l_brace:3442// This can only be an expression, never a clause.3443parseRequiresExpression(RequiresToken);3444return false;3445case tok::l_paren:3446// Clauses and expression can start with a paren, it's unclear what we have.3447break;3448default:3449// All other tokens can only be a clause.3450parseRequiresClause(RequiresToken);3451return true;3452}34533454// Looking forward we would have to decide if there are function declaration3455// like arguments to the requires expression:3456// requires (T t) {3457// Or there is a constraint expression for the requires clause:3458// requires (C<T> && ...34593460// But first let's look behind.3461auto *PreviousNonComment = RequiresToken->getPreviousNonComment();34623463if (!PreviousNonComment ||3464PreviousNonComment->is(TT_RequiresExpressionLBrace)) {3465// If there is no token, or an expression left brace, we are a requires3466// clause within a requires expression.3467parseRequiresClause(RequiresToken);3468return true;3469}34703471switch (PreviousNonComment->Tok.getKind()) {3472case tok::greater:3473case tok::r_paren:3474case tok::kw_noexcept:3475case tok::kw_const:3476// This is a requires clause.3477parseRequiresClause(RequiresToken);3478return true;3479case tok::amp:3480case tok::ampamp: {3481// This can be either:3482// if (... && requires (T t) ...)3483// Or3484// void member(...) && requires (C<T> ...3485// We check the one token before that for a const:3486// void member(...) const && requires (C<T> ...3487auto PrevPrev = PreviousNonComment->getPreviousNonComment();3488if (PrevPrev && PrevPrev->is(tok::kw_const)) {3489parseRequiresClause(RequiresToken);3490return true;3491}3492break;3493}3494default:3495if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {3496// This is a requires clause.3497parseRequiresClause(RequiresToken);3498return true;3499}3500// It's an expression.3501parseRequiresExpression(RequiresToken);3502return false;3503}35043505// Now we look forward and try to check if the paren content is a parameter3506// list. The parameters can be cv-qualified and contain references or3507// pointers.3508// So we want basically to check for TYPE NAME, but TYPE can contain all kinds3509// of stuff: typename, const, *, &, &&, ::, identifiers.35103511unsigned StoredPosition = Tokens->getPosition();3512FormatToken *NextToken = Tokens->getNextToken();3513int Lookahead = 0;3514auto PeekNext = [&Lookahead, &NextToken, this] {3515++Lookahead;3516NextToken = Tokens->getNextToken();3517};35183519bool FoundType = false;3520bool LastWasColonColon = false;3521int OpenAngles = 0;35223523for (; Lookahead < 50; PeekNext()) {3524switch (NextToken->Tok.getKind()) {3525case tok::kw_volatile:3526case tok::kw_const:3527case tok::comma:3528if (OpenAngles == 0) {3529FormatTok = Tokens->setPosition(StoredPosition);3530parseRequiresExpression(RequiresToken);3531return false;3532}3533break;3534case tok::eof:3535// Break out of the loop.3536Lookahead = 50;3537break;3538case tok::coloncolon:3539LastWasColonColon = true;3540break;3541case tok::kw_decltype:3542case tok::identifier:3543if (FoundType && !LastWasColonColon && OpenAngles == 0) {3544FormatTok = Tokens->setPosition(StoredPosition);3545parseRequiresExpression(RequiresToken);3546return false;3547}3548FoundType = true;3549LastWasColonColon = false;3550break;3551case tok::less:3552++OpenAngles;3553break;3554case tok::greater:3555--OpenAngles;3556break;3557default:3558if (NextToken->isTypeName(LangOpts)) {3559FormatTok = Tokens->setPosition(StoredPosition);3560parseRequiresExpression(RequiresToken);3561return false;3562}3563break;3564}3565}3566// This seems to be a complicated expression, just assume it's a clause.3567FormatTok = Tokens->setPosition(StoredPosition);3568parseRequiresClause(RequiresToken);3569return true;3570}35713572/// \brief Parses a requires clause.3573/// \param RequiresToken The requires keyword token, which starts this clause.3574/// \pre We need to be on the next token after the requires keyword.3575/// \sa parseRequiresExpression3576///3577/// Returns if it either has finished parsing the clause, or it detects, that3578/// the clause is incorrect.3579void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) {3580assert(FormatTok->getPreviousNonComment() == RequiresToken);3581assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");35823583// If there is no previous token, we are within a requires expression,3584// otherwise we will always have the template or function declaration in front3585// of it.3586bool InRequiresExpression =3587!RequiresToken->Previous ||3588RequiresToken->Previous->is(TT_RequiresExpressionLBrace);35893590RequiresToken->setFinalizedType(InRequiresExpression3591? TT_RequiresClauseInARequiresExpression3592: TT_RequiresClause);35933594// NOTE: parseConstraintExpression is only ever called from this function.3595// It could be inlined into here.3596parseConstraintExpression();35973598if (!InRequiresExpression)3599FormatTok->Previous->ClosesRequiresClause = true;3600}36013602/// \brief Parses a requires expression.3603/// \param RequiresToken The requires keyword token, which starts this clause.3604/// \pre We need to be on the next token after the requires keyword.3605/// \sa parseRequiresClause3606///3607/// Returns if it either has finished parsing the expression, or it detects,3608/// that the expression is incorrect.3609void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) {3610assert(FormatTok->getPreviousNonComment() == RequiresToken);3611assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");36123613RequiresToken->setFinalizedType(TT_RequiresExpression);36143615if (FormatTok->is(tok::l_paren)) {3616FormatTok->setFinalizedType(TT_RequiresExpressionLParen);3617parseParens();3618}36193620if (FormatTok->is(tok::l_brace)) {3621FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);3622parseChildBlock();3623}3624}36253626/// \brief Parses a constraint expression.3627///3628/// This is the body of a requires clause. It returns, when the parsing is3629/// complete, or the expression is incorrect.3630void UnwrappedLineParser::parseConstraintExpression() {3631// The special handling for lambdas is needed since tryToParseLambda() eats a3632// token and if a requires expression is the last part of a requires clause3633// and followed by an attribute like [[nodiscard]] the ClosesRequiresClause is3634// not set on the correct token. Thus we need to be aware if we even expect a3635// lambda to be possible.3636// template <typename T> requires requires { ... } [[nodiscard]] ...;3637bool LambdaNextTimeAllowed = true;36383639// Within lambda declarations, it is permitted to put a requires clause after3640// its template parameter list, which would place the requires clause right3641// before the parentheses of the parameters of the lambda declaration. Thus,3642// we track if we expect to see grouping parentheses at all.3643// Without this check, `requires foo<T> (T t)` in the below example would be3644// seen as the whole requires clause, accidentally eating the parameters of3645// the lambda.3646// [&]<typename T> requires foo<T> (T t) { ... };3647bool TopLevelParensAllowed = true;36483649do {3650bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false);36513652switch (FormatTok->Tok.getKind()) {3653case tok::kw_requires: {3654auto RequiresToken = FormatTok;3655nextToken();3656parseRequiresExpression(RequiresToken);3657break;3658}36593660case tok::l_paren:3661if (!TopLevelParensAllowed)3662return;3663parseParens(/*AmpAmpTokenType=*/TT_BinaryOperator);3664TopLevelParensAllowed = false;3665break;36663667case tok::l_square:3668if (!LambdaThisTimeAllowed || !tryToParseLambda())3669return;3670break;36713672case tok::kw_const:3673case tok::semi:3674case tok::kw_class:3675case tok::kw_struct:3676case tok::kw_union:3677return;36783679case tok::l_brace:3680// Potential function body.3681return;36823683case tok::ampamp:3684case tok::pipepipe:3685FormatTok->setFinalizedType(TT_BinaryOperator);3686nextToken();3687LambdaNextTimeAllowed = true;3688TopLevelParensAllowed = true;3689break;36903691case tok::comma:3692case tok::comment:3693LambdaNextTimeAllowed = LambdaThisTimeAllowed;3694nextToken();3695break;36963697case tok::kw_sizeof:3698case tok::greater:3699case tok::greaterequal:3700case tok::greatergreater:3701case tok::less:3702case tok::lessequal:3703case tok::lessless:3704case tok::equalequal:3705case tok::exclaim:3706case tok::exclaimequal:3707case tok::plus:3708case tok::minus:3709case tok::star:3710case tok::slash:3711LambdaNextTimeAllowed = true;3712TopLevelParensAllowed = true;3713// Just eat them.3714nextToken();3715break;37163717case tok::numeric_constant:3718case tok::coloncolon:3719case tok::kw_true:3720case tok::kw_false:3721TopLevelParensAllowed = false;3722// Just eat them.3723nextToken();3724break;37253726case tok::kw_static_cast:3727case tok::kw_const_cast:3728case tok::kw_reinterpret_cast:3729case tok::kw_dynamic_cast:3730nextToken();3731if (FormatTok->isNot(tok::less))3732return;37333734nextToken();3735parseBracedList(/*IsAngleBracket=*/true);3736break;37373738default:3739if (!FormatTok->Tok.getIdentifierInfo()) {3740// Identifiers are part of the default case, we check for more then3741// tok::identifier to handle builtin type traits.3742return;3743}37443745// We need to differentiate identifiers for a template deduction guide,3746// variables, or function return types (the constraint expression has3747// ended before that), and basically all other cases. But it's easier to3748// check the other way around.3749assert(FormatTok->Previous);3750switch (FormatTok->Previous->Tok.getKind()) {3751case tok::coloncolon: // Nested identifier.3752case tok::ampamp: // Start of a function or variable for the3753case tok::pipepipe: // constraint expression. (binary)3754case tok::exclaim: // The same as above, but unary.3755case tok::kw_requires: // Initial identifier of a requires clause.3756case tok::equal: // Initial identifier of a concept declaration.3757break;3758default:3759return;3760}37613762// Read identifier with optional template declaration.3763nextToken();3764if (FormatTok->is(tok::less)) {3765nextToken();3766parseBracedList(/*IsAngleBracket=*/true);3767}3768TopLevelParensAllowed = false;3769break;3770}3771} while (!eof());3772}37733774bool UnwrappedLineParser::parseEnum() {3775const FormatToken &InitialToken = *FormatTok;37763777// Won't be 'enum' for NS_ENUMs.3778if (FormatTok->is(tok::kw_enum))3779nextToken();37803781// In TypeScript, "enum" can also be used as property name, e.g. in interface3782// declarations. An "enum" keyword followed by a colon would be a syntax3783// error and thus assume it is just an identifier.3784if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))3785return false;37863787// In protobuf, "enum" can be used as a field name.3788if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))3789return false;37903791if (IsCpp) {3792// Eat up enum class ...3793if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))3794nextToken();3795while (FormatTok->is(tok::l_square))3796if (!handleCppAttributes())3797return false;3798}37993800while (FormatTok->Tok.getIdentifierInfo() ||3801FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,3802tok::greater, tok::comma, tok::question,3803tok::l_square)) {3804if (Style.isVerilog()) {3805FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);3806nextToken();3807// In Verilog the base type can have dimensions.3808while (FormatTok->is(tok::l_square))3809parseSquare();3810} else {3811nextToken();3812}3813// We can have macros or attributes in between 'enum' and the enum name.3814if (FormatTok->is(tok::l_paren))3815parseParens();3816if (FormatTok->is(tok::identifier)) {3817nextToken();3818// If there are two identifiers in a row, this is likely an elaborate3819// return type. In Java, this can be "implements", etc.3820if (IsCpp && FormatTok->is(tok::identifier))3821return false;3822}3823}38243825// Just a declaration or something is wrong.3826if (FormatTok->isNot(tok::l_brace))3827return true;3828FormatTok->setFinalizedType(TT_EnumLBrace);3829FormatTok->setBlockKind(BK_Block);38303831if (Style.Language == FormatStyle::LK_Java) {3832// Java enums are different.3833parseJavaEnumBody();3834return true;3835}3836if (Style.Language == FormatStyle::LK_Proto) {3837parseBlock(/*MustBeDeclaration=*/true);3838return true;3839}38403841if (!Style.AllowShortEnumsOnASingleLine &&3842ShouldBreakBeforeBrace(Style, InitialToken)) {3843addUnwrappedLine();3844}3845// Parse enum body.3846nextToken();3847if (!Style.AllowShortEnumsOnASingleLine) {3848addUnwrappedLine();3849Line->Level += 1;3850}3851bool HasError = !parseBracedList(/*IsAngleBracket=*/false, /*IsEnum=*/true);3852if (!Style.AllowShortEnumsOnASingleLine)3853Line->Level -= 1;3854if (HasError) {3855if (FormatTok->is(tok::semi))3856nextToken();3857addUnwrappedLine();3858}3859setPreviousRBraceType(TT_EnumRBrace);3860return true;38613862// There is no addUnwrappedLine() here so that we fall through to parsing a3863// structural element afterwards. Thus, in "enum A {} n, m;",3864// "} n, m;" will end up in one unwrapped line.3865}38663867bool UnwrappedLineParser::parseStructLike() {3868// parseRecord falls through and does not yet add an unwrapped line as a3869// record declaration or definition can start a structural element.3870parseRecord();3871// This does not apply to Java, JavaScript and C#.3872if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||3873Style.isCSharp()) {3874if (FormatTok->is(tok::semi))3875nextToken();3876addUnwrappedLine();3877return true;3878}3879return false;3880}38813882namespace {3883// A class used to set and restore the Token position when peeking3884// ahead in the token source.3885class ScopedTokenPosition {3886unsigned StoredPosition;3887FormatTokenSource *Tokens;38883889public:3890ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {3891assert(Tokens && "Tokens expected to not be null");3892StoredPosition = Tokens->getPosition();3893}38943895~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }3896};3897} // namespace38983899// Look to see if we have [[ by looking ahead, if3900// its not then rewind to the original position.3901bool UnwrappedLineParser::tryToParseSimpleAttribute() {3902ScopedTokenPosition AutoPosition(Tokens);3903FormatToken *Tok = Tokens->getNextToken();3904// We already read the first [ check for the second.3905if (Tok->isNot(tok::l_square))3906return false;3907// Double check that the attribute is just something3908// fairly simple.3909while (Tok->isNot(tok::eof)) {3910if (Tok->is(tok::r_square))3911break;3912Tok = Tokens->getNextToken();3913}3914if (Tok->is(tok::eof))3915return false;3916Tok = Tokens->getNextToken();3917if (Tok->isNot(tok::r_square))3918return false;3919Tok = Tokens->getNextToken();3920if (Tok->is(tok::semi))3921return false;3922return true;3923}39243925void UnwrappedLineParser::parseJavaEnumBody() {3926assert(FormatTok->is(tok::l_brace));3927const FormatToken *OpeningBrace = FormatTok;39283929// Determine whether the enum is simple, i.e. does not have a semicolon or3930// constants with class bodies. Simple enums can be formatted like braced3931// lists, contracted to a single line, etc.3932unsigned StoredPosition = Tokens->getPosition();3933bool IsSimple = true;3934FormatToken *Tok = Tokens->getNextToken();3935while (Tok->isNot(tok::eof)) {3936if (Tok->is(tok::r_brace))3937break;3938if (Tok->isOneOf(tok::l_brace, tok::semi)) {3939IsSimple = false;3940break;3941}3942// FIXME: This will also mark enums with braces in the arguments to enum3943// constants as "not simple". This is probably fine in practice, though.3944Tok = Tokens->getNextToken();3945}3946FormatTok = Tokens->setPosition(StoredPosition);39473948if (IsSimple) {3949nextToken();3950parseBracedList();3951addUnwrappedLine();3952return;3953}39543955// Parse the body of a more complex enum.3956// First add a line for everything up to the "{".3957nextToken();3958addUnwrappedLine();3959++Line->Level;39603961// Parse the enum constants.3962while (!eof()) {3963if (FormatTok->is(tok::l_brace)) {3964// Parse the constant's class body.3965parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u,3966/*MunchSemi=*/false);3967} else if (FormatTok->is(tok::l_paren)) {3968parseParens();3969} else if (FormatTok->is(tok::comma)) {3970nextToken();3971addUnwrappedLine();3972} else if (FormatTok->is(tok::semi)) {3973nextToken();3974addUnwrappedLine();3975break;3976} else if (FormatTok->is(tok::r_brace)) {3977addUnwrappedLine();3978break;3979} else {3980nextToken();3981}3982}39833984// Parse the class body after the enum's ";" if any.3985parseLevel(OpeningBrace);3986nextToken();3987--Line->Level;3988addUnwrappedLine();3989}39903991void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {3992const FormatToken &InitialToken = *FormatTok;3993nextToken();39943995const FormatToken *ClassName = nullptr;3996bool IsDerived = false;3997auto IsNonMacroIdentifier = [](const FormatToken *Tok) {3998return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();3999};4000// JavaScript/TypeScript supports anonymous classes like:4001// a = class extends foo { }4002bool JSPastExtendsOrImplements = false;4003// The actual identifier can be a nested name specifier, and in macros4004// it is often token-pasted.4005// An [[attribute]] can be before the identifier.4006while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,4007tok::kw_alignas, tok::l_square) ||4008FormatTok->isAttribute() ||4009((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&4010FormatTok->isOneOf(tok::period, tok::comma))) {4011if (Style.isJavaScript() &&4012FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {4013JSPastExtendsOrImplements = true;4014// JavaScript/TypeScript supports inline object types in4015// extends/implements positions:4016// class Foo implements {bar: number} { }4017nextToken();4018if (FormatTok->is(tok::l_brace)) {4019tryToParseBracedList();4020continue;4021}4022}4023if (FormatTok->is(tok::l_square) && handleCppAttributes())4024continue;4025const auto *Previous = FormatTok;4026nextToken();4027switch (FormatTok->Tok.getKind()) {4028case tok::l_paren:4029// We can have macros in between 'class' and the class name.4030if (!IsNonMacroIdentifier(Previous) ||4031// e.g. `struct macro(a) S { int i; };`4032Previous->Previous == &InitialToken) {4033parseParens();4034}4035break;4036case tok::coloncolon:4037case tok::hashhash:4038break;4039default:4040if (!JSPastExtendsOrImplements && !ClassName &&4041Previous->is(tok::identifier) && Previous->isNot(TT_AttributeMacro)) {4042ClassName = Previous;4043}4044}4045}40464047auto IsListInitialization = [&] {4048if (!ClassName || IsDerived)4049return false;4050assert(FormatTok->is(tok::l_brace));4051const auto *Prev = FormatTok->getPreviousNonComment();4052assert(Prev);4053return Prev != ClassName && Prev->is(tok::identifier) &&4054Prev->isNot(Keywords.kw_final) && tryToParseBracedList();4055};40564057if (FormatTok->isOneOf(tok::colon, tok::less)) {4058int AngleNestingLevel = 0;4059do {4060if (FormatTok->is(tok::less))4061++AngleNestingLevel;4062else if (FormatTok->is(tok::greater))4063--AngleNestingLevel;40644065if (AngleNestingLevel == 0) {4066if (FormatTok->is(tok::colon)) {4067IsDerived = true;4068} else if (FormatTok->is(tok::identifier) &&4069FormatTok->Previous->is(tok::coloncolon)) {4070ClassName = FormatTok;4071} else if (FormatTok->is(tok::l_paren) &&4072IsNonMacroIdentifier(FormatTok->Previous)) {4073break;4074}4075}4076if (FormatTok->is(tok::l_brace)) {4077if (AngleNestingLevel == 0 && IsListInitialization())4078return;4079calculateBraceTypes(/*ExpectClassBody=*/true);4080if (!tryToParseBracedList())4081break;4082}4083if (FormatTok->is(tok::l_square)) {4084FormatToken *Previous = FormatTok->Previous;4085if (!Previous || (Previous->isNot(tok::r_paren) &&4086!Previous->isTypeOrIdentifier(LangOpts))) {4087// Don't try parsing a lambda if we had a closing parenthesis before,4088// it was probably a pointer to an array: int (*)[].4089if (!tryToParseLambda())4090continue;4091} else {4092parseSquare();4093continue;4094}4095}4096if (FormatTok->is(tok::semi))4097return;4098if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {4099addUnwrappedLine();4100nextToken();4101parseCSharpGenericTypeConstraint();4102break;4103}4104nextToken();4105} while (!eof());4106}41074108auto GetBraceTypes =4109[](const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {4110switch (RecordTok.Tok.getKind()) {4111case tok::kw_class:4112return {TT_ClassLBrace, TT_ClassRBrace};4113case tok::kw_struct:4114return {TT_StructLBrace, TT_StructRBrace};4115case tok::kw_union:4116return {TT_UnionLBrace, TT_UnionRBrace};4117default:4118// Useful for e.g. interface.4119return {TT_RecordLBrace, TT_RecordRBrace};4120}4121};4122if (FormatTok->is(tok::l_brace)) {4123if (IsListInitialization())4124return;4125auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);4126FormatTok->setFinalizedType(OpenBraceType);4127if (ParseAsExpr) {4128parseChildBlock();4129} else {4130if (ShouldBreakBeforeBrace(Style, InitialToken))4131addUnwrappedLine();41324133unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;4134parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/false);4135}4136setPreviousRBraceType(ClosingBraceType);4137}4138// There is no addUnwrappedLine() here so that we fall through to parsing a4139// structural element afterwards. Thus, in "class A {} n, m;",4140// "} n, m;" will end up in one unwrapped line.4141}41424143void UnwrappedLineParser::parseObjCMethod() {4144assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&4145"'(' or identifier expected.");4146do {4147if (FormatTok->is(tok::semi)) {4148nextToken();4149addUnwrappedLine();4150return;4151} else if (FormatTok->is(tok::l_brace)) {4152if (Style.BraceWrapping.AfterFunction)4153addUnwrappedLine();4154parseBlock();4155addUnwrappedLine();4156return;4157} else {4158nextToken();4159}4160} while (!eof());4161}41624163void UnwrappedLineParser::parseObjCProtocolList() {4164assert(FormatTok->is(tok::less) && "'<' expected.");4165do {4166nextToken();4167// Early exit in case someone forgot a close angle.4168if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||4169FormatTok->isObjCAtKeyword(tok::objc_end)) {4170return;4171}4172} while (!eof() && FormatTok->isNot(tok::greater));4173nextToken(); // Skip '>'.4174}41754176void UnwrappedLineParser::parseObjCUntilAtEnd() {4177do {4178if (FormatTok->isObjCAtKeyword(tok::objc_end)) {4179nextToken();4180addUnwrappedLine();4181break;4182}4183if (FormatTok->is(tok::l_brace)) {4184parseBlock();4185// In ObjC interfaces, nothing should be following the "}".4186addUnwrappedLine();4187} else if (FormatTok->is(tok::r_brace)) {4188// Ignore stray "}". parseStructuralElement doesn't consume them.4189nextToken();4190addUnwrappedLine();4191} else if (FormatTok->isOneOf(tok::minus, tok::plus)) {4192nextToken();4193parseObjCMethod();4194} else {4195parseStructuralElement();4196}4197} while (!eof());4198}41994200void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {4201assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_interface ||4202FormatTok->Tok.getObjCKeywordID() == tok::objc_implementation);4203nextToken();4204nextToken(); // interface name42054206// @interface can be followed by a lightweight generic4207// specialization list, then either a base class or a category.4208if (FormatTok->is(tok::less))4209parseObjCLightweightGenerics();4210if (FormatTok->is(tok::colon)) {4211nextToken();4212nextToken(); // base class name4213// The base class can also have lightweight generics applied to it.4214if (FormatTok->is(tok::less))4215parseObjCLightweightGenerics();4216} else if (FormatTok->is(tok::l_paren)) {4217// Skip category, if present.4218parseParens();4219}42204221if (FormatTok->is(tok::less))4222parseObjCProtocolList();42234224if (FormatTok->is(tok::l_brace)) {4225if (Style.BraceWrapping.AfterObjCDeclaration)4226addUnwrappedLine();4227parseBlock(/*MustBeDeclaration=*/true);4228}42294230// With instance variables, this puts '}' on its own line. Without instance4231// variables, this ends the @interface line.4232addUnwrappedLine();42334234parseObjCUntilAtEnd();4235}42364237void UnwrappedLineParser::parseObjCLightweightGenerics() {4238assert(FormatTok->is(tok::less));4239// Unlike protocol lists, generic parameterizations support4240// nested angles:4241//4242// @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :4243// NSObject <NSCopying, NSSecureCoding>4244//4245// so we need to count how many open angles we have left.4246unsigned NumOpenAngles = 1;4247do {4248nextToken();4249// Early exit in case someone forgot a close angle.4250if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||4251FormatTok->isObjCAtKeyword(tok::objc_end)) {4252break;4253}4254if (FormatTok->is(tok::less)) {4255++NumOpenAngles;4256} else if (FormatTok->is(tok::greater)) {4257assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");4258--NumOpenAngles;4259}4260} while (!eof() && NumOpenAngles != 0);4261nextToken(); // Skip '>'.4262}42634264// Returns true for the declaration/definition form of @protocol,4265// false for the expression form.4266bool UnwrappedLineParser::parseObjCProtocol() {4267assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_protocol);4268nextToken();42694270if (FormatTok->is(tok::l_paren)) {4271// The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);".4272return false;4273}42744275// The definition/declaration form,4276// @protocol Foo4277// - (int)someMethod;4278// @end42794280nextToken(); // protocol name42814282if (FormatTok->is(tok::less))4283parseObjCProtocolList();42844285// Check for protocol declaration.4286if (FormatTok->is(tok::semi)) {4287nextToken();4288addUnwrappedLine();4289return true;4290}42914292addUnwrappedLine();4293parseObjCUntilAtEnd();4294return true;4295}42964297void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {4298bool IsImport = FormatTok->is(Keywords.kw_import);4299assert(IsImport || FormatTok->is(tok::kw_export));4300nextToken();43014302// Consume the "default" in "export default class/function".4303if (FormatTok->is(tok::kw_default))4304nextToken();43054306// Consume "async function", "function" and "default function", so that these4307// get parsed as free-standing JS functions, i.e. do not require a trailing4308// semicolon.4309if (FormatTok->is(Keywords.kw_async))4310nextToken();4311if (FormatTok->is(Keywords.kw_function)) {4312nextToken();4313return;4314}43154316// For imports, `export *`, `export {...}`, consume the rest of the line up4317// to the terminating `;`. For everything else, just return and continue4318// parsing the structural element, i.e. the declaration or expression for4319// `export default`.4320if (!IsImport && !FormatTok->isOneOf(tok::l_brace, tok::star) &&4321!FormatTok->isStringLiteral() &&4322!(FormatTok->is(Keywords.kw_type) &&4323Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {4324return;4325}43264327while (!eof()) {4328if (FormatTok->is(tok::semi))4329return;4330if (Line->Tokens.empty()) {4331// Common issue: Automatic Semicolon Insertion wrapped the line, so the4332// import statement should terminate.4333return;4334}4335if (FormatTok->is(tok::l_brace)) {4336FormatTok->setBlockKind(BK_Block);4337nextToken();4338parseBracedList();4339} else {4340nextToken();4341}4342}4343}43444345void UnwrappedLineParser::parseStatementMacro() {4346nextToken();4347if (FormatTok->is(tok::l_paren))4348parseParens();4349if (FormatTok->is(tok::semi))4350nextToken();4351addUnwrappedLine();4352}43534354void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {4355// consume things like a::`b.c[d:e] or a::*4356while (true) {4357if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,4358tok::coloncolon, tok::hash) ||4359Keywords.isVerilogIdentifier(*FormatTok)) {4360nextToken();4361} else if (FormatTok->is(tok::l_square)) {4362parseSquare();4363} else {4364break;4365}4366}4367}43684369void UnwrappedLineParser::parseVerilogSensitivityList() {4370if (FormatTok->isNot(tok::at))4371return;4372nextToken();4373// A block event expression has 2 at signs.4374if (FormatTok->is(tok::at))4375nextToken();4376switch (FormatTok->Tok.getKind()) {4377case tok::star:4378nextToken();4379break;4380case tok::l_paren:4381parseParens();4382break;4383default:4384parseVerilogHierarchyIdentifier();4385break;4386}4387}43884389unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {4390unsigned AddLevels = 0;43914392if (FormatTok->is(Keywords.kw_clocking)) {4393nextToken();4394if (Keywords.isVerilogIdentifier(*FormatTok))4395nextToken();4396parseVerilogSensitivityList();4397if (FormatTok->is(tok::semi))4398nextToken();4399} else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,4400Keywords.kw_casez, Keywords.kw_randcase,4401Keywords.kw_randsequence)) {4402if (Style.IndentCaseLabels)4403AddLevels++;4404nextToken();4405if (FormatTok->is(tok::l_paren)) {4406FormatTok->setFinalizedType(TT_ConditionLParen);4407parseParens();4408}4409if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))4410nextToken();4411// The case header has no semicolon.4412} else {4413// "module" etc.4414nextToken();4415// all the words like the name of the module and specifiers like4416// "automatic" and the width of function return type4417while (true) {4418if (FormatTok->is(tok::l_square)) {4419auto Prev = FormatTok->getPreviousNonComment();4420if (Prev && Keywords.isVerilogIdentifier(*Prev))4421Prev->setFinalizedType(TT_VerilogDimensionedTypeName);4422parseSquare();4423} else if (Keywords.isVerilogIdentifier(*FormatTok) ||4424FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) {4425nextToken();4426} else {4427break;4428}4429}44304431auto NewLine = [this]() {4432addUnwrappedLine();4433Line->IsContinuation = true;4434};44354436// package imports4437while (FormatTok->is(Keywords.kw_import)) {4438NewLine();4439nextToken();4440parseVerilogHierarchyIdentifier();4441if (FormatTok->is(tok::semi))4442nextToken();4443}44444445// parameters and ports4446if (FormatTok->is(Keywords.kw_verilogHash)) {4447NewLine();4448nextToken();4449if (FormatTok->is(tok::l_paren)) {4450FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);4451parseParens();4452}4453}4454if (FormatTok->is(tok::l_paren)) {4455NewLine();4456FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);4457parseParens();4458}44594460// extends and implements4461if (FormatTok->is(Keywords.kw_extends)) {4462NewLine();4463nextToken();4464parseVerilogHierarchyIdentifier();4465if (FormatTok->is(tok::l_paren))4466parseParens();4467}4468if (FormatTok->is(Keywords.kw_implements)) {4469NewLine();4470do {4471nextToken();4472parseVerilogHierarchyIdentifier();4473} while (FormatTok->is(tok::comma));4474}44754476// Coverage event for cover groups.4477if (FormatTok->is(tok::at)) {4478NewLine();4479parseVerilogSensitivityList();4480}44814482if (FormatTok->is(tok::semi))4483nextToken(/*LevelDifference=*/1);4484addUnwrappedLine();4485}44864487return AddLevels;4488}44894490void UnwrappedLineParser::parseVerilogTable() {4491assert(FormatTok->is(Keywords.kw_table));4492nextToken(/*LevelDifference=*/1);4493addUnwrappedLine();44944495auto InitialLevel = Line->Level++;4496while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) {4497FormatToken *Tok = FormatTok;4498nextToken();4499if (Tok->is(tok::semi))4500addUnwrappedLine();4501else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus))4502Tok->setFinalizedType(TT_VerilogTableItem);4503}4504Line->Level = InitialLevel;4505nextToken(/*LevelDifference=*/-1);4506addUnwrappedLine();4507}45084509void UnwrappedLineParser::parseVerilogCaseLabel() {4510// The label will get unindented in AnnotatingParser. If there are no leading4511// spaces, indent the rest here so that things inside the block will be4512// indented relative to things outside. We don't use parseLabel because we4513// don't know whether this colon is a label or a ternary expression at this4514// point.4515auto OrigLevel = Line->Level;4516auto FirstLine = CurrentLines->size();4517if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1))4518++Line->Level;4519else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))4520--Line->Level;4521parseStructuralElement();4522// Restore the indentation in both the new line and the line that has the4523// label.4524if (CurrentLines->size() > FirstLine)4525(*CurrentLines)[FirstLine].Level = OrigLevel;4526Line->Level = OrigLevel;4527}45284529bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const {4530for (const auto &N : Line.Tokens) {4531if (N.Tok->MacroCtx)4532return true;4533for (const UnwrappedLine &Child : N.Children)4534if (containsExpansion(Child))4535return true;4536}4537return false;4538}45394540void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {4541if (Line->Tokens.empty())4542return;4543LLVM_DEBUG({4544if (!parsingPPDirective()) {4545llvm::dbgs() << "Adding unwrapped line:\n";4546printDebugInfo(*Line);4547}4548});45494550// If this line closes a block when in Whitesmiths mode, remember that4551// information so that the level can be decreased after the line is added.4552// This has to happen after the addition of the line since the line itself4553// needs to be indented.4554bool ClosesWhitesmithsBlock =4555Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&4556Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;45574558// If the current line was expanded from a macro call, we use it to4559// reconstruct an unwrapped line from the structure of the expanded unwrapped4560// line and the unexpanded token stream.4561if (!parsingPPDirective() && !InExpansion && containsExpansion(*Line)) {4562if (!Reconstruct)4563Reconstruct.emplace(Line->Level, Unexpanded);4564Reconstruct->addLine(*Line);45654566// While the reconstructed unexpanded lines are stored in the normal4567// flow of lines, the expanded lines are stored on the side to be analyzed4568// in an extra step.4569CurrentExpandedLines.push_back(std::move(*Line));45704571if (Reconstruct->finished()) {4572UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();4573assert(!Reconstructed.Tokens.empty() &&4574"Reconstructed must at least contain the macro identifier.");4575assert(!parsingPPDirective());4576LLVM_DEBUG({4577llvm::dbgs() << "Adding unexpanded line:\n";4578printDebugInfo(Reconstructed);4579});4580ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;4581Lines.push_back(std::move(Reconstructed));4582CurrentExpandedLines.clear();4583Reconstruct.reset();4584}4585} else {4586// At the top level we only get here when no unexpansion is going on, or4587// when conditional formatting led to unfinished macro reconstructions.4588assert(!Reconstruct || (CurrentLines != &Lines) || PPStack.size() > 0);4589CurrentLines->push_back(std::move(*Line));4590}4591Line->Tokens.clear();4592Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;4593Line->FirstStartColumn = 0;4594Line->IsContinuation = false;4595Line->SeenDecltypeAuto = false;45964597if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)4598--Line->Level;4599if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {4600CurrentLines->append(4601std::make_move_iterator(PreprocessorDirectives.begin()),4602std::make_move_iterator(PreprocessorDirectives.end()));4603PreprocessorDirectives.clear();4604}4605// Disconnect the current token from the last token on the previous line.4606FormatTok->Previous = nullptr;4607}46084609bool UnwrappedLineParser::eof() const { return FormatTok->is(tok::eof); }46104611bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {4612return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&4613FormatTok.NewlinesBefore > 0;4614}46154616// Checks if \p FormatTok is a line comment that continues the line comment4617// section on \p Line.4618static bool4619continuesLineCommentSection(const FormatToken &FormatTok,4620const UnwrappedLine &Line,4621const llvm::Regex &CommentPragmasRegex) {4622if (Line.Tokens.empty())4623return false;46244625StringRef IndentContent = FormatTok.TokenText;4626if (FormatTok.TokenText.starts_with("//") ||4627FormatTok.TokenText.starts_with("/*")) {4628IndentContent = FormatTok.TokenText.substr(2);4629}4630if (CommentPragmasRegex.match(IndentContent))4631return false;46324633// If Line starts with a line comment, then FormatTok continues the comment4634// section if its original column is greater or equal to the original start4635// column of the line.4636//4637// Define the min column token of a line as follows: if a line ends in '{' or4638// contains a '{' followed by a line comment, then the min column token is4639// that '{'. Otherwise, the min column token of the line is the first token of4640// the line.4641//4642// If Line starts with a token other than a line comment, then FormatTok4643// continues the comment section if its original column is greater than the4644// original start column of the min column token of the line.4645//4646// For example, the second line comment continues the first in these cases:4647//4648// // first line4649// // second line4650//4651// and:4652//4653// // first line4654// // second line4655//4656// and:4657//4658// int i; // first line4659// // second line4660//4661// and:4662//4663// do { // first line4664// // second line4665// int i;4666// } while (true);4667//4668// and:4669//4670// enum {4671// a, // first line4672// // second line4673// b4674// };4675//4676// The second line comment doesn't continue the first in these cases:4677//4678// // first line4679// // second line4680//4681// and:4682//4683// int i; // first line4684// // second line4685//4686// and:4687//4688// do { // first line4689// // second line4690// int i;4691// } while (true);4692//4693// and:4694//4695// enum {4696// a, // first line4697// // second line4698// };4699const FormatToken *MinColumnToken = Line.Tokens.front().Tok;47004701// Scan for '{//'. If found, use the column of '{' as a min column for line4702// comment section continuation.4703const FormatToken *PreviousToken = nullptr;4704for (const UnwrappedLineNode &Node : Line.Tokens) {4705if (PreviousToken && PreviousToken->is(tok::l_brace) &&4706isLineComment(*Node.Tok)) {4707MinColumnToken = PreviousToken;4708break;4709}4710PreviousToken = Node.Tok;47114712// Grab the last newline preceding a token in this unwrapped line.4713if (Node.Tok->NewlinesBefore > 0)4714MinColumnToken = Node.Tok;4715}4716if (PreviousToken && PreviousToken->is(tok::l_brace))4717MinColumnToken = PreviousToken;47184719return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,4720MinColumnToken);4721}47224723void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {4724bool JustComments = Line->Tokens.empty();4725for (FormatToken *Tok : CommentsBeforeNextToken) {4726// Line comments that belong to the same line comment section are put on the4727// same line since later we might want to reflow content between them.4728// Additional fine-grained breaking of line comment sections is controlled4729// by the class BreakableLineCommentSection in case it is desirable to keep4730// several line comment sections in the same unwrapped line.4731//4732// FIXME: Consider putting separate line comment sections as children to the4733// unwrapped line instead.4734Tok->ContinuesLineCommentSection =4735continuesLineCommentSection(*Tok, *Line, CommentPragmasRegex);4736if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection)4737addUnwrappedLine();4738pushToken(Tok);4739}4740if (NewlineBeforeNext && JustComments)4741addUnwrappedLine();4742CommentsBeforeNextToken.clear();4743}47444745void UnwrappedLineParser::nextToken(int LevelDifference) {4746if (eof())4747return;4748flushComments(isOnNewLine(*FormatTok));4749pushToken(FormatTok);4750FormatToken *Previous = FormatTok;4751if (!Style.isJavaScript())4752readToken(LevelDifference);4753else4754readTokenWithJavaScriptASI();4755FormatTok->Previous = Previous;4756if (Style.isVerilog()) {4757// Blocks in Verilog can have `begin` and `end` instead of braces. For4758// keywords like `begin`, we can't treat them the same as left braces4759// because some contexts require one of them. For example structs use4760// braces and if blocks use keywords, and a left brace can occur in an if4761// statement, but it is not a block. For keywords like `end`, we simply4762// treat them the same as right braces.4763if (Keywords.isVerilogEnd(*FormatTok))4764FormatTok->Tok.setKind(tok::r_brace);4765}4766}47674768void UnwrappedLineParser::distributeComments(4769const SmallVectorImpl<FormatToken *> &Comments,4770const FormatToken *NextTok) {4771// Whether or not a line comment token continues a line is controlled by4772// the method continuesLineCommentSection, with the following caveat:4773//4774// Define a trail of Comments to be a nonempty proper postfix of Comments such4775// that each comment line from the trail is aligned with the next token, if4776// the next token exists. If a trail exists, the beginning of the maximal4777// trail is marked as a start of a new comment section.4778//4779// For example in this code:4780//4781// int a; // line about a4782// // line 1 about b4783// // line 2 about b4784// int b;4785//4786// the two lines about b form a maximal trail, so there are two sections, the4787// first one consisting of the single comment "// line about a" and the4788// second one consisting of the next two comments.4789if (Comments.empty())4790return;4791bool ShouldPushCommentsInCurrentLine = true;4792bool HasTrailAlignedWithNextToken = false;4793unsigned StartOfTrailAlignedWithNextToken = 0;4794if (NextTok) {4795// We are skipping the first element intentionally.4796for (unsigned i = Comments.size() - 1; i > 0; --i) {4797if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) {4798HasTrailAlignedWithNextToken = true;4799StartOfTrailAlignedWithNextToken = i;4800}4801}4802}4803for (unsigned i = 0, e = Comments.size(); i < e; ++i) {4804FormatToken *FormatTok = Comments[i];4805if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {4806FormatTok->ContinuesLineCommentSection = false;4807} else {4808FormatTok->ContinuesLineCommentSection =4809continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);4810}4811if (!FormatTok->ContinuesLineCommentSection &&4812(isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {4813ShouldPushCommentsInCurrentLine = false;4814}4815if (ShouldPushCommentsInCurrentLine)4816pushToken(FormatTok);4817else4818CommentsBeforeNextToken.push_back(FormatTok);4819}4820}48214822void UnwrappedLineParser::readToken(int LevelDifference) {4823SmallVector<FormatToken *, 1> Comments;4824bool PreviousWasComment = false;4825bool FirstNonCommentOnLine = false;4826do {4827FormatTok = Tokens->getNextToken();4828assert(FormatTok);4829while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,4830TT_ConflictAlternative)) {4831if (FormatTok->is(TT_ConflictStart))4832conditionalCompilationStart(/*Unreachable=*/false);4833else if (FormatTok->is(TT_ConflictAlternative))4834conditionalCompilationAlternative();4835else if (FormatTok->is(TT_ConflictEnd))4836conditionalCompilationEnd();4837FormatTok = Tokens->getNextToken();4838FormatTok->MustBreakBefore = true;4839FormatTok->MustBreakBeforeFinalized = true;4840}48414842auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine,4843const FormatToken &Tok,4844bool PreviousWasComment) {4845auto IsFirstOnLine = [](const FormatToken &Tok) {4846return Tok.HasUnescapedNewline || Tok.IsFirst;4847};48484849// Consider preprocessor directives preceded by block comments as first4850// on line.4851if (PreviousWasComment)4852return FirstNonCommentOnLine || IsFirstOnLine(Tok);4853return IsFirstOnLine(Tok);4854};48554856FirstNonCommentOnLine = IsFirstNonCommentOnLine(4857FirstNonCommentOnLine, *FormatTok, PreviousWasComment);4858PreviousWasComment = FormatTok->is(tok::comment);48594860while (!Line->InPPDirective && FormatTok->is(tok::hash) &&4861(!Style.isVerilog() ||4862Keywords.isVerilogPPDirective(*Tokens->peekNextToken())) &&4863FirstNonCommentOnLine) {4864distributeComments(Comments, FormatTok);4865Comments.clear();4866// If there is an unfinished unwrapped line, we flush the preprocessor4867// directives only after that unwrapped line was finished later.4868bool SwitchToPreprocessorLines = !Line->Tokens.empty();4869ScopedLineState BlockState(*this, SwitchToPreprocessorLines);4870assert((LevelDifference >= 0 ||4871static_cast<unsigned>(-LevelDifference) <= Line->Level) &&4872"LevelDifference makes Line->Level negative");4873Line->Level += LevelDifference;4874// Comments stored before the preprocessor directive need to be output4875// before the preprocessor directive, at the same level as the4876// preprocessor directive, as we consider them to apply to the directive.4877if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&4878PPBranchLevel > 0) {4879Line->Level += PPBranchLevel;4880}4881assert(Line->Level >= Line->UnbracedBodyLevel);4882Line->Level -= Line->UnbracedBodyLevel;4883flushComments(isOnNewLine(*FormatTok));4884parsePPDirective();4885PreviousWasComment = FormatTok->is(tok::comment);4886FirstNonCommentOnLine = IsFirstNonCommentOnLine(4887FirstNonCommentOnLine, *FormatTok, PreviousWasComment);4888}48894890if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&4891!Line->InPPDirective) {4892continue;4893}48944895if (FormatTok->is(tok::identifier) &&4896Macros.defined(FormatTok->TokenText) &&4897// FIXME: Allow expanding macros in preprocessor directives.4898!Line->InPPDirective) {4899FormatToken *ID = FormatTok;4900unsigned Position = Tokens->getPosition();49014902// To correctly parse the code, we need to replace the tokens of the macro4903// call with its expansion.4904auto PreCall = std::move(Line);4905Line.reset(new UnwrappedLine);4906bool OldInExpansion = InExpansion;4907InExpansion = true;4908// We parse the macro call into a new line.4909auto Args = parseMacroCall();4910InExpansion = OldInExpansion;4911assert(Line->Tokens.front().Tok == ID);4912// And remember the unexpanded macro call tokens.4913auto UnexpandedLine = std::move(Line);4914// Reset to the old line.4915Line = std::move(PreCall);49164917LLVM_DEBUG({4918llvm::dbgs() << "Macro call: " << ID->TokenText << "(";4919if (Args) {4920llvm::dbgs() << "(";4921for (const auto &Arg : Args.value())4922for (const auto &T : Arg)4923llvm::dbgs() << T->TokenText << " ";4924llvm::dbgs() << ")";4925}4926llvm::dbgs() << "\n";4927});4928if (Macros.objectLike(ID->TokenText) && Args &&4929!Macros.hasArity(ID->TokenText, Args->size())) {4930// The macro is either4931// - object-like, but we got argumnets, or4932// - overloaded to be both object-like and function-like, but none of4933// the function-like arities match the number of arguments.4934// Thus, expand as object-like macro.4935LLVM_DEBUG(llvm::dbgs()4936<< "Macro \"" << ID->TokenText4937<< "\" not overloaded for arity " << Args->size()4938<< "or not function-like, using object-like overload.");4939Args.reset();4940UnexpandedLine->Tokens.resize(1);4941Tokens->setPosition(Position);4942nextToken();4943assert(!Args && Macros.objectLike(ID->TokenText));4944}4945if ((!Args && Macros.objectLike(ID->TokenText)) ||4946(Args && Macros.hasArity(ID->TokenText, Args->size()))) {4947// Next, we insert the expanded tokens in the token stream at the4948// current position, and continue parsing.4949Unexpanded[ID] = std::move(UnexpandedLine);4950SmallVector<FormatToken *, 8> Expansion =4951Macros.expand(ID, std::move(Args));4952if (!Expansion.empty())4953FormatTok = Tokens->insertTokens(Expansion);49544955LLVM_DEBUG({4956llvm::dbgs() << "Expanded: ";4957for (const auto &T : Expansion)4958llvm::dbgs() << T->TokenText << " ";4959llvm::dbgs() << "\n";4960});4961} else {4962LLVM_DEBUG({4963llvm::dbgs() << "Did not expand macro \"" << ID->TokenText4964<< "\", because it was used ";4965if (Args)4966llvm::dbgs() << "with " << Args->size();4967else4968llvm::dbgs() << "without";4969llvm::dbgs() << " arguments, which doesn't match any definition.\n";4970});4971Tokens->setPosition(Position);4972FormatTok = ID;4973}4974}49754976if (FormatTok->isNot(tok::comment)) {4977distributeComments(Comments, FormatTok);4978Comments.clear();4979return;4980}49814982Comments.push_back(FormatTok);4983} while (!eof());49844985distributeComments(Comments, nullptr);4986Comments.clear();4987}49884989namespace {4990template <typename Iterator>4991void pushTokens(Iterator Begin, Iterator End,4992llvm::SmallVectorImpl<FormatToken *> &Into) {4993for (auto I = Begin; I != End; ++I) {4994Into.push_back(I->Tok);4995for (const auto &Child : I->Children)4996pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);4997}4998}4999} // namespace50005001std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>5002UnwrappedLineParser::parseMacroCall() {5003std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;5004assert(Line->Tokens.empty());5005nextToken();5006if (FormatTok->isNot(tok::l_paren))5007return Args;5008unsigned Position = Tokens->getPosition();5009FormatToken *Tok = FormatTok;5010nextToken();5011Args.emplace();5012auto ArgStart = std::prev(Line->Tokens.end());50135014int Parens = 0;5015do {5016switch (FormatTok->Tok.getKind()) {5017case tok::l_paren:5018++Parens;5019nextToken();5020break;5021case tok::r_paren: {5022if (Parens > 0) {5023--Parens;5024nextToken();5025break;5026}5027Args->push_back({});5028pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());5029nextToken();5030return Args;5031}5032case tok::comma: {5033if (Parens > 0) {5034nextToken();5035break;5036}5037Args->push_back({});5038pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());5039nextToken();5040ArgStart = std::prev(Line->Tokens.end());5041break;5042}5043default:5044nextToken();5045break;5046}5047} while (!eof());5048Line->Tokens.resize(1);5049Tokens->setPosition(Position);5050FormatTok = Tok;5051return {};5052}50535054void UnwrappedLineParser::pushToken(FormatToken *Tok) {5055Line->Tokens.push_back(UnwrappedLineNode(Tok));5056if (MustBreakBeforeNextToken) {5057Line->Tokens.back().Tok->MustBreakBefore = true;5058Line->Tokens.back().Tok->MustBreakBeforeFinalized = true;5059MustBreakBeforeNextToken = false;5060}5061}50625063} // end namespace format5064} // end namespace clang506550665067