10b57cec5SDimitry Andric //===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file contains the implementation of the UnwrappedLineParser, 110b57cec5SDimitry Andric /// which turns a stream of tokens into UnwrappedLines. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "UnwrappedLineParser.h" 165ffd83dbSDimitry Andric #include "FormatToken.h" 1706c3fb27SDimitry Andric #include "FormatTokenLexer.h" 1806c3fb27SDimitry Andric #include "FormatTokenSource.h" 1906c3fb27SDimitry Andric #include "Macros.h" 2004eeddc0SDimitry Andric #include "TokenAnnotator.h" 21753f127fSDimitry Andric #include "clang/Basic/TokenKinds.h" 220b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 2306c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h" 240b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 2506c3fb27SDimitry Andric #include "llvm/Support/raw_os_ostream.h" 260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #include <algorithm> 2981ad6265SDimitry Andric #include <utility> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric #define DEBUG_TYPE "format-parser" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace clang { 340b57cec5SDimitry Andric namespace format { 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric namespace { 370b57cec5SDimitry Andric 38bdd1243dSDimitry Andric void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line, 39bdd1243dSDimitry Andric StringRef Prefix = "", bool PrintText = false) { 40bdd1243dSDimitry Andric OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn 41bdd1243dSDimitry Andric << ")" << (Line.InPPDirective ? " MACRO" : "") << ": "; 42bdd1243dSDimitry Andric bool NewLine = false; 43bdd1243dSDimitry Andric for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(), 44bdd1243dSDimitry Andric E = Line.Tokens.end(); 45bdd1243dSDimitry Andric I != E; ++I) { 46bdd1243dSDimitry Andric if (NewLine) { 47bdd1243dSDimitry Andric OS << Prefix; 48bdd1243dSDimitry Andric NewLine = false; 49bdd1243dSDimitry Andric } 500fca6ea1SDimitry Andric OS << I->Tok->Tok.getName() << "[" 510fca6ea1SDimitry Andric << "T=" << (unsigned)I->Tok->getType() 52bdd1243dSDimitry Andric << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText 53bdd1243dSDimitry Andric << "\"] "; 54bdd1243dSDimitry Andric for (SmallVectorImpl<UnwrappedLine>::const_iterator 55bdd1243dSDimitry Andric CI = I->Children.begin(), 56bdd1243dSDimitry Andric CE = I->Children.end(); 57bdd1243dSDimitry Andric CI != CE; ++CI) { 58bdd1243dSDimitry Andric OS << "\n"; 59bdd1243dSDimitry Andric printLine(OS, *CI, (Prefix + " ").str()); 60bdd1243dSDimitry Andric NewLine = true; 61bdd1243dSDimitry Andric } 62bdd1243dSDimitry Andric } 63bdd1243dSDimitry Andric if (!NewLine) 64bdd1243dSDimitry Andric OS << "\n"; 65bdd1243dSDimitry Andric } 66bdd1243dSDimitry Andric 67bdd1243dSDimitry Andric LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line) { 68bdd1243dSDimitry Andric printLine(llvm::dbgs(), Line); 69bdd1243dSDimitry Andric } 70bdd1243dSDimitry Andric 710b57cec5SDimitry Andric class ScopedDeclarationState { 720b57cec5SDimitry Andric public: 7304eeddc0SDimitry Andric ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack, 740b57cec5SDimitry Andric bool MustBeDeclaration) 750b57cec5SDimitry Andric : Line(Line), Stack(Stack) { 760b57cec5SDimitry Andric Line.MustBeDeclaration = MustBeDeclaration; 770b57cec5SDimitry Andric Stack.push_back(MustBeDeclaration); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric ~ScopedDeclarationState() { 800b57cec5SDimitry Andric Stack.pop_back(); 810b57cec5SDimitry Andric if (!Stack.empty()) 820b57cec5SDimitry Andric Line.MustBeDeclaration = Stack.back(); 830b57cec5SDimitry Andric else 840b57cec5SDimitry Andric Line.MustBeDeclaration = true; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric private: 880b57cec5SDimitry Andric UnwrappedLine &Line; 8904eeddc0SDimitry Andric llvm::BitVector &Stack; 900b57cec5SDimitry Andric }; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric } // end anonymous namespace 930b57cec5SDimitry Andric 940fca6ea1SDimitry Andric std::ostream &operator<<(std::ostream &Stream, const UnwrappedLine &Line) { 950fca6ea1SDimitry Andric llvm::raw_os_ostream OS(Stream); 960fca6ea1SDimitry Andric printLine(OS, Line); 970fca6ea1SDimitry Andric return Stream; 980fca6ea1SDimitry Andric } 990fca6ea1SDimitry Andric 1000b57cec5SDimitry Andric class ScopedLineState { 1010b57cec5SDimitry Andric public: 1020b57cec5SDimitry Andric ScopedLineState(UnwrappedLineParser &Parser, 1030b57cec5SDimitry Andric bool SwitchToPreprocessorLines = false) 1040b57cec5SDimitry Andric : Parser(Parser), OriginalLines(Parser.CurrentLines) { 1050b57cec5SDimitry Andric if (SwitchToPreprocessorLines) 1060b57cec5SDimitry Andric Parser.CurrentLines = &Parser.PreprocessorDirectives; 1070b57cec5SDimitry Andric else if (!Parser.Line->Tokens.empty()) 1080b57cec5SDimitry Andric Parser.CurrentLines = &Parser.Line->Tokens.back().Children; 1090b57cec5SDimitry Andric PreBlockLine = std::move(Parser.Line); 110a7dea167SDimitry Andric Parser.Line = std::make_unique<UnwrappedLine>(); 1110b57cec5SDimitry Andric Parser.Line->Level = PreBlockLine->Level; 112bdd1243dSDimitry Andric Parser.Line->PPLevel = PreBlockLine->PPLevel; 1130b57cec5SDimitry Andric Parser.Line->InPPDirective = PreBlockLine->InPPDirective; 114bdd1243dSDimitry Andric Parser.Line->InMacroBody = PreBlockLine->InMacroBody; 1150fca6ea1SDimitry Andric Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel; 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric ~ScopedLineState() { 11981ad6265SDimitry Andric if (!Parser.Line->Tokens.empty()) 1200b57cec5SDimitry Andric Parser.addUnwrappedLine(); 1210b57cec5SDimitry Andric assert(Parser.Line->Tokens.empty()); 1220b57cec5SDimitry Andric Parser.Line = std::move(PreBlockLine); 1230b57cec5SDimitry Andric if (Parser.CurrentLines == &Parser.PreprocessorDirectives) 1240b57cec5SDimitry Andric Parser.MustBreakBeforeNextToken = true; 1250b57cec5SDimitry Andric Parser.CurrentLines = OriginalLines; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric private: 1290b57cec5SDimitry Andric UnwrappedLineParser &Parser; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric std::unique_ptr<UnwrappedLine> PreBlockLine; 1320b57cec5SDimitry Andric SmallVectorImpl<UnwrappedLine> *OriginalLines; 1330b57cec5SDimitry Andric }; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric class CompoundStatementIndenter { 1360b57cec5SDimitry Andric public: 1370b57cec5SDimitry Andric CompoundStatementIndenter(UnwrappedLineParser *Parser, 1380b57cec5SDimitry Andric const FormatStyle &Style, unsigned &LineLevel) 1390b57cec5SDimitry Andric : CompoundStatementIndenter(Parser, LineLevel, 1400b57cec5SDimitry Andric Style.BraceWrapping.AfterControlStatement, 141a7dea167SDimitry Andric Style.BraceWrapping.IndentBraces) {} 1420b57cec5SDimitry Andric CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel, 1430b57cec5SDimitry Andric bool WrapBrace, bool IndentBrace) 1440b57cec5SDimitry Andric : LineLevel(LineLevel), OldLineLevel(LineLevel) { 1450b57cec5SDimitry Andric if (WrapBrace) 1460b57cec5SDimitry Andric Parser->addUnwrappedLine(); 1470b57cec5SDimitry Andric if (IndentBrace) 1480b57cec5SDimitry Andric ++LineLevel; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric ~CompoundStatementIndenter() { LineLevel = OldLineLevel; } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric private: 1530b57cec5SDimitry Andric unsigned &LineLevel; 1540b57cec5SDimitry Andric unsigned OldLineLevel; 1550b57cec5SDimitry Andric }; 1560b57cec5SDimitry Andric 15706c3fb27SDimitry Andric UnwrappedLineParser::UnwrappedLineParser( 15806c3fb27SDimitry Andric SourceManager &SourceMgr, const FormatStyle &Style, 15906c3fb27SDimitry Andric const AdditionalKeywords &Keywords, unsigned FirstStartColumn, 16006c3fb27SDimitry Andric ArrayRef<FormatToken *> Tokens, UnwrappedLineConsumer &Callback, 16106c3fb27SDimitry Andric llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator, 16206c3fb27SDimitry Andric IdentifierTable &IdentTable) 1630b57cec5SDimitry Andric : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), 1640fca6ea1SDimitry Andric CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()), 1650fca6ea1SDimitry Andric LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords), 1660b57cec5SDimitry Andric CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr), 1670b57cec5SDimitry Andric Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1), 1680b57cec5SDimitry Andric IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None 1690b57cec5SDimitry Andric ? IG_Rejected 1700b57cec5SDimitry Andric : IG_Inited), 17106c3fb27SDimitry Andric IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn), 1720fca6ea1SDimitry Andric Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) { 1730fca6ea1SDimitry Andric assert(IsCpp == LangOpts.CXXOperatorNames); 1740fca6ea1SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void UnwrappedLineParser::reset() { 1770b57cec5SDimitry Andric PPBranchLevel = -1; 1780b57cec5SDimitry Andric IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None 1790b57cec5SDimitry Andric ? IG_Rejected 1800b57cec5SDimitry Andric : IG_Inited; 1810b57cec5SDimitry Andric IncludeGuardToken = nullptr; 1820b57cec5SDimitry Andric Line.reset(new UnwrappedLine); 1830b57cec5SDimitry Andric CommentsBeforeNextToken.clear(); 1840b57cec5SDimitry Andric FormatTok = nullptr; 1850b57cec5SDimitry Andric MustBreakBeforeNextToken = false; 186bdb86d1aSDimitry Andric IsDecltypeAutoFunction = false; 1870b57cec5SDimitry Andric PreprocessorDirectives.clear(); 1880b57cec5SDimitry Andric CurrentLines = &Lines; 1890b57cec5SDimitry Andric DeclarationScopeStack.clear(); 19004eeddc0SDimitry Andric NestedTooDeep.clear(); 191bdb86d1aSDimitry Andric NestedLambdas.clear(); 1920b57cec5SDimitry Andric PPStack.clear(); 1930b57cec5SDimitry Andric Line->FirstStartColumn = FirstStartColumn; 19406c3fb27SDimitry Andric 19506c3fb27SDimitry Andric if (!Unexpanded.empty()) 19606c3fb27SDimitry Andric for (FormatToken *Token : AllTokens) 19706c3fb27SDimitry Andric Token->MacroCtx.reset(); 19806c3fb27SDimitry Andric CurrentExpandedLines.clear(); 19906c3fb27SDimitry Andric ExpandedLines.clear(); 20006c3fb27SDimitry Andric Unexpanded.clear(); 20106c3fb27SDimitry Andric InExpansion = false; 20206c3fb27SDimitry Andric Reconstruct.reset(); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric void UnwrappedLineParser::parse() { 2060b57cec5SDimitry Andric IndexedTokenSource TokenSource(AllTokens); 2070b57cec5SDimitry Andric Line->FirstStartColumn = FirstStartColumn; 2080b57cec5SDimitry Andric do { 2090b57cec5SDimitry Andric LLVM_DEBUG(llvm::dbgs() << "----\n"); 2100b57cec5SDimitry Andric reset(); 2110b57cec5SDimitry Andric Tokens = &TokenSource; 2120b57cec5SDimitry Andric TokenSource.reset(); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric readToken(); 2150b57cec5SDimitry Andric parseFile(); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric // If we found an include guard then all preprocessor directives (other than 2180b57cec5SDimitry Andric // the guard) are over-indented by one. 21981ad6265SDimitry Andric if (IncludeGuard == IG_Found) { 2200b57cec5SDimitry Andric for (auto &Line : Lines) 2210b57cec5SDimitry Andric if (Line.InPPDirective && Line.Level > 0) 2220b57cec5SDimitry Andric --Line.Level; 22381ad6265SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric // Create line with eof token. 2265f757f3fSDimitry Andric assert(eof()); 2270b57cec5SDimitry Andric pushToken(FormatTok); 2280b57cec5SDimitry Andric addUnwrappedLine(); 2290b57cec5SDimitry Andric 23006c3fb27SDimitry Andric // In a first run, format everything with the lines containing macro calls 23106c3fb27SDimitry Andric // replaced by the expansion. 23206c3fb27SDimitry Andric if (!ExpandedLines.empty()) { 23306c3fb27SDimitry Andric LLVM_DEBUG(llvm::dbgs() << "Expanded lines:\n"); 23406c3fb27SDimitry Andric for (const auto &Line : Lines) { 23506c3fb27SDimitry Andric if (!Line.Tokens.empty()) { 23606c3fb27SDimitry Andric auto it = ExpandedLines.find(Line.Tokens.begin()->Tok); 23706c3fb27SDimitry Andric if (it != ExpandedLines.end()) { 23806c3fb27SDimitry Andric for (const auto &Expanded : it->second) { 23906c3fb27SDimitry Andric LLVM_DEBUG(printDebugInfo(Expanded)); 24006c3fb27SDimitry Andric Callback.consumeUnwrappedLine(Expanded); 24106c3fb27SDimitry Andric } 24206c3fb27SDimitry Andric continue; 24306c3fb27SDimitry Andric } 24406c3fb27SDimitry Andric } 24506c3fb27SDimitry Andric LLVM_DEBUG(printDebugInfo(Line)); 24604eeddc0SDimitry Andric Callback.consumeUnwrappedLine(Line); 24706c3fb27SDimitry Andric } 24806c3fb27SDimitry Andric Callback.finishRun(); 24906c3fb27SDimitry Andric } 25004eeddc0SDimitry Andric 25106c3fb27SDimitry Andric LLVM_DEBUG(llvm::dbgs() << "Unwrapped lines:\n"); 25206c3fb27SDimitry Andric for (const UnwrappedLine &Line : Lines) { 25306c3fb27SDimitry Andric LLVM_DEBUG(printDebugInfo(Line)); 25406c3fb27SDimitry Andric Callback.consumeUnwrappedLine(Line); 25506c3fb27SDimitry Andric } 2560b57cec5SDimitry Andric Callback.finishRun(); 2570b57cec5SDimitry Andric Lines.clear(); 2580b57cec5SDimitry Andric while (!PPLevelBranchIndex.empty() && 2590b57cec5SDimitry Andric PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) { 2600b57cec5SDimitry Andric PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1); 2610b57cec5SDimitry Andric PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric if (!PPLevelBranchIndex.empty()) { 2640b57cec5SDimitry Andric ++PPLevelBranchIndex.back(); 2650b57cec5SDimitry Andric assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size()); 2660b57cec5SDimitry Andric assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back()); 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric } while (!PPLevelBranchIndex.empty()); 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric void UnwrappedLineParser::parseFile() { 2720b57cec5SDimitry Andric // The top-level context in a file always has declarations, except for pre- 2730b57cec5SDimitry Andric // processor directives and JavaScript files. 2740eae32dcSDimitry Andric bool MustBeDeclaration = !Line->InPPDirective && !Style.isJavaScript(); 2750b57cec5SDimitry Andric ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, 2760b57cec5SDimitry Andric MustBeDeclaration); 2770b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto) 2780b57cec5SDimitry Andric parseBracedList(); 2790b57cec5SDimitry Andric else 28081ad6265SDimitry Andric parseLevel(); 2810b57cec5SDimitry Andric // Make sure to format the remaining tokens. 2820b57cec5SDimitry Andric // 2830b57cec5SDimitry Andric // LK_TextProto is special since its top-level is parsed as the body of a 2840b57cec5SDimitry Andric // braced list, which does not necessarily have natural line separators such 2850b57cec5SDimitry Andric // as a semicolon. Comments after the last entry that have been determined to 2860b57cec5SDimitry Andric // not belong to that line, as in: 2870b57cec5SDimitry Andric // key: value 2880b57cec5SDimitry Andric // // endfile comment 2890b57cec5SDimitry Andric // do not have a chance to be put on a line of their own until this point. 2900b57cec5SDimitry Andric // Here we add this newline before end-of-file comments. 2910b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto && 29281ad6265SDimitry Andric !CommentsBeforeNextToken.empty()) { 2930b57cec5SDimitry Andric addUnwrappedLine(); 29481ad6265SDimitry Andric } 2950b57cec5SDimitry Andric flushComments(true); 2960b57cec5SDimitry Andric addUnwrappedLine(); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2995ffd83dbSDimitry Andric void UnwrappedLineParser::parseCSharpGenericTypeConstraint() { 3005ffd83dbSDimitry Andric do { 3015ffd83dbSDimitry Andric switch (FormatTok->Tok.getKind()) { 3025ffd83dbSDimitry Andric case tok::l_brace: 3035ffd83dbSDimitry Andric return; 3045ffd83dbSDimitry Andric default: 3055ffd83dbSDimitry Andric if (FormatTok->is(Keywords.kw_where)) { 3065ffd83dbSDimitry Andric addUnwrappedLine(); 3075ffd83dbSDimitry Andric nextToken(); 3085ffd83dbSDimitry Andric parseCSharpGenericTypeConstraint(); 3095ffd83dbSDimitry Andric break; 3105ffd83dbSDimitry Andric } 3115ffd83dbSDimitry Andric nextToken(); 3125ffd83dbSDimitry Andric break; 3135ffd83dbSDimitry Andric } 3145ffd83dbSDimitry Andric } while (!eof()); 3155ffd83dbSDimitry Andric } 3165ffd83dbSDimitry Andric 3175ffd83dbSDimitry Andric void UnwrappedLineParser::parseCSharpAttribute() { 3185ffd83dbSDimitry Andric int UnpairedSquareBrackets = 1; 3195ffd83dbSDimitry Andric do { 3205ffd83dbSDimitry Andric switch (FormatTok->Tok.getKind()) { 3215ffd83dbSDimitry Andric case tok::r_square: 3225ffd83dbSDimitry Andric nextToken(); 3235ffd83dbSDimitry Andric --UnpairedSquareBrackets; 3245ffd83dbSDimitry Andric if (UnpairedSquareBrackets == 0) { 3255ffd83dbSDimitry Andric addUnwrappedLine(); 3265ffd83dbSDimitry Andric return; 3275ffd83dbSDimitry Andric } 3285ffd83dbSDimitry Andric break; 3295ffd83dbSDimitry Andric case tok::l_square: 3305ffd83dbSDimitry Andric ++UnpairedSquareBrackets; 3315ffd83dbSDimitry Andric nextToken(); 3325ffd83dbSDimitry Andric break; 3335ffd83dbSDimitry Andric default: 3345ffd83dbSDimitry Andric nextToken(); 3355ffd83dbSDimitry Andric break; 3365ffd83dbSDimitry Andric } 3375ffd83dbSDimitry Andric } while (!eof()); 3385ffd83dbSDimitry Andric } 3395ffd83dbSDimitry Andric 34004eeddc0SDimitry Andric bool UnwrappedLineParser::precededByCommentOrPPDirective() const { 34104eeddc0SDimitry Andric if (!Lines.empty() && Lines.back().InPPDirective) 34204eeddc0SDimitry Andric return true; 34304eeddc0SDimitry Andric 34404eeddc0SDimitry Andric const FormatToken *Previous = Tokens->getPreviousToken(); 34504eeddc0SDimitry Andric return Previous && Previous->is(tok::comment) && 34604eeddc0SDimitry Andric (Previous->IsMultiline || Previous->NewlinesBefore > 0); 34704eeddc0SDimitry Andric } 34804eeddc0SDimitry Andric 34981ad6265SDimitry Andric /// \brief Parses a level, that is ???. 3505f757f3fSDimitry Andric /// \param OpeningBrace Opening brace (\p nullptr if absent) of that level. 35181ad6265SDimitry Andric /// \param IfKind The \p if statement kind in the level. 35281ad6265SDimitry Andric /// \param IfLeftBrace The left brace of the \p if block in the level. 35381ad6265SDimitry Andric /// \returns true if a simple block of if/else/for/while, or false otherwise. 35481ad6265SDimitry Andric /// (A simple block has a single statement.) 35581ad6265SDimitry Andric bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, 35681ad6265SDimitry Andric IfStmtKind *IfKind, 35781ad6265SDimitry Andric FormatToken **IfLeftBrace) { 3585f757f3fSDimitry Andric const bool InRequiresExpression = 3595f757f3fSDimitry Andric OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); 36004eeddc0SDimitry Andric const bool IsPrecededByCommentOrPPDirective = 36104eeddc0SDimitry Andric !Style.RemoveBracesLLVM || precededByCommentOrPPDirective(); 36281ad6265SDimitry Andric FormatToken *IfLBrace = nullptr; 36381ad6265SDimitry Andric bool HasDoWhile = false; 36481ad6265SDimitry Andric bool HasLabel = false; 36504eeddc0SDimitry Andric unsigned StatementCount = 0; 3660b57cec5SDimitry Andric bool SwitchLabelEncountered = false; 36781ad6265SDimitry Andric 3680b57cec5SDimitry Andric do { 3695f757f3fSDimitry Andric if (FormatTok->isAttribute()) { 37081ad6265SDimitry Andric nextToken(); 3710fca6ea1SDimitry Andric if (FormatTok->is(tok::l_paren)) 3720fca6ea1SDimitry Andric parseParens(); 37381ad6265SDimitry Andric continue; 3740b57cec5SDimitry Andric } 3750fca6ea1SDimitry Andric tok::TokenKind Kind = FormatTok->Tok.getKind(); 3760fca6ea1SDimitry Andric if (FormatTok->is(TT_MacroBlockBegin)) 3770fca6ea1SDimitry Andric Kind = tok::l_brace; 3780fca6ea1SDimitry Andric else if (FormatTok->is(TT_MacroBlockEnd)) 3790fca6ea1SDimitry Andric Kind = tok::r_brace; 38081ad6265SDimitry Andric 3815f757f3fSDimitry Andric auto ParseDefault = [this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile, 3825f757f3fSDimitry Andric &HasLabel, &StatementCount] { 3835f757f3fSDimitry Andric parseStructuralElement(OpeningBrace, IfKind, &IfLBrace, 3845f757f3fSDimitry Andric HasDoWhile ? nullptr : &HasDoWhile, 38581ad6265SDimitry Andric HasLabel ? nullptr : &HasLabel); 38681ad6265SDimitry Andric ++StatementCount; 38781ad6265SDimitry Andric assert(StatementCount > 0 && "StatementCount overflow!"); 38881ad6265SDimitry Andric }; 3890b57cec5SDimitry Andric 3900fca6ea1SDimitry Andric switch (Kind) { 3910b57cec5SDimitry Andric case tok::comment: 3920b57cec5SDimitry Andric nextToken(); 3930b57cec5SDimitry Andric addUnwrappedLine(); 3940b57cec5SDimitry Andric break; 3950b57cec5SDimitry Andric case tok::l_brace: 3965f757f3fSDimitry Andric if (InRequiresExpression) { 3975f757f3fSDimitry Andric FormatTok->setFinalizedType(TT_RequiresExpressionLBrace); 39881ad6265SDimitry Andric } else if (FormatTok->Previous && 39981ad6265SDimitry Andric FormatTok->Previous->ClosesRequiresClause) { 40081ad6265SDimitry Andric // We need the 'default' case here to correctly parse a function 40181ad6265SDimitry Andric // l_brace. 40281ad6265SDimitry Andric ParseDefault(); 4030b57cec5SDimitry Andric continue; 40481ad6265SDimitry Andric } 4050fca6ea1SDimitry Andric if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) { 4060fca6ea1SDimitry Andric if (tryToParseBracedList()) 40781ad6265SDimitry Andric continue; 4080fca6ea1SDimitry Andric FormatTok->setFinalizedType(TT_BlockLBrace); 40981ad6265SDimitry Andric } 4105f757f3fSDimitry Andric parseBlock(); 41104eeddc0SDimitry Andric ++StatementCount; 41204eeddc0SDimitry Andric assert(StatementCount > 0 && "StatementCount overflow!"); 4130b57cec5SDimitry Andric addUnwrappedLine(); 4140b57cec5SDimitry Andric break; 4150b57cec5SDimitry Andric case tok::r_brace: 41681ad6265SDimitry Andric if (OpeningBrace) { 417fcaf7f86SDimitry Andric if (!Style.RemoveBracesLLVM || Line->InPPDirective || 41881ad6265SDimitry Andric !OpeningBrace->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) { 41904eeddc0SDimitry Andric return false; 42081ad6265SDimitry Andric } 42181ad6265SDimitry Andric if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel || 42281ad6265SDimitry Andric HasDoWhile || IsPrecededByCommentOrPPDirective || 42304eeddc0SDimitry Andric precededByCommentOrPPDirective()) { 42404eeddc0SDimitry Andric return false; 42504eeddc0SDimitry Andric } 42604eeddc0SDimitry Andric const FormatToken *Next = Tokens->peekNextToken(); 42704eeddc0SDimitry Andric if (Next->is(tok::comment) && Next->NewlinesBefore == 0) 42804eeddc0SDimitry Andric return false; 42981ad6265SDimitry Andric if (IfLeftBrace) 43081ad6265SDimitry Andric *IfLeftBrace = IfLBrace; 43181ad6265SDimitry Andric return true; 43204eeddc0SDimitry Andric } 4330b57cec5SDimitry Andric nextToken(); 4340b57cec5SDimitry Andric addUnwrappedLine(); 4350b57cec5SDimitry Andric break; 4360b57cec5SDimitry Andric case tok::kw_default: { 4370b57cec5SDimitry Andric unsigned StoredPosition = Tokens->getPosition(); 4380fca6ea1SDimitry Andric auto *Next = Tokens->getNextNonComment(); 4390b57cec5SDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 4400fca6ea1SDimitry Andric if (!Next->isOneOf(tok::colon, tok::arrow)) { 4410fca6ea1SDimitry Andric // default not followed by `:` or `->` is not a case label; treat it 4420fca6ea1SDimitry Andric // like an identifier. 4430b57cec5SDimitry Andric parseStructuralElement(); 4440b57cec5SDimitry Andric break; 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric // Else, if it is 'default:', fall through to the case handling. 447bdd1243dSDimitry Andric [[fallthrough]]; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric case tok::kw_case: 4505f757f3fSDimitry Andric if (Style.Language == FormatStyle::LK_Proto || Style.isVerilog() || 451bdd1243dSDimitry Andric (Style.isJavaScript() && Line->MustBeDeclaration)) { 452bdd1243dSDimitry Andric // Proto: there are no switch/case statements 453bdd1243dSDimitry Andric // Verilog: Case labels don't have this word. We handle case 454bdd1243dSDimitry Andric // labels including default in TokenAnnotator. 455bdd1243dSDimitry Andric // JavaScript: A 'case: string' style field declaration. 456bdd1243dSDimitry Andric ParseDefault(); 4570b57cec5SDimitry Andric break; 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric if (!SwitchLabelEncountered && 46081ad6265SDimitry Andric (Style.IndentCaseLabels || 4610fca6ea1SDimitry Andric (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) || 46281ad6265SDimitry Andric (Line->InPPDirective && Line->Level == 1))) { 4630b57cec5SDimitry Andric ++Line->Level; 46481ad6265SDimitry Andric } 4650b57cec5SDimitry Andric SwitchLabelEncountered = true; 4660b57cec5SDimitry Andric parseStructuralElement(); 4670b57cec5SDimitry Andric break; 4685ffd83dbSDimitry Andric case tok::l_square: 4695ffd83dbSDimitry Andric if (Style.isCSharp()) { 4705ffd83dbSDimitry Andric nextToken(); 4715ffd83dbSDimitry Andric parseCSharpAttribute(); 4725ffd83dbSDimitry Andric break; 4735ffd83dbSDimitry Andric } 47481ad6265SDimitry Andric if (handleCppAttributes()) 47581ad6265SDimitry Andric break; 476bdd1243dSDimitry Andric [[fallthrough]]; 4770b57cec5SDimitry Andric default: 47881ad6265SDimitry Andric ParseDefault(); 4790b57cec5SDimitry Andric break; 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric } while (!eof()); 48281ad6265SDimitry Andric 48304eeddc0SDimitry Andric return false; 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { 4870b57cec5SDimitry Andric // We'll parse forward through the tokens until we hit 4880b57cec5SDimitry Andric // a closing brace or eof - note that getNextToken() will 4890b57cec5SDimitry Andric // parse macros, so this will magically work inside macro 4900b57cec5SDimitry Andric // definitions, too. 4910b57cec5SDimitry Andric unsigned StoredPosition = Tokens->getPosition(); 4920b57cec5SDimitry Andric FormatToken *Tok = FormatTok; 4930b57cec5SDimitry Andric const FormatToken *PrevTok = Tok->Previous; 4940b57cec5SDimitry Andric // Keep a stack of positions of lbrace tokens. We will 4950b57cec5SDimitry Andric // update information about whether an lbrace starts a 4960b57cec5SDimitry Andric // braced init list or a different block during the loop. 49706c3fb27SDimitry Andric struct StackEntry { 49806c3fb27SDimitry Andric FormatToken *Tok; 49906c3fb27SDimitry Andric const FormatToken *PrevTok; 50006c3fb27SDimitry Andric }; 50106c3fb27SDimitry Andric SmallVector<StackEntry, 8> LBraceStack; 50281ad6265SDimitry Andric assert(Tok->is(tok::l_brace)); 5035678d1d9SDimitry Andric 5040b57cec5SDimitry Andric do { 5050fca6ea1SDimitry Andric auto *NextTok = Tokens->getNextNonComment(); 5065678d1d9SDimitry Andric 5070fca6ea1SDimitry Andric if (!Line->InMacroBody && !Style.isTableGen()) { 5085678d1d9SDimitry Andric // Skip PPDirective lines and comments. 5095678d1d9SDimitry Andric while (NextTok->is(tok::hash)) { 51062987288SDimitry Andric NextTok = Tokens->getNextToken(); 51162987288SDimitry Andric if (NextTok->is(tok::pp_not_keyword)) 51262987288SDimitry Andric break; 5135f757f3fSDimitry Andric do { 5145f757f3fSDimitry Andric NextTok = Tokens->getNextToken(); 515*6c05f3a7SDimitry Andric } while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof)); 5165678d1d9SDimitry Andric 5175678d1d9SDimitry Andric while (NextTok->is(tok::comment)) 5185678d1d9SDimitry Andric NextTok = Tokens->getNextToken(); 5195678d1d9SDimitry Andric } 5205f757f3fSDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric switch (Tok->Tok.getKind()) { 5230b57cec5SDimitry Andric case tok::l_brace: 5240eae32dcSDimitry Andric if (Style.isJavaScript() && PrevTok) { 52581ad6265SDimitry Andric if (PrevTok->isOneOf(tok::colon, tok::less)) { 5260b57cec5SDimitry Andric // A ':' indicates this code is in a type, or a braced list 5270b57cec5SDimitry Andric // following a label in an object literal ({a: {b: 1}}). 5280b57cec5SDimitry Andric // A '<' could be an object used in a comparison, but that is nonsense 5290b57cec5SDimitry Andric // code (can never return true), so more likely it is a generic type 5300b57cec5SDimitry Andric // argument (`X<{a: string; b: number}>`). 5310b57cec5SDimitry Andric // The code below could be confused by semicolons between the 5320b57cec5SDimitry Andric // individual members in a type member list, which would normally 5330b57cec5SDimitry Andric // trigger BK_Block. In both cases, this must be parsed as an inline 5340b57cec5SDimitry Andric // braced init. 535e8d8bef9SDimitry Andric Tok->setBlockKind(BK_BracedInit); 53681ad6265SDimitry Andric } else if (PrevTok->is(tok::r_paren)) { 5370b57cec5SDimitry Andric // `) { }` can only occur in function or method declarations in JS. 538e8d8bef9SDimitry Andric Tok->setBlockKind(BK_Block); 53981ad6265SDimitry Andric } 5400b57cec5SDimitry Andric } else { 541e8d8bef9SDimitry Andric Tok->setBlockKind(BK_Unknown); 5420b57cec5SDimitry Andric } 54306c3fb27SDimitry Andric LBraceStack.push_back({Tok, PrevTok}); 5440b57cec5SDimitry Andric break; 5450b57cec5SDimitry Andric case tok::r_brace: 5460b57cec5SDimitry Andric if (LBraceStack.empty()) 5470b57cec5SDimitry Andric break; 5480fca6ea1SDimitry Andric if (auto *LBrace = LBraceStack.back().Tok; LBrace->is(BK_Unknown)) { 5490b57cec5SDimitry Andric bool ProbablyBracedList = false; 5500b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Proto) { 5510b57cec5SDimitry Andric ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square); 5520fca6ea1SDimitry Andric } else if (LBrace->isNot(TT_EnumLBrace)) { 5530b57cec5SDimitry Andric // Using OriginalColumn to distinguish between ObjC methods and 5540b57cec5SDimitry Andric // binary operators is a bit hacky. 5550b57cec5SDimitry Andric bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) && 5560b57cec5SDimitry Andric NextTok->OriginalColumn == 0; 5570b57cec5SDimitry Andric 55881ad6265SDimitry Andric // Try to detect a braced list. Note that regardless how we mark inner 55981ad6265SDimitry Andric // braces here, we will overwrite the BlockKind later if we parse a 56081ad6265SDimitry Andric // braced list (where all blocks inside are by default braced lists), 56181ad6265SDimitry Andric // or when we explicitly detect blocks (for example while parsing 56281ad6265SDimitry Andric // lambdas). 56381ad6265SDimitry Andric 56481ad6265SDimitry Andric // If we already marked the opening brace as braced list, the closing 56581ad6265SDimitry Andric // must also be part of it. 5660fca6ea1SDimitry Andric ProbablyBracedList = LBrace->is(TT_BracedListLBrace); 56781ad6265SDimitry Andric 56881ad6265SDimitry Andric ProbablyBracedList = ProbablyBracedList || 56981ad6265SDimitry Andric (Style.isJavaScript() && 57081ad6265SDimitry Andric NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in, 57181ad6265SDimitry Andric Keywords.kw_as)); 5720fca6ea1SDimitry Andric ProbablyBracedList = 573c80e69b0SDimitry Andric ProbablyBracedList || (IsCpp && (PrevTok->Tok.isLiteral() || 574c80e69b0SDimitry Andric NextTok->is(tok::l_paren))); 57581ad6265SDimitry Andric 5760b57cec5SDimitry Andric // If there is a comma, semicolon or right paren after the closing 57781ad6265SDimitry Andric // brace, we assume this is a braced initializer list. 5780b57cec5SDimitry Andric // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a 5790b57cec5SDimitry Andric // braced list in JS. 5800b57cec5SDimitry Andric ProbablyBracedList = 58181ad6265SDimitry Andric ProbablyBracedList || 5820b57cec5SDimitry Andric NextTok->isOneOf(tok::comma, tok::period, tok::colon, 58306c3fb27SDimitry Andric tok::r_paren, tok::r_square, tok::ellipsis); 58406c3fb27SDimitry Andric 58506c3fb27SDimitry Andric // Distinguish between braced list in a constructor initializer list 58606c3fb27SDimitry Andric // followed by constructor body, or just adjacent blocks. 58706c3fb27SDimitry Andric ProbablyBracedList = 58806c3fb27SDimitry Andric ProbablyBracedList || 58906c3fb27SDimitry Andric (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok && 5908a4dda33SDimitry Andric LBraceStack.back().PrevTok->isOneOf(tok::identifier, 5918a4dda33SDimitry Andric tok::greater)); 59281ad6265SDimitry Andric 59381ad6265SDimitry Andric ProbablyBracedList = 59481ad6265SDimitry Andric ProbablyBracedList || 5950b57cec5SDimitry Andric (NextTok->is(tok::identifier) && 59681ad6265SDimitry Andric !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace)); 59781ad6265SDimitry Andric 59881ad6265SDimitry Andric ProbablyBracedList = ProbablyBracedList || 5990b57cec5SDimitry Andric (NextTok->is(tok::semi) && 60081ad6265SDimitry Andric (!ExpectClassBody || LBraceStack.size() != 1)); 60181ad6265SDimitry Andric 60281ad6265SDimitry Andric ProbablyBracedList = 60381ad6265SDimitry Andric ProbablyBracedList || 6040b57cec5SDimitry Andric (NextTok->isBinaryOperator() && !NextIsObjCMethod); 60581ad6265SDimitry Andric 606480093f4SDimitry Andric if (!Style.isCSharp() && NextTok->is(tok::l_square)) { 6070b57cec5SDimitry Andric // We can have an array subscript after a braced init 6080b57cec5SDimitry Andric // list, but C++11 attributes are expected after blocks. 6090b57cec5SDimitry Andric NextTok = Tokens->getNextToken(); 6100b57cec5SDimitry Andric ProbablyBracedList = NextTok->isNot(tok::l_square); 6110b57cec5SDimitry Andric } 6125678d1d9SDimitry Andric 613c80e69b0SDimitry Andric // Cpp macro definition body that is a nonempty braced list or block: 6140fca6ea1SDimitry Andric if (IsCpp && Line->InMacroBody && PrevTok != FormatTok && 615c80e69b0SDimitry Andric !FormatTok->Previous && NextTok->is(tok::eof) && 6165678d1d9SDimitry Andric // A statement can end with only `;` (simple statement), a block 6175678d1d9SDimitry Andric // closing brace (compound statement), or `:` (label statement). 6185678d1d9SDimitry Andric // If PrevTok is a block opening brace, Tok ends an empty block. 6195678d1d9SDimitry Andric !PrevTok->isOneOf(tok::semi, BK_Block, tok::colon)) { 6205678d1d9SDimitry Andric ProbablyBracedList = true; 6215678d1d9SDimitry Andric } 6220b57cec5SDimitry Andric } 6230fca6ea1SDimitry Andric const auto BlockKind = ProbablyBracedList ? BK_BracedInit : BK_Block; 6240fca6ea1SDimitry Andric Tok->setBlockKind(BlockKind); 6250fca6ea1SDimitry Andric LBrace->setBlockKind(BlockKind); 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric LBraceStack.pop_back(); 6280b57cec5SDimitry Andric break; 6290b57cec5SDimitry Andric case tok::identifier: 6305f757f3fSDimitry Andric if (Tok->isNot(TT_StatementMacro)) 6310b57cec5SDimitry Andric break; 632bdd1243dSDimitry Andric [[fallthrough]]; 6330b57cec5SDimitry Andric case tok::at: 6340b57cec5SDimitry Andric case tok::semi: 6350b57cec5SDimitry Andric case tok::kw_if: 6360b57cec5SDimitry Andric case tok::kw_while: 6370b57cec5SDimitry Andric case tok::kw_for: 6380b57cec5SDimitry Andric case tok::kw_switch: 6390b57cec5SDimitry Andric case tok::kw_try: 6400b57cec5SDimitry Andric case tok::kw___try: 64106c3fb27SDimitry Andric if (!LBraceStack.empty() && LBraceStack.back().Tok->is(BK_Unknown)) 64206c3fb27SDimitry Andric LBraceStack.back().Tok->setBlockKind(BK_Block); 6430b57cec5SDimitry Andric break; 6440b57cec5SDimitry Andric default: 6450b57cec5SDimitry Andric break; 6460b57cec5SDimitry Andric } 6475678d1d9SDimitry Andric 6480b57cec5SDimitry Andric PrevTok = Tok; 6490b57cec5SDimitry Andric Tok = NextTok; 65081ad6265SDimitry Andric } while (Tok->isNot(tok::eof) && !LBraceStack.empty()); 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric // Assume other blocks for all unclosed opening braces. 65306c3fb27SDimitry Andric for (const auto &Entry : LBraceStack) 65406c3fb27SDimitry Andric if (Entry.Tok->is(BK_Unknown)) 65506c3fb27SDimitry Andric Entry.Tok->setBlockKind(BK_Block); 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6605f757f3fSDimitry Andric // Sets the token type of the directly previous right brace. 6615f757f3fSDimitry Andric void UnwrappedLineParser::setPreviousRBraceType(TokenType Type) { 6625f757f3fSDimitry Andric if (auto Prev = FormatTok->getPreviousNonComment(); 6635f757f3fSDimitry Andric Prev && Prev->is(tok::r_brace)) { 6645f757f3fSDimitry Andric Prev->setFinalizedType(Type); 6655f757f3fSDimitry Andric } 6665f757f3fSDimitry Andric } 6675f757f3fSDimitry Andric 6680b57cec5SDimitry Andric template <class T> 6690b57cec5SDimitry Andric static inline void hash_combine(std::size_t &seed, const T &v) { 6700b57cec5SDimitry Andric std::hash<T> hasher; 6710b57cec5SDimitry Andric seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric size_t UnwrappedLineParser::computePPHash() const { 6750b57cec5SDimitry Andric size_t h = 0; 6760b57cec5SDimitry Andric for (const auto &i : PPStack) { 6770b57cec5SDimitry Andric hash_combine(h, size_t(i.Kind)); 6780b57cec5SDimitry Andric hash_combine(h, i.Line); 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric return h; 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 68381ad6265SDimitry Andric // Checks whether \p ParsedLine might fit on a single line. If \p OpeningBrace 68481ad6265SDimitry Andric // is not null, subtracts its length (plus the preceding space) when computing 68581ad6265SDimitry Andric // the length of \p ParsedLine. We must clone the tokens of \p ParsedLine before 68681ad6265SDimitry Andric // running the token annotator on it so that we can restore them afterward. 68781ad6265SDimitry Andric bool UnwrappedLineParser::mightFitOnOneLine( 68881ad6265SDimitry Andric UnwrappedLine &ParsedLine, const FormatToken *OpeningBrace) const { 68981ad6265SDimitry Andric const auto ColumnLimit = Style.ColumnLimit; 69081ad6265SDimitry Andric if (ColumnLimit == 0) 69181ad6265SDimitry Andric return true; 69281ad6265SDimitry Andric 69381ad6265SDimitry Andric auto &Tokens = ParsedLine.Tokens; 69481ad6265SDimitry Andric assert(!Tokens.empty()); 69581ad6265SDimitry Andric 69681ad6265SDimitry Andric const auto *LastToken = Tokens.back().Tok; 69781ad6265SDimitry Andric assert(LastToken); 69881ad6265SDimitry Andric 69981ad6265SDimitry Andric SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size()); 70081ad6265SDimitry Andric 70181ad6265SDimitry Andric int Index = 0; 70281ad6265SDimitry Andric for (const auto &Token : Tokens) { 70381ad6265SDimitry Andric assert(Token.Tok); 70481ad6265SDimitry Andric auto &SavedToken = SavedTokens[Index++]; 70581ad6265SDimitry Andric SavedToken.Tok = new FormatToken; 70681ad6265SDimitry Andric SavedToken.Tok->copyFrom(*Token.Tok); 70781ad6265SDimitry Andric SavedToken.Children = std::move(Token.Children); 70881ad6265SDimitry Andric } 70981ad6265SDimitry Andric 71081ad6265SDimitry Andric AnnotatedLine Line(ParsedLine); 71181ad6265SDimitry Andric assert(Line.Last == LastToken); 71281ad6265SDimitry Andric 71381ad6265SDimitry Andric TokenAnnotator Annotator(Style, Keywords); 71481ad6265SDimitry Andric Annotator.annotate(Line); 71581ad6265SDimitry Andric Annotator.calculateFormattingInformation(Line); 71681ad6265SDimitry Andric 71781ad6265SDimitry Andric auto Length = LastToken->TotalLength; 71881ad6265SDimitry Andric if (OpeningBrace) { 71981ad6265SDimitry Andric assert(OpeningBrace != Tokens.front().Tok); 720bdd1243dSDimitry Andric if (auto Prev = OpeningBrace->Previous; 721bdd1243dSDimitry Andric Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) { 722bdd1243dSDimitry Andric Length -= ColumnLimit; 723bdd1243dSDimitry Andric } 72481ad6265SDimitry Andric Length -= OpeningBrace->TokenText.size() + 1; 72581ad6265SDimitry Andric } 72681ad6265SDimitry Andric 727bdd1243dSDimitry Andric if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) { 728bdd1243dSDimitry Andric assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace)); 729bdd1243dSDimitry Andric Length -= FirstToken->TokenText.size() + 1; 730bdd1243dSDimitry Andric } 731bdd1243dSDimitry Andric 73281ad6265SDimitry Andric Index = 0; 73381ad6265SDimitry Andric for (auto &Token : Tokens) { 73481ad6265SDimitry Andric const auto &SavedToken = SavedTokens[Index++]; 73581ad6265SDimitry Andric Token.Tok->copyFrom(*SavedToken.Tok); 73681ad6265SDimitry Andric Token.Children = std::move(SavedToken.Children); 73781ad6265SDimitry Andric delete SavedToken.Tok; 73881ad6265SDimitry Andric } 73981ad6265SDimitry Andric 740bdd1243dSDimitry Andric // If these change PPLevel needs to be used for get correct indentation. 741bdd1243dSDimitry Andric assert(!Line.InMacroBody); 742bdd1243dSDimitry Andric assert(!Line.InPPDirective); 74381ad6265SDimitry Andric return Line.Level * Style.IndentWidth + Length <= ColumnLimit; 74481ad6265SDimitry Andric } 74581ad6265SDimitry Andric 7465f757f3fSDimitry Andric FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration, 7475f757f3fSDimitry Andric unsigned AddLevels, bool MunchSemi, 7485f757f3fSDimitry Andric bool KeepBraces, 7495f757f3fSDimitry Andric IfStmtKind *IfKind, 7505f757f3fSDimitry Andric bool UnindentWhitesmithsBraces) { 75181ad6265SDimitry Andric auto HandleVerilogBlockLabel = [this]() { 75281ad6265SDimitry Andric // ":" name 75381ad6265SDimitry Andric if (Style.isVerilog() && FormatTok->is(tok::colon)) { 75481ad6265SDimitry Andric nextToken(); 75581ad6265SDimitry Andric if (Keywords.isVerilogIdentifier(*FormatTok)) 75681ad6265SDimitry Andric nextToken(); 75781ad6265SDimitry Andric } 75881ad6265SDimitry Andric }; 75981ad6265SDimitry Andric 760bdd1243dSDimitry Andric // Whether this is a Verilog-specific block that has a special header like a 761bdd1243dSDimitry Andric // module. 762bdd1243dSDimitry Andric const bool VerilogHierarchy = 763bdd1243dSDimitry Andric Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok); 76481ad6265SDimitry Andric assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) || 765bdd1243dSDimitry Andric (Style.isVerilog() && 766bdd1243dSDimitry Andric (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) && 7670b57cec5SDimitry Andric "'{' or macro block token expected"); 76804eeddc0SDimitry Andric FormatToken *Tok = FormatTok; 76981ad6265SDimitry Andric const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment); 77081ad6265SDimitry Andric auto Index = CurrentLines->size(); 7710b57cec5SDimitry Andric const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin); 772e8d8bef9SDimitry Andric FormatTok->setBlockKind(BK_Block); 7730b57cec5SDimitry Andric 77423408297SDimitry Andric // For Whitesmiths mode, jump to the next level prior to skipping over the 77523408297SDimitry Andric // braces. 776bdd1243dSDimitry Andric if (!VerilogHierarchy && AddLevels > 0 && 777bdd1243dSDimitry Andric Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) { 77823408297SDimitry Andric ++Line->Level; 779bdd1243dSDimitry Andric } 78023408297SDimitry Andric 7810b57cec5SDimitry Andric size_t PPStartHash = computePPHash(); 7820b57cec5SDimitry Andric 78381ad6265SDimitry Andric const unsigned InitialLevel = Line->Level; 784bdd1243dSDimitry Andric if (VerilogHierarchy) { 785bdd1243dSDimitry Andric AddLevels += parseVerilogHierarchyHeader(); 786bdd1243dSDimitry Andric } else { 78723408297SDimitry Andric nextToken(/*LevelDifference=*/AddLevels); 78881ad6265SDimitry Andric HandleVerilogBlockLabel(); 789bdd1243dSDimitry Andric } 79081ad6265SDimitry Andric 79181ad6265SDimitry Andric // Bail out if there are too many levels. Otherwise, the stack might overflow. 79281ad6265SDimitry Andric if (Line->Level > 300) 79381ad6265SDimitry Andric return nullptr; 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric if (MacroBlock && FormatTok->is(tok::l_paren)) 7960b57cec5SDimitry Andric parseParens(); 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric size_t NbPreprocessorDirectives = 79906c3fb27SDimitry Andric !parsingPPDirective() ? PreprocessorDirectives.size() : 0; 8000b57cec5SDimitry Andric addUnwrappedLine(); 8010b57cec5SDimitry Andric size_t OpeningLineIndex = 8020b57cec5SDimitry Andric CurrentLines->empty() 8030b57cec5SDimitry Andric ? (UnwrappedLine::kInvalidIndex) 8040b57cec5SDimitry Andric : (CurrentLines->size() - 1 - NbPreprocessorDirectives); 8050b57cec5SDimitry Andric 80623408297SDimitry Andric // Whitesmiths is weird here. The brace needs to be indented for the namespace 80723408297SDimitry Andric // block, but the block itself may not be indented depending on the style 80823408297SDimitry Andric // settings. This allows the format to back up one level in those cases. 80923408297SDimitry Andric if (UnindentWhitesmithsBraces) 81023408297SDimitry Andric --Line->Level; 81123408297SDimitry Andric 8120b57cec5SDimitry Andric ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, 8130b57cec5SDimitry Andric MustBeDeclaration); 81423408297SDimitry Andric if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths) 81523408297SDimitry Andric Line->Level += AddLevels; 81604eeddc0SDimitry Andric 81781ad6265SDimitry Andric FormatToken *IfLBrace = nullptr; 8185f757f3fSDimitry Andric const bool SimpleBlock = parseLevel(Tok, IfKind, &IfLBrace); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric if (eof()) 82181ad6265SDimitry Andric return IfLBrace; 8220b57cec5SDimitry Andric 8235f757f3fSDimitry Andric if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd) 8245f757f3fSDimitry Andric : FormatTok->isNot(tok::r_brace)) { 8250b57cec5SDimitry Andric Line->Level = InitialLevel; 826e8d8bef9SDimitry Andric FormatTok->setBlockKind(BK_Block); 82781ad6265SDimitry Andric return IfLBrace; 82804eeddc0SDimitry Andric } 82904eeddc0SDimitry Andric 8300fca6ea1SDimitry Andric if (FormatTok->is(tok::r_brace)) { 8310fca6ea1SDimitry Andric FormatTok->setBlockKind(BK_Block); 8320fca6ea1SDimitry Andric if (Tok->is(TT_NamespaceLBrace)) 8335f757f3fSDimitry Andric FormatTok->setFinalizedType(TT_NamespaceRBrace); 8340fca6ea1SDimitry Andric } 8355f757f3fSDimitry Andric 836bdd1243dSDimitry Andric const bool IsFunctionRBrace = 837bdd1243dSDimitry Andric FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace); 838bdd1243dSDimitry Andric 83981ad6265SDimitry Andric auto RemoveBraces = [=]() mutable { 84081ad6265SDimitry Andric if (!SimpleBlock) 84181ad6265SDimitry Andric return false; 84281ad6265SDimitry Andric assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace)); 84304eeddc0SDimitry Andric assert(FormatTok->is(tok::r_brace)); 84481ad6265SDimitry Andric const bool WrappedOpeningBrace = !Tok->Previous; 84581ad6265SDimitry Andric if (WrappedOpeningBrace && FollowedByComment) 84681ad6265SDimitry Andric return false; 84781ad6265SDimitry Andric const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional; 84881ad6265SDimitry Andric if (KeepBraces && !HasRequiredIfBraces) 84981ad6265SDimitry Andric return false; 85081ad6265SDimitry Andric if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) { 85104eeddc0SDimitry Andric const FormatToken *Previous = Tokens->getPreviousToken(); 85204eeddc0SDimitry Andric assert(Previous); 85381ad6265SDimitry Andric if (Previous->is(tok::r_brace) && !Previous->Optional) 85481ad6265SDimitry Andric return false; 85581ad6265SDimitry Andric } 85681ad6265SDimitry Andric assert(!CurrentLines->empty()); 85781ad6265SDimitry Andric auto &LastLine = CurrentLines->back(); 85881ad6265SDimitry Andric if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine)) 85981ad6265SDimitry Andric return false; 86081ad6265SDimitry Andric if (Tok->is(TT_ElseLBrace)) 86181ad6265SDimitry Andric return true; 86281ad6265SDimitry Andric if (WrappedOpeningBrace) { 86381ad6265SDimitry Andric assert(Index > 0); 86481ad6265SDimitry Andric --Index; // The line above the wrapped l_brace. 86581ad6265SDimitry Andric Tok = nullptr; 86681ad6265SDimitry Andric } 86781ad6265SDimitry Andric return mightFitOnOneLine((*CurrentLines)[Index], Tok); 86881ad6265SDimitry Andric }; 86981ad6265SDimitry Andric if (RemoveBraces()) { 87004eeddc0SDimitry Andric Tok->MatchingParen = FormatTok; 87104eeddc0SDimitry Andric FormatTok->MatchingParen = Tok; 87204eeddc0SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric size_t PPEndHash = computePPHash(); 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric // Munch the closing brace. 87723408297SDimitry Andric nextToken(/*LevelDifference=*/-AddLevels); 878bdd1243dSDimitry Andric 879bdd1243dSDimitry Andric // When this is a function block and there is an unnecessary semicolon 880bdd1243dSDimitry Andric // afterwards then mark it as optional (so the RemoveSemi pass can get rid of 881bdd1243dSDimitry Andric // it later). 882bdd1243dSDimitry Andric if (Style.RemoveSemicolon && IsFunctionRBrace) { 883bdd1243dSDimitry Andric while (FormatTok->is(tok::semi)) { 884bdd1243dSDimitry Andric FormatTok->Optional = true; 885bdd1243dSDimitry Andric nextToken(); 886bdd1243dSDimitry Andric } 887bdd1243dSDimitry Andric } 888bdd1243dSDimitry Andric 88981ad6265SDimitry Andric HandleVerilogBlockLabel(); 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric if (MacroBlock && FormatTok->is(tok::l_paren)) 8920b57cec5SDimitry Andric parseParens(); 8930b57cec5SDimitry Andric 894bdd1243dSDimitry Andric Line->Level = InitialLevel; 895bdd1243dSDimitry Andric 89681ad6265SDimitry Andric if (FormatTok->is(tok::kw_noexcept)) { 89781ad6265SDimitry Andric // A noexcept in a requires expression. 89881ad6265SDimitry Andric nextToken(); 89981ad6265SDimitry Andric } 90081ad6265SDimitry Andric 901e8d8bef9SDimitry Andric if (FormatTok->is(tok::arrow)) { 90281ad6265SDimitry Andric // Following the } or noexcept we can find a trailing return type arrow 903e8d8bef9SDimitry Andric // as part of an implicit conversion constraint. 904e8d8bef9SDimitry Andric nextToken(); 905e8d8bef9SDimitry Andric parseStructuralElement(); 906e8d8bef9SDimitry Andric } 907e8d8bef9SDimitry Andric 90881ad6265SDimitry Andric if (MunchSemi && FormatTok->is(tok::semi)) 9090b57cec5SDimitry Andric nextToken(); 910e8d8bef9SDimitry Andric 9110b57cec5SDimitry Andric if (PPStartHash == PPEndHash) { 9120b57cec5SDimitry Andric Line->MatchingOpeningBlockLineIndex = OpeningLineIndex; 9130b57cec5SDimitry Andric if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) { 9140b57cec5SDimitry Andric // Update the opening line to add the forward reference as well 9150b57cec5SDimitry Andric (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex = 9160b57cec5SDimitry Andric CurrentLines->size() - 1; 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric } 91904eeddc0SDimitry Andric 92081ad6265SDimitry Andric return IfLBrace; 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric static bool isGoogScope(const UnwrappedLine &Line) { 9240b57cec5SDimitry Andric // FIXME: Closure-library specific stuff should not be hard-coded but be 9250b57cec5SDimitry Andric // configurable. 9260b57cec5SDimitry Andric if (Line.Tokens.size() < 4) 9270b57cec5SDimitry Andric return false; 9280b57cec5SDimitry Andric auto I = Line.Tokens.begin(); 9290b57cec5SDimitry Andric if (I->Tok->TokenText != "goog") 9300b57cec5SDimitry Andric return false; 9310b57cec5SDimitry Andric ++I; 9320b57cec5SDimitry Andric if (I->Tok->isNot(tok::period)) 9330b57cec5SDimitry Andric return false; 9340b57cec5SDimitry Andric ++I; 9350b57cec5SDimitry Andric if (I->Tok->TokenText != "scope") 9360b57cec5SDimitry Andric return false; 9370b57cec5SDimitry Andric ++I; 9380b57cec5SDimitry Andric return I->Tok->is(tok::l_paren); 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric static bool isIIFE(const UnwrappedLine &Line, 9420b57cec5SDimitry Andric const AdditionalKeywords &Keywords) { 9430b57cec5SDimitry Andric // Look for the start of an immediately invoked anonymous function. 9440b57cec5SDimitry Andric // https://en.wikipedia.org/wiki/Immediately-invoked_function_expression 9450b57cec5SDimitry Andric // This is commonly done in JavaScript to create a new, anonymous scope. 9460b57cec5SDimitry Andric // Example: (function() { ... })() 9470b57cec5SDimitry Andric if (Line.Tokens.size() < 3) 9480b57cec5SDimitry Andric return false; 9490b57cec5SDimitry Andric auto I = Line.Tokens.begin(); 9500b57cec5SDimitry Andric if (I->Tok->isNot(tok::l_paren)) 9510b57cec5SDimitry Andric return false; 9520b57cec5SDimitry Andric ++I; 9530b57cec5SDimitry Andric if (I->Tok->isNot(Keywords.kw_function)) 9540b57cec5SDimitry Andric return false; 9550b57cec5SDimitry Andric ++I; 9560b57cec5SDimitry Andric return I->Tok->is(tok::l_paren); 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric 9590b57cec5SDimitry Andric static bool ShouldBreakBeforeBrace(const FormatStyle &Style, 9600b57cec5SDimitry Andric const FormatToken &InitialToken) { 96181ad6265SDimitry Andric tok::TokenKind Kind = InitialToken.Tok.getKind(); 96281ad6265SDimitry Andric if (InitialToken.is(TT_NamespaceMacro)) 96381ad6265SDimitry Andric Kind = tok::kw_namespace; 96481ad6265SDimitry Andric 96581ad6265SDimitry Andric switch (Kind) { 96681ad6265SDimitry Andric case tok::kw_namespace: 9670b57cec5SDimitry Andric return Style.BraceWrapping.AfterNamespace; 96881ad6265SDimitry Andric case tok::kw_class: 9690b57cec5SDimitry Andric return Style.BraceWrapping.AfterClass; 97081ad6265SDimitry Andric case tok::kw_union: 9710b57cec5SDimitry Andric return Style.BraceWrapping.AfterUnion; 97281ad6265SDimitry Andric case tok::kw_struct: 9730b57cec5SDimitry Andric return Style.BraceWrapping.AfterStruct; 97481ad6265SDimitry Andric case tok::kw_enum: 97504eeddc0SDimitry Andric return Style.BraceWrapping.AfterEnum; 97681ad6265SDimitry Andric default: 9770b57cec5SDimitry Andric return false; 9780b57cec5SDimitry Andric } 97981ad6265SDimitry Andric } 9800b57cec5SDimitry Andric 9815f757f3fSDimitry Andric void UnwrappedLineParser::parseChildBlock() { 98281ad6265SDimitry Andric assert(FormatTok->is(tok::l_brace)); 983e8d8bef9SDimitry Andric FormatTok->setBlockKind(BK_Block); 98481ad6265SDimitry Andric const FormatToken *OpeningBrace = FormatTok; 9850b57cec5SDimitry Andric nextToken(); 9860b57cec5SDimitry Andric { 9870eae32dcSDimitry Andric bool SkipIndent = (Style.isJavaScript() && 9880b57cec5SDimitry Andric (isGoogScope(*Line) || isIIFE(*Line, Keywords))); 9890b57cec5SDimitry Andric ScopedLineState LineState(*this); 9900b57cec5SDimitry Andric ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, 9910b57cec5SDimitry Andric /*MustBeDeclaration=*/false); 9920b57cec5SDimitry Andric Line->Level += SkipIndent ? 0 : 1; 9935f757f3fSDimitry Andric parseLevel(OpeningBrace); 9940b57cec5SDimitry Andric flushComments(isOnNewLine(*FormatTok)); 9950b57cec5SDimitry Andric Line->Level -= SkipIndent ? 0 : 1; 9960b57cec5SDimitry Andric } 9970b57cec5SDimitry Andric nextToken(); 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric void UnwrappedLineParser::parsePPDirective() { 100181ad6265SDimitry Andric assert(FormatTok->is(tok::hash) && "'#' expected"); 10020b57cec5SDimitry Andric ScopedMacroState MacroState(*Line, Tokens, FormatTok); 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric nextToken(); 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric if (!FormatTok->Tok.getIdentifierInfo()) { 10070b57cec5SDimitry Andric parsePPUnknown(); 10080b57cec5SDimitry Andric return; 10090b57cec5SDimitry Andric } 10100b57cec5SDimitry Andric 10110b57cec5SDimitry Andric switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) { 10120b57cec5SDimitry Andric case tok::pp_define: 10130b57cec5SDimitry Andric parsePPDefine(); 10140b57cec5SDimitry Andric return; 10150b57cec5SDimitry Andric case tok::pp_if: 10160b57cec5SDimitry Andric parsePPIf(/*IfDef=*/false); 10170b57cec5SDimitry Andric break; 10180b57cec5SDimitry Andric case tok::pp_ifdef: 10190b57cec5SDimitry Andric case tok::pp_ifndef: 10200b57cec5SDimitry Andric parsePPIf(/*IfDef=*/true); 10210b57cec5SDimitry Andric break; 10220b57cec5SDimitry Andric case tok::pp_else: 1023fe6060f1SDimitry Andric case tok::pp_elifdef: 1024fe6060f1SDimitry Andric case tok::pp_elifndef: 10250b57cec5SDimitry Andric case tok::pp_elif: 1026bdd1243dSDimitry Andric parsePPElse(); 10270b57cec5SDimitry Andric break; 10280b57cec5SDimitry Andric case tok::pp_endif: 10290b57cec5SDimitry Andric parsePPEndIf(); 10300b57cec5SDimitry Andric break; 1031bdd1243dSDimitry Andric case tok::pp_pragma: 1032bdd1243dSDimitry Andric parsePPPragma(); 1033bdd1243dSDimitry Andric break; 10340b57cec5SDimitry Andric default: 10350b57cec5SDimitry Andric parsePPUnknown(); 10360b57cec5SDimitry Andric break; 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) { 10410b57cec5SDimitry Andric size_t Line = CurrentLines->size(); 10420b57cec5SDimitry Andric if (CurrentLines == &PreprocessorDirectives) 10430b57cec5SDimitry Andric Line += Lines.size(); 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric if (Unreachable || 104681ad6265SDimitry Andric (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) { 10470b57cec5SDimitry Andric PPStack.push_back({PP_Unreachable, Line}); 104881ad6265SDimitry Andric } else { 10490b57cec5SDimitry Andric PPStack.push_back({PP_Conditional, Line}); 10500b57cec5SDimitry Andric } 105181ad6265SDimitry Andric } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) { 10540b57cec5SDimitry Andric ++PPBranchLevel; 10550b57cec5SDimitry Andric assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size()); 10560b57cec5SDimitry Andric if (PPBranchLevel == (int)PPLevelBranchIndex.size()) { 10570b57cec5SDimitry Andric PPLevelBranchIndex.push_back(0); 10580b57cec5SDimitry Andric PPLevelBranchCount.push_back(0); 10590b57cec5SDimitry Andric } 1060bdd1243dSDimitry Andric PPChainBranchIndex.push(Unreachable ? -1 : 0); 10610b57cec5SDimitry Andric bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0; 10620b57cec5SDimitry Andric conditionalCompilationCondition(Unreachable || Skip); 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric void UnwrappedLineParser::conditionalCompilationAlternative() { 10660b57cec5SDimitry Andric if (!PPStack.empty()) 10670b57cec5SDimitry Andric PPStack.pop_back(); 10680b57cec5SDimitry Andric assert(PPBranchLevel < (int)PPLevelBranchIndex.size()); 10690b57cec5SDimitry Andric if (!PPChainBranchIndex.empty()) 10700b57cec5SDimitry Andric ++PPChainBranchIndex.top(); 10710b57cec5SDimitry Andric conditionalCompilationCondition( 10720b57cec5SDimitry Andric PPBranchLevel >= 0 && !PPChainBranchIndex.empty() && 10730b57cec5SDimitry Andric PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top()); 10740b57cec5SDimitry Andric } 10750b57cec5SDimitry Andric 10760b57cec5SDimitry Andric void UnwrappedLineParser::conditionalCompilationEnd() { 10770b57cec5SDimitry Andric assert(PPBranchLevel < (int)PPLevelBranchIndex.size()); 10780b57cec5SDimitry Andric if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) { 107981ad6265SDimitry Andric if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel]) 10800b57cec5SDimitry Andric PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1; 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric // Guard against #endif's without #if. 10830b57cec5SDimitry Andric if (PPBranchLevel > -1) 10840b57cec5SDimitry Andric --PPBranchLevel; 10850b57cec5SDimitry Andric if (!PPChainBranchIndex.empty()) 10860b57cec5SDimitry Andric PPChainBranchIndex.pop(); 10870b57cec5SDimitry Andric if (!PPStack.empty()) 10880b57cec5SDimitry Andric PPStack.pop_back(); 10890b57cec5SDimitry Andric } 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric void UnwrappedLineParser::parsePPIf(bool IfDef) { 10920b57cec5SDimitry Andric bool IfNDef = FormatTok->is(tok::pp_ifndef); 10930b57cec5SDimitry Andric nextToken(); 10940b57cec5SDimitry Andric bool Unreachable = false; 10950b57cec5SDimitry Andric if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0")) 10960b57cec5SDimitry Andric Unreachable = true; 10970b57cec5SDimitry Andric if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG") 10980b57cec5SDimitry Andric Unreachable = true; 10990b57cec5SDimitry Andric conditionalCompilationStart(Unreachable); 11000b57cec5SDimitry Andric FormatToken *IfCondition = FormatTok; 11010b57cec5SDimitry Andric // If there's a #ifndef on the first line, and the only lines before it are 11020b57cec5SDimitry Andric // comments, it could be an include guard. 11030b57cec5SDimitry Andric bool MaybeIncludeGuard = IfNDef; 110481ad6265SDimitry Andric if (IncludeGuard == IG_Inited && MaybeIncludeGuard) { 11050b57cec5SDimitry Andric for (auto &Line : Lines) { 11065f757f3fSDimitry Andric if (Line.Tokens.front().Tok->isNot(tok::comment)) { 11070b57cec5SDimitry Andric MaybeIncludeGuard = false; 11080b57cec5SDimitry Andric IncludeGuard = IG_Rejected; 11090b57cec5SDimitry Andric break; 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric } 111281ad6265SDimitry Andric } 11130b57cec5SDimitry Andric --PPBranchLevel; 11140b57cec5SDimitry Andric parsePPUnknown(); 11150b57cec5SDimitry Andric ++PPBranchLevel; 11160b57cec5SDimitry Andric if (IncludeGuard == IG_Inited && MaybeIncludeGuard) { 11170b57cec5SDimitry Andric IncludeGuard = IG_IfNdefed; 11180b57cec5SDimitry Andric IncludeGuardToken = IfCondition; 11190b57cec5SDimitry Andric } 11200b57cec5SDimitry Andric } 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric void UnwrappedLineParser::parsePPElse() { 11230b57cec5SDimitry Andric // If a potential include guard has an #else, it's not an include guard. 11240b57cec5SDimitry Andric if (IncludeGuard == IG_Defined && PPBranchLevel == 0) 11250b57cec5SDimitry Andric IncludeGuard = IG_Rejected; 1126bdd1243dSDimitry Andric // Don't crash when there is an #else without an #if. 1127bdd1243dSDimitry Andric assert(PPBranchLevel >= -1); 1128bdd1243dSDimitry Andric if (PPBranchLevel == -1) 1129bdd1243dSDimitry Andric conditionalCompilationStart(/*Unreachable=*/true); 11300b57cec5SDimitry Andric conditionalCompilationAlternative(); 11310b57cec5SDimitry Andric --PPBranchLevel; 11320b57cec5SDimitry Andric parsePPUnknown(); 11330b57cec5SDimitry Andric ++PPBranchLevel; 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric void UnwrappedLineParser::parsePPEndIf() { 11370b57cec5SDimitry Andric conditionalCompilationEnd(); 11380b57cec5SDimitry Andric parsePPUnknown(); 11390b57cec5SDimitry Andric // If the #endif of a potential include guard is the last thing in the file, 11400b57cec5SDimitry Andric // then we found an include guard. 11414824e7fdSDimitry Andric if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() && 114281ad6265SDimitry Andric Style.IndentPPDirectives != FormatStyle::PPDIS_None) { 11430b57cec5SDimitry Andric IncludeGuard = IG_Found; 11440b57cec5SDimitry Andric } 114581ad6265SDimitry Andric } 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric void UnwrappedLineParser::parsePPDefine() { 11480b57cec5SDimitry Andric nextToken(); 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andric if (!FormatTok->Tok.getIdentifierInfo()) { 11510b57cec5SDimitry Andric IncludeGuard = IG_Rejected; 11520b57cec5SDimitry Andric IncludeGuardToken = nullptr; 11530b57cec5SDimitry Andric parsePPUnknown(); 11540b57cec5SDimitry Andric return; 11550b57cec5SDimitry Andric } 11560b57cec5SDimitry Andric 11570b57cec5SDimitry Andric if (IncludeGuard == IG_IfNdefed && 11580b57cec5SDimitry Andric IncludeGuardToken->TokenText == FormatTok->TokenText) { 11590b57cec5SDimitry Andric IncludeGuard = IG_Defined; 11600b57cec5SDimitry Andric IncludeGuardToken = nullptr; 11610b57cec5SDimitry Andric for (auto &Line : Lines) { 11620b57cec5SDimitry Andric if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) { 11630b57cec5SDimitry Andric IncludeGuard = IG_Rejected; 11640b57cec5SDimitry Andric break; 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric } 11670b57cec5SDimitry Andric } 11680b57cec5SDimitry Andric 116981ad6265SDimitry Andric // In the context of a define, even keywords should be treated as normal 117081ad6265SDimitry Andric // identifiers. Setting the kind to identifier is not enough, because we need 117181ad6265SDimitry Andric // to treat additional keywords like __except as well, which are already 117281ad6265SDimitry Andric // identifiers. Setting the identifier info to null interferes with include 117381ad6265SDimitry Andric // guard processing above, and changes preprocessing nesting. 117481ad6265SDimitry Andric FormatTok->Tok.setKind(tok::identifier); 117581ad6265SDimitry Andric FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define); 11760b57cec5SDimitry Andric nextToken(); 11770b57cec5SDimitry Andric if (FormatTok->Tok.getKind() == tok::l_paren && 117804eeddc0SDimitry Andric !FormatTok->hasWhitespaceBefore()) { 11790b57cec5SDimitry Andric parseParens(); 11800b57cec5SDimitry Andric } 11810b57cec5SDimitry Andric if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) 11820b57cec5SDimitry Andric Line->Level += PPBranchLevel + 1; 11830b57cec5SDimitry Andric addUnwrappedLine(); 11840b57cec5SDimitry Andric ++Line->Level; 11850b57cec5SDimitry Andric 1186bdd1243dSDimitry Andric Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1); 1187bdd1243dSDimitry Andric assert((int)Line->PPLevel >= 0); 1188bdd1243dSDimitry Andric Line->InMacroBody = true; 1189bdd1243dSDimitry Andric 11907a6dacacSDimitry Andric if (Style.SkipMacroDefinitionBody) { 11910fca6ea1SDimitry Andric while (!eof()) { 11927a6dacacSDimitry Andric FormatTok->Finalized = true; 11930fca6ea1SDimitry Andric FormatTok = Tokens->getNextToken(); 11940fca6ea1SDimitry Andric } 11957a6dacacSDimitry Andric addUnwrappedLine(); 11967a6dacacSDimitry Andric return; 11977a6dacacSDimitry Andric } 11987a6dacacSDimitry Andric 11990b57cec5SDimitry Andric // Errors during a preprocessor directive can only affect the layout of the 12000b57cec5SDimitry Andric // preprocessor directive, and thus we ignore them. An alternative approach 12010b57cec5SDimitry Andric // would be to use the same approach we use on the file level (no 12020b57cec5SDimitry Andric // re-indentation if there was a structural error) within the macro 12030b57cec5SDimitry Andric // definition. 12040b57cec5SDimitry Andric parseFile(); 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric 1207bdd1243dSDimitry Andric void UnwrappedLineParser::parsePPPragma() { 1208bdd1243dSDimitry Andric Line->InPragmaDirective = true; 1209bdd1243dSDimitry Andric parsePPUnknown(); 1210bdd1243dSDimitry Andric } 1211bdd1243dSDimitry Andric 12120b57cec5SDimitry Andric void UnwrappedLineParser::parsePPUnknown() { 12130b57cec5SDimitry Andric do { 12140b57cec5SDimitry Andric nextToken(); 12150b57cec5SDimitry Andric } while (!eof()); 12160b57cec5SDimitry Andric if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) 12170b57cec5SDimitry Andric Line->Level += PPBranchLevel + 1; 12180b57cec5SDimitry Andric addUnwrappedLine(); 12190b57cec5SDimitry Andric } 12200b57cec5SDimitry Andric 12215ffd83dbSDimitry Andric // Here we exclude certain tokens that are not usually the first token in an 12220b57cec5SDimitry Andric // unwrapped line. This is used in attempt to distinguish macro calls without 12230b57cec5SDimitry Andric // trailing semicolons from other constructs split to several lines. 12245ffd83dbSDimitry Andric static bool tokenCanStartNewLine(const FormatToken &Tok) { 12250b57cec5SDimitry Andric // Semicolon can be a null-statement, l_square can be a start of a macro or 12260b57cec5SDimitry Andric // a C++11 attribute, but this doesn't seem to be common. 12275f757f3fSDimitry Andric return !Tok.isOneOf(tok::semi, tok::l_brace, 12285f757f3fSDimitry Andric // Tokens that can only be used as binary operators and a 12295f757f3fSDimitry Andric // part of overloaded operator names. 12305f757f3fSDimitry Andric tok::period, tok::periodstar, tok::arrow, tok::arrowstar, 12315f757f3fSDimitry Andric tok::less, tok::greater, tok::slash, tok::percent, 12325f757f3fSDimitry Andric tok::lessless, tok::greatergreater, tok::equal, 12335f757f3fSDimitry Andric tok::plusequal, tok::minusequal, tok::starequal, 12345f757f3fSDimitry Andric tok::slashequal, tok::percentequal, tok::ampequal, 12355f757f3fSDimitry Andric tok::pipeequal, tok::caretequal, tok::greatergreaterequal, 12365f757f3fSDimitry Andric tok::lesslessequal, 12375f757f3fSDimitry Andric // Colon is used in labels, base class lists, initializer 12385f757f3fSDimitry Andric // lists, range-based for loops, ternary operator, but 12395f757f3fSDimitry Andric // should never be the first token in an unwrapped line. 12405f757f3fSDimitry Andric tok::colon, 12410b57cec5SDimitry Andric // 'noexcept' is a trailing annotation. 12425f757f3fSDimitry Andric tok::kw_noexcept); 12430b57cec5SDimitry Andric } 12440b57cec5SDimitry Andric 12450b57cec5SDimitry Andric static bool mustBeJSIdent(const AdditionalKeywords &Keywords, 12460b57cec5SDimitry Andric const FormatToken *FormatTok) { 12470b57cec5SDimitry Andric // FIXME: This returns true for C/C++ keywords like 'struct'. 12480b57cec5SDimitry Andric return FormatTok->is(tok::identifier) && 124906c3fb27SDimitry Andric (!FormatTok->Tok.getIdentifierInfo() || 12500b57cec5SDimitry Andric !FormatTok->isOneOf( 12510b57cec5SDimitry Andric Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async, 12520b57cec5SDimitry Andric Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally, 12530b57cec5SDimitry Andric Keywords.kw_function, Keywords.kw_import, Keywords.kw_is, 12540b57cec5SDimitry Andric Keywords.kw_let, Keywords.kw_var, tok::kw_const, 12550b57cec5SDimitry Andric Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements, 1256349cc55cSDimitry Andric Keywords.kw_instanceof, Keywords.kw_interface, 1257349cc55cSDimitry Andric Keywords.kw_override, Keywords.kw_throws, Keywords.kw_from)); 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric 12600b57cec5SDimitry Andric static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords, 12610b57cec5SDimitry Andric const FormatToken *FormatTok) { 12620b57cec5SDimitry Andric return FormatTok->Tok.isLiteral() || 12630b57cec5SDimitry Andric FormatTok->isOneOf(tok::kw_true, tok::kw_false) || 12640b57cec5SDimitry Andric mustBeJSIdent(Keywords, FormatTok); 12650b57cec5SDimitry Andric } 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric // isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement 12680b57cec5SDimitry Andric // when encountered after a value (see mustBeJSIdentOrValue). 12690b57cec5SDimitry Andric static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords, 12700b57cec5SDimitry Andric const FormatToken *FormatTok) { 12710b57cec5SDimitry Andric return FormatTok->isOneOf( 12720b57cec5SDimitry Andric tok::kw_return, Keywords.kw_yield, 12730b57cec5SDimitry Andric // conditionals 12740b57cec5SDimitry Andric tok::kw_if, tok::kw_else, 12750b57cec5SDimitry Andric // loops 12760b57cec5SDimitry Andric tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break, 12770b57cec5SDimitry Andric // switch/case 12780b57cec5SDimitry Andric tok::kw_switch, tok::kw_case, 12790b57cec5SDimitry Andric // exceptions 12800b57cec5SDimitry Andric tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally, 12810b57cec5SDimitry Andric // declaration 12820b57cec5SDimitry Andric tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let, 12830b57cec5SDimitry Andric Keywords.kw_async, Keywords.kw_function, 12840b57cec5SDimitry Andric // import/export 12850b57cec5SDimitry Andric Keywords.kw_import, tok::kw_export); 12860b57cec5SDimitry Andric } 12870b57cec5SDimitry Andric 12888c6f6c0cSDimitry Andric // Checks whether a token is a type in K&R C (aka C78). 12898c6f6c0cSDimitry Andric static bool isC78Type(const FormatToken &Tok) { 12908c6f6c0cSDimitry Andric return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long, 12918c6f6c0cSDimitry Andric tok::kw_unsigned, tok::kw_float, tok::kw_double, 12928c6f6c0cSDimitry Andric tok::identifier); 12938c6f6c0cSDimitry Andric } 12948c6f6c0cSDimitry Andric 1295fe6060f1SDimitry Andric // This function checks whether a token starts the first parameter declaration 1296fe6060f1SDimitry Andric // in a K&R C (aka C78) function definition, e.g.: 1297fe6060f1SDimitry Andric // int f(a, b) 1298fe6060f1SDimitry Andric // short a, b; 1299fe6060f1SDimitry Andric // { 1300fe6060f1SDimitry Andric // return a + b; 1301fe6060f1SDimitry Andric // } 13028c6f6c0cSDimitry Andric static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next, 13038c6f6c0cSDimitry Andric const FormatToken *FuncName) { 13048c6f6c0cSDimitry Andric assert(Tok); 13058c6f6c0cSDimitry Andric assert(Next); 13068c6f6c0cSDimitry Andric assert(FuncName); 13078c6f6c0cSDimitry Andric 13088c6f6c0cSDimitry Andric if (FuncName->isNot(tok::identifier)) 1309fe6060f1SDimitry Andric return false; 1310fe6060f1SDimitry Andric 13118c6f6c0cSDimitry Andric const FormatToken *Prev = FuncName->Previous; 13128c6f6c0cSDimitry Andric if (!Prev || (Prev->isNot(tok::star) && !isC78Type(*Prev))) 13138c6f6c0cSDimitry Andric return false; 13148c6f6c0cSDimitry Andric 13158c6f6c0cSDimitry Andric if (!isC78Type(*Tok) && 131681ad6265SDimitry Andric !Tok->isOneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) { 13178c6f6c0cSDimitry Andric return false; 131881ad6265SDimitry Andric } 13198c6f6c0cSDimitry Andric 13208c6f6c0cSDimitry Andric if (Next->isNot(tok::star) && !Next->Tok.getIdentifierInfo()) 1321fe6060f1SDimitry Andric return false; 1322fe6060f1SDimitry Andric 1323fe6060f1SDimitry Andric Tok = Tok->Previous; 1324fe6060f1SDimitry Andric if (!Tok || Tok->isNot(tok::r_paren)) 1325fe6060f1SDimitry Andric return false; 1326fe6060f1SDimitry Andric 1327fe6060f1SDimitry Andric Tok = Tok->Previous; 1328fe6060f1SDimitry Andric if (!Tok || Tok->isNot(tok::identifier)) 1329fe6060f1SDimitry Andric return false; 1330fe6060f1SDimitry Andric 1331fe6060f1SDimitry Andric return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma); 1332fe6060f1SDimitry Andric } 1333fe6060f1SDimitry Andric 1334bdd1243dSDimitry Andric bool UnwrappedLineParser::parseModuleImport() { 1335bdd1243dSDimitry Andric assert(FormatTok->is(Keywords.kw_import) && "'import' expected"); 1336bdd1243dSDimitry Andric 1337bdd1243dSDimitry Andric if (auto Token = Tokens->peekNextToken(/*SkipComment=*/true); 1338bdd1243dSDimitry Andric !Token->Tok.getIdentifierInfo() && 1339bdd1243dSDimitry Andric !Token->isOneOf(tok::colon, tok::less, tok::string_literal)) { 1340bdd1243dSDimitry Andric return false; 1341bdd1243dSDimitry Andric } 1342bdd1243dSDimitry Andric 13434824e7fdSDimitry Andric nextToken(); 13444824e7fdSDimitry Andric while (!eof()) { 13454824e7fdSDimitry Andric if (FormatTok->is(tok::colon)) { 134681ad6265SDimitry Andric FormatTok->setFinalizedType(TT_ModulePartitionColon); 13474824e7fdSDimitry Andric } 13484824e7fdSDimitry Andric // Handle import <foo/bar.h> as we would an include statement. 13494824e7fdSDimitry Andric else if (FormatTok->is(tok::less)) { 13504824e7fdSDimitry Andric nextToken(); 13514824e7fdSDimitry Andric while (!FormatTok->isOneOf(tok::semi, tok::greater, tok::eof)) { 13524824e7fdSDimitry Andric // Mark tokens up to the trailing line comments as implicit string 13534824e7fdSDimitry Andric // literals. 13544824e7fdSDimitry Andric if (FormatTok->isNot(tok::comment) && 13555f757f3fSDimitry Andric !FormatTok->TokenText.starts_with("//")) { 135681ad6265SDimitry Andric FormatTok->setFinalizedType(TT_ImplicitStringLiteral); 135781ad6265SDimitry Andric } 13584824e7fdSDimitry Andric nextToken(); 13594824e7fdSDimitry Andric } 13604824e7fdSDimitry Andric } 13614824e7fdSDimitry Andric if (FormatTok->is(tok::semi)) { 13624824e7fdSDimitry Andric nextToken(); 13634824e7fdSDimitry Andric break; 13644824e7fdSDimitry Andric } 13654824e7fdSDimitry Andric nextToken(); 13664824e7fdSDimitry Andric } 13674824e7fdSDimitry Andric 13684824e7fdSDimitry Andric addUnwrappedLine(); 1369bdd1243dSDimitry Andric return true; 13704824e7fdSDimitry Andric } 13714824e7fdSDimitry Andric 13720b57cec5SDimitry Andric // readTokenWithJavaScriptASI reads the next token and terminates the current 13730b57cec5SDimitry Andric // line if JavaScript Automatic Semicolon Insertion must 13740b57cec5SDimitry Andric // happen between the current token and the next token. 13750b57cec5SDimitry Andric // 13760b57cec5SDimitry Andric // This method is conservative - it cannot cover all edge cases of JavaScript, 13770b57cec5SDimitry Andric // but only aims to correctly handle certain well known cases. It *must not* 13780b57cec5SDimitry Andric // return true in speculative cases. 13790b57cec5SDimitry Andric void UnwrappedLineParser::readTokenWithJavaScriptASI() { 13800b57cec5SDimitry Andric FormatToken *Previous = FormatTok; 13810b57cec5SDimitry Andric readToken(); 13820b57cec5SDimitry Andric FormatToken *Next = FormatTok; 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andric bool IsOnSameLine = 13850b57cec5SDimitry Andric CommentsBeforeNextToken.empty() 13860b57cec5SDimitry Andric ? Next->NewlinesBefore == 0 13870b57cec5SDimitry Andric : CommentsBeforeNextToken.front()->NewlinesBefore == 0; 13880b57cec5SDimitry Andric if (IsOnSameLine) 13890b57cec5SDimitry Andric return; 13900b57cec5SDimitry Andric 13910b57cec5SDimitry Andric bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous); 13920b57cec5SDimitry Andric bool PreviousStartsTemplateExpr = 13935f757f3fSDimitry Andric Previous->is(TT_TemplateString) && Previous->TokenText.ends_with("${"); 13940b57cec5SDimitry Andric if (PreviousMustBeValue || Previous->is(tok::r_paren)) { 13950b57cec5SDimitry Andric // If the line contains an '@' sign, the previous token might be an 13960b57cec5SDimitry Andric // annotation, which can precede another identifier/value. 1397349cc55cSDimitry Andric bool HasAt = llvm::any_of(Line->Tokens, [](UnwrappedLineNode &LineNode) { 13980b57cec5SDimitry Andric return LineNode.Tok->is(tok::at); 1399349cc55cSDimitry Andric }); 14000b57cec5SDimitry Andric if (HasAt) 14010b57cec5SDimitry Andric return; 14020b57cec5SDimitry Andric } 14030b57cec5SDimitry Andric if (Next->is(tok::exclaim) && PreviousMustBeValue) 14040b57cec5SDimitry Andric return addUnwrappedLine(); 14050b57cec5SDimitry Andric bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next); 14060b57cec5SDimitry Andric bool NextEndsTemplateExpr = 14075f757f3fSDimitry Andric Next->is(TT_TemplateString) && Next->TokenText.starts_with("}"); 14080b57cec5SDimitry Andric if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr && 14090b57cec5SDimitry Andric (PreviousMustBeValue || 14100b57cec5SDimitry Andric Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus, 141181ad6265SDimitry Andric tok::minusminus))) { 14120b57cec5SDimitry Andric return addUnwrappedLine(); 14130b57cec5SDimitry Andric } 141481ad6265SDimitry Andric if ((PreviousMustBeValue || Previous->is(tok::r_paren)) && 141581ad6265SDimitry Andric isJSDeclOrStmt(Keywords, Next)) { 141681ad6265SDimitry Andric return addUnwrappedLine(); 141781ad6265SDimitry Andric } 141881ad6265SDimitry Andric } 14190b57cec5SDimitry Andric 142081ad6265SDimitry Andric void UnwrappedLineParser::parseStructuralElement( 14215f757f3fSDimitry Andric const FormatToken *OpeningBrace, IfStmtKind *IfKind, 142281ad6265SDimitry Andric FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) { 14230b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TableGen && 14240b57cec5SDimitry Andric FormatTok->is(tok::pp_include)) { 14250b57cec5SDimitry Andric nextToken(); 14260b57cec5SDimitry Andric if (FormatTok->is(tok::string_literal)) 14270b57cec5SDimitry Andric nextToken(); 14280b57cec5SDimitry Andric addUnwrappedLine(); 14290b57cec5SDimitry Andric return; 14300b57cec5SDimitry Andric } 1431bdd1243dSDimitry Andric 14320fca6ea1SDimitry Andric if (IsCpp) { 14335f757f3fSDimitry Andric while (FormatTok->is(tok::l_square) && handleCppAttributes()) { 14345f757f3fSDimitry Andric } 14355f757f3fSDimitry Andric } else if (Style.isVerilog()) { 143606c3fb27SDimitry Andric if (Keywords.isVerilogStructuredProcedure(*FormatTok)) { 143706c3fb27SDimitry Andric parseForOrWhileLoop(/*HasParens=*/false); 143806c3fb27SDimitry Andric return; 143906c3fb27SDimitry Andric } 144006c3fb27SDimitry Andric if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) { 144106c3fb27SDimitry Andric parseForOrWhileLoop(); 144206c3fb27SDimitry Andric return; 144306c3fb27SDimitry Andric } 144406c3fb27SDimitry Andric if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert, 144506c3fb27SDimitry Andric Keywords.kw_assume, Keywords.kw_cover)) { 144606c3fb27SDimitry Andric parseIfThenElse(IfKind, /*KeepBraces=*/false, /*IsVerilogAssert=*/true); 144706c3fb27SDimitry Andric return; 144806c3fb27SDimitry Andric } 144906c3fb27SDimitry Andric 1450bdd1243dSDimitry Andric // Skip things that can exist before keywords like 'if' and 'case'. 1451bdd1243dSDimitry Andric while (true) { 1452bdd1243dSDimitry Andric if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique, 1453bdd1243dSDimitry Andric Keywords.kw_unique0)) { 1454bdd1243dSDimitry Andric nextToken(); 1455bdd1243dSDimitry Andric } else if (FormatTok->is(tok::l_paren) && 1456bdd1243dSDimitry Andric Tokens->peekNextToken()->is(tok::star)) { 1457bdd1243dSDimitry Andric parseParens(); 1458bdd1243dSDimitry Andric } else { 1459bdd1243dSDimitry Andric break; 1460bdd1243dSDimitry Andric } 1461bdd1243dSDimitry Andric } 1462bdd1243dSDimitry Andric } 1463bdd1243dSDimitry Andric 1464bdd1243dSDimitry Andric // Tokens that only make sense at the beginning of a line. 14650fca6ea1SDimitry Andric if (FormatTok->isAccessSpecifierKeyword()) { 14660fca6ea1SDimitry Andric if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || 14670fca6ea1SDimitry Andric Style.isCSharp()) { 14680fca6ea1SDimitry Andric nextToken(); 14690fca6ea1SDimitry Andric } else { 14700fca6ea1SDimitry Andric parseAccessSpecifier(); 14710fca6ea1SDimitry Andric } 14720fca6ea1SDimitry Andric return; 14730fca6ea1SDimitry Andric } 14740b57cec5SDimitry Andric switch (FormatTok->Tok.getKind()) { 14750b57cec5SDimitry Andric case tok::kw_asm: 14760b57cec5SDimitry Andric nextToken(); 14770b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 147881ad6265SDimitry Andric FormatTok->setFinalizedType(TT_InlineASMBrace); 14790b57cec5SDimitry Andric nextToken(); 1480bdd1243dSDimitry Andric while (FormatTok && !eof()) { 14810b57cec5SDimitry Andric if (FormatTok->is(tok::r_brace)) { 148281ad6265SDimitry Andric FormatTok->setFinalizedType(TT_InlineASMBrace); 14830b57cec5SDimitry Andric nextToken(); 14840b57cec5SDimitry Andric addUnwrappedLine(); 14850b57cec5SDimitry Andric break; 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric FormatTok->Finalized = true; 14880b57cec5SDimitry Andric nextToken(); 14890b57cec5SDimitry Andric } 14900b57cec5SDimitry Andric } 14910b57cec5SDimitry Andric break; 14920b57cec5SDimitry Andric case tok::kw_namespace: 14930b57cec5SDimitry Andric parseNamespace(); 14940b57cec5SDimitry Andric return; 149581ad6265SDimitry Andric case tok::kw_if: { 149681ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 14975ffd83dbSDimitry Andric // field/method declaration. 14985ffd83dbSDimitry Andric break; 149981ad6265SDimitry Andric } 150081ad6265SDimitry Andric FormatToken *Tok = parseIfThenElse(IfKind); 150181ad6265SDimitry Andric if (IfLeftBrace) 150281ad6265SDimitry Andric *IfLeftBrace = Tok; 15030b57cec5SDimitry Andric return; 150481ad6265SDimitry Andric } 15050b57cec5SDimitry Andric case tok::kw_for: 15060b57cec5SDimitry Andric case tok::kw_while: 150781ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 15085ffd83dbSDimitry Andric // field/method declaration. 15095ffd83dbSDimitry Andric break; 151081ad6265SDimitry Andric } 15110b57cec5SDimitry Andric parseForOrWhileLoop(); 15120b57cec5SDimitry Andric return; 15130b57cec5SDimitry Andric case tok::kw_do: 151481ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 15155ffd83dbSDimitry Andric // field/method declaration. 15165ffd83dbSDimitry Andric break; 151781ad6265SDimitry Andric } 15180b57cec5SDimitry Andric parseDoWhile(); 151981ad6265SDimitry Andric if (HasDoWhile) 152081ad6265SDimitry Andric *HasDoWhile = true; 15210b57cec5SDimitry Andric return; 15220b57cec5SDimitry Andric case tok::kw_switch: 152381ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 15240b57cec5SDimitry Andric // 'switch: string' field declaration. 15250b57cec5SDimitry Andric break; 152681ad6265SDimitry Andric } 15270fca6ea1SDimitry Andric parseSwitch(/*IsExpr=*/false); 15280b57cec5SDimitry Andric return; 15290fca6ea1SDimitry Andric case tok::kw_default: { 1530bdd1243dSDimitry Andric // In Verilog default along with other labels are handled in the next loop. 1531bdd1243dSDimitry Andric if (Style.isVerilog()) 1532bdd1243dSDimitry Andric break; 153381ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 15340b57cec5SDimitry Andric // 'default: string' field declaration. 15350b57cec5SDimitry Andric break; 153681ad6265SDimitry Andric } 15370fca6ea1SDimitry Andric auto *Default = FormatTok; 15380b57cec5SDimitry Andric nextToken(); 15390b57cec5SDimitry Andric if (FormatTok->is(tok::colon)) { 154006c3fb27SDimitry Andric FormatTok->setFinalizedType(TT_CaseLabelColon); 15410b57cec5SDimitry Andric parseLabel(); 15420b57cec5SDimitry Andric return; 15430b57cec5SDimitry Andric } 15440fca6ea1SDimitry Andric if (FormatTok->is(tok::arrow)) { 15450fca6ea1SDimitry Andric FormatTok->setFinalizedType(TT_CaseLabelArrow); 15460fca6ea1SDimitry Andric Default->setFinalizedType(TT_SwitchExpressionLabel); 15470fca6ea1SDimitry Andric parseLabel(); 15480fca6ea1SDimitry Andric return; 15490fca6ea1SDimitry Andric } 15500b57cec5SDimitry Andric // e.g. "default void f() {}" in a Java interface. 15510b57cec5SDimitry Andric break; 15520fca6ea1SDimitry Andric } 15530b57cec5SDimitry Andric case tok::kw_case: 1554bdd1243dSDimitry Andric // Proto: there are no switch/case statements. 15555f757f3fSDimitry Andric if (Style.Language == FormatStyle::LK_Proto) { 1556bdd1243dSDimitry Andric nextToken(); 1557bdd1243dSDimitry Andric return; 1558bdd1243dSDimitry Andric } 1559bdd1243dSDimitry Andric if (Style.isVerilog()) { 1560bdd1243dSDimitry Andric parseBlock(); 1561bdd1243dSDimitry Andric addUnwrappedLine(); 1562bdd1243dSDimitry Andric return; 1563bdd1243dSDimitry Andric } 156481ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 15650b57cec5SDimitry Andric // 'case: string' field declaration. 156681ad6265SDimitry Andric nextToken(); 15670b57cec5SDimitry Andric break; 156881ad6265SDimitry Andric } 15690b57cec5SDimitry Andric parseCaseLabel(); 15700b57cec5SDimitry Andric return; 15710b57cec5SDimitry Andric case tok::kw_try: 15720b57cec5SDimitry Andric case tok::kw___try: 157381ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 15745ffd83dbSDimitry Andric // field/method declaration. 15755ffd83dbSDimitry Andric break; 157681ad6265SDimitry Andric } 15770b57cec5SDimitry Andric parseTryCatch(); 15780b57cec5SDimitry Andric return; 15790b57cec5SDimitry Andric case tok::kw_extern: 15800b57cec5SDimitry Andric nextToken(); 1581bdd1243dSDimitry Andric if (Style.isVerilog()) { 1582bdd1243dSDimitry Andric // In Verilog and extern module declaration looks like a start of module. 1583bdd1243dSDimitry Andric // But there is no body and endmodule. So we handle it separately. 1584bdd1243dSDimitry Andric if (Keywords.isVerilogHierarchy(*FormatTok)) { 1585bdd1243dSDimitry Andric parseVerilogHierarchyHeader(); 1586bdd1243dSDimitry Andric return; 1587bdd1243dSDimitry Andric } 1588bdd1243dSDimitry Andric } else if (FormatTok->is(tok::string_literal)) { 15890b57cec5SDimitry Andric nextToken(); 159081ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 15910eae32dcSDimitry Andric if (Style.BraceWrapping.AfterExternBlock) 15920b57cec5SDimitry Andric addUnwrappedLine(); 15930eae32dcSDimitry Andric // Either we indent or for backwards compatibility we follow the 15940eae32dcSDimitry Andric // AfterExternBlock style. 1595fe6060f1SDimitry Andric unsigned AddLevels = 15960eae32dcSDimitry Andric (Style.IndentExternBlock == FormatStyle::IEBS_Indent) || 15970eae32dcSDimitry Andric (Style.BraceWrapping.AfterExternBlock && 15980eae32dcSDimitry Andric Style.IndentExternBlock == 15990eae32dcSDimitry Andric FormatStyle::IEBS_AfterExternBlock) 16000eae32dcSDimitry Andric ? 1u 16010eae32dcSDimitry Andric : 0u; 1602fe6060f1SDimitry Andric parseBlock(/*MustBeDeclaration=*/true, AddLevels); 16030b57cec5SDimitry Andric addUnwrappedLine(); 16040b57cec5SDimitry Andric return; 16050b57cec5SDimitry Andric } 16060b57cec5SDimitry Andric } 16070b57cec5SDimitry Andric break; 16080b57cec5SDimitry Andric case tok::kw_export: 16090eae32dcSDimitry Andric if (Style.isJavaScript()) { 16100b57cec5SDimitry Andric parseJavaScriptEs6ImportExport(); 16110b57cec5SDimitry Andric return; 16120b57cec5SDimitry Andric } 16130fca6ea1SDimitry Andric if (IsCpp) { 1614bdd1243dSDimitry Andric nextToken(); 1615bdd1243dSDimitry Andric if (FormatTok->is(tok::kw_namespace)) { 1616bdd1243dSDimitry Andric parseNamespace(); 1617bdd1243dSDimitry Andric return; 1618bdd1243dSDimitry Andric } 1619bdd1243dSDimitry Andric if (FormatTok->is(Keywords.kw_import) && parseModuleImport()) 1620bdd1243dSDimitry Andric return; 1621bdd1243dSDimitry Andric } 16220b57cec5SDimitry Andric break; 16230b57cec5SDimitry Andric case tok::kw_inline: 16240b57cec5SDimitry Andric nextToken(); 162581ad6265SDimitry Andric if (FormatTok->is(tok::kw_namespace)) { 16260b57cec5SDimitry Andric parseNamespace(); 16270b57cec5SDimitry Andric return; 16280b57cec5SDimitry Andric } 16290b57cec5SDimitry Andric break; 16300b57cec5SDimitry Andric case tok::identifier: 16310b57cec5SDimitry Andric if (FormatTok->is(TT_ForEachMacro)) { 16320b57cec5SDimitry Andric parseForOrWhileLoop(); 16330b57cec5SDimitry Andric return; 16340b57cec5SDimitry Andric } 16350b57cec5SDimitry Andric if (FormatTok->is(TT_MacroBlockBegin)) { 1636fe6060f1SDimitry Andric parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, 16370b57cec5SDimitry Andric /*MunchSemi=*/false); 16380b57cec5SDimitry Andric return; 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric if (FormatTok->is(Keywords.kw_import)) { 16410eae32dcSDimitry Andric if (Style.isJavaScript()) { 16420b57cec5SDimitry Andric parseJavaScriptEs6ImportExport(); 16430b57cec5SDimitry Andric return; 16440b57cec5SDimitry Andric } 16450b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Proto) { 16460b57cec5SDimitry Andric nextToken(); 16470b57cec5SDimitry Andric if (FormatTok->is(tok::kw_public)) 16480b57cec5SDimitry Andric nextToken(); 16495f757f3fSDimitry Andric if (FormatTok->isNot(tok::string_literal)) 16500b57cec5SDimitry Andric return; 16510b57cec5SDimitry Andric nextToken(); 16520b57cec5SDimitry Andric if (FormatTok->is(tok::semi)) 16530b57cec5SDimitry Andric nextToken(); 16540b57cec5SDimitry Andric addUnwrappedLine(); 16550b57cec5SDimitry Andric return; 16560b57cec5SDimitry Andric } 16570fca6ea1SDimitry Andric if (IsCpp && parseModuleImport()) 16584824e7fdSDimitry Andric return; 16594824e7fdSDimitry Andric } 16600fca6ea1SDimitry Andric if (IsCpp && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals, 16610b57cec5SDimitry Andric Keywords.kw_slots, Keywords.kw_qslots)) { 16620b57cec5SDimitry Andric nextToken(); 16630b57cec5SDimitry Andric if (FormatTok->is(tok::colon)) { 16640b57cec5SDimitry Andric nextToken(); 16650b57cec5SDimitry Andric addUnwrappedLine(); 16660b57cec5SDimitry Andric return; 16670b57cec5SDimitry Andric } 16680b57cec5SDimitry Andric } 16690fca6ea1SDimitry Andric if (IsCpp && FormatTok->is(TT_StatementMacro)) { 16700b57cec5SDimitry Andric parseStatementMacro(); 16710b57cec5SDimitry Andric return; 16720b57cec5SDimitry Andric } 16730fca6ea1SDimitry Andric if (IsCpp && FormatTok->is(TT_NamespaceMacro)) { 16740b57cec5SDimitry Andric parseNamespace(); 16750b57cec5SDimitry Andric return; 16760b57cec5SDimitry Andric } 16775f757f3fSDimitry Andric // In Verilog labels can be any expression, so we don't do them here. 1678cb14a3feSDimitry Andric // JS doesn't have macros, and within classes colons indicate fields, not 1679cb14a3feSDimitry Andric // labels. 16807a6dacacSDimitry Andric // TableGen doesn't have labels. 16817a6dacacSDimitry Andric if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() && 1682cb14a3feSDimitry Andric Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) { 16835f757f3fSDimitry Andric nextToken(); 16840fca6ea1SDimitry Andric if (!Line->InMacroBody || CurrentLines->size() > 1) 16855f757f3fSDimitry Andric Line->Tokens.begin()->Tok->MustBreakBefore = true; 16865f757f3fSDimitry Andric FormatTok->setFinalizedType(TT_GotoLabelColon); 16875f757f3fSDimitry Andric parseLabel(!Style.IndentGotoLabels); 16885f757f3fSDimitry Andric if (HasLabel) 16895f757f3fSDimitry Andric *HasLabel = true; 16905f757f3fSDimitry Andric return; 16915f757f3fSDimitry Andric } 16920b57cec5SDimitry Andric // In all other cases, parse the declaration. 16930b57cec5SDimitry Andric break; 16940b57cec5SDimitry Andric default: 16950b57cec5SDimitry Andric break; 16960b57cec5SDimitry Andric } 16975f757f3fSDimitry Andric 16980fca6ea1SDimitry Andric for (const bool InRequiresExpression = 16995f757f3fSDimitry Andric OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); 17000fca6ea1SDimitry Andric !eof();) { 17010fca6ea1SDimitry Andric if (IsCpp && FormatTok->isCppAlternativeOperatorKeyword()) { 17020fca6ea1SDimitry Andric if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true); 17030fca6ea1SDimitry Andric Next && Next->isBinaryOperator()) { 17040fca6ea1SDimitry Andric FormatTok->Tok.setKind(tok::identifier); 17050fca6ea1SDimitry Andric } 17060fca6ea1SDimitry Andric } 17070b57cec5SDimitry Andric const FormatToken *Previous = FormatTok->Previous; 17080b57cec5SDimitry Andric switch (FormatTok->Tok.getKind()) { 17090b57cec5SDimitry Andric case tok::at: 17100b57cec5SDimitry Andric nextToken(); 171181ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 17120b57cec5SDimitry Andric nextToken(); 17130b57cec5SDimitry Andric parseBracedList(); 17140b57cec5SDimitry Andric break; 17150b57cec5SDimitry Andric } else if (Style.Language == FormatStyle::LK_Java && 17160b57cec5SDimitry Andric FormatTok->is(Keywords.kw_interface)) { 17170b57cec5SDimitry Andric nextToken(); 17180b57cec5SDimitry Andric break; 17190b57cec5SDimitry Andric } 17200b57cec5SDimitry Andric switch (FormatTok->Tok.getObjCKeywordID()) { 17210b57cec5SDimitry Andric case tok::objc_public: 17220b57cec5SDimitry Andric case tok::objc_protected: 17230b57cec5SDimitry Andric case tok::objc_package: 17240b57cec5SDimitry Andric case tok::objc_private: 17250b57cec5SDimitry Andric return parseAccessSpecifier(); 17260b57cec5SDimitry Andric case tok::objc_interface: 17270b57cec5SDimitry Andric case tok::objc_implementation: 17280b57cec5SDimitry Andric return parseObjCInterfaceOrImplementation(); 17290b57cec5SDimitry Andric case tok::objc_protocol: 17300b57cec5SDimitry Andric if (parseObjCProtocol()) 17310b57cec5SDimitry Andric return; 17320b57cec5SDimitry Andric break; 17330b57cec5SDimitry Andric case tok::objc_end: 17340b57cec5SDimitry Andric return; // Handled by the caller. 17350b57cec5SDimitry Andric case tok::objc_optional: 17360b57cec5SDimitry Andric case tok::objc_required: 17370b57cec5SDimitry Andric nextToken(); 17380b57cec5SDimitry Andric addUnwrappedLine(); 17390b57cec5SDimitry Andric return; 17400b57cec5SDimitry Andric case tok::objc_autoreleasepool: 17410b57cec5SDimitry Andric nextToken(); 174281ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 1743a7dea167SDimitry Andric if (Style.BraceWrapping.AfterControlStatement == 174481ad6265SDimitry Andric FormatStyle::BWACS_Always) { 17450b57cec5SDimitry Andric addUnwrappedLine(); 174681ad6265SDimitry Andric } 1747349cc55cSDimitry Andric parseBlock(); 17480b57cec5SDimitry Andric } 17490b57cec5SDimitry Andric addUnwrappedLine(); 17500b57cec5SDimitry Andric return; 17510b57cec5SDimitry Andric case tok::objc_synchronized: 17520b57cec5SDimitry Andric nextToken(); 175381ad6265SDimitry Andric if (FormatTok->is(tok::l_paren)) { 17540b57cec5SDimitry Andric // Skip synchronization object 17550b57cec5SDimitry Andric parseParens(); 175681ad6265SDimitry Andric } 175781ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 1758a7dea167SDimitry Andric if (Style.BraceWrapping.AfterControlStatement == 175981ad6265SDimitry Andric FormatStyle::BWACS_Always) { 17600b57cec5SDimitry Andric addUnwrappedLine(); 176181ad6265SDimitry Andric } 1762349cc55cSDimitry Andric parseBlock(); 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric addUnwrappedLine(); 17650b57cec5SDimitry Andric return; 17660b57cec5SDimitry Andric case tok::objc_try: 17670b57cec5SDimitry Andric // This branch isn't strictly necessary (the kw_try case below would 17680b57cec5SDimitry Andric // do this too after the tok::at is parsed above). But be explicit. 17690b57cec5SDimitry Andric parseTryCatch(); 17700b57cec5SDimitry Andric return; 17710b57cec5SDimitry Andric default: 17720b57cec5SDimitry Andric break; 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric break; 177581ad6265SDimitry Andric case tok::kw_requires: { 17760fca6ea1SDimitry Andric if (IsCpp) { 177781ad6265SDimitry Andric bool ParsedClause = parseRequires(); 177881ad6265SDimitry Andric if (ParsedClause) 17790eae32dcSDimitry Andric return; 178081ad6265SDimitry Andric } else { 178181ad6265SDimitry Andric nextToken(); 178281ad6265SDimitry Andric } 178381ad6265SDimitry Andric break; 178481ad6265SDimitry Andric } 17850b57cec5SDimitry Andric case tok::kw_enum: 17860fca6ea1SDimitry Andric // Ignore if this is part of "template <enum ..." or "... -> enum" or 17870fca6ea1SDimitry Andric // "template <..., enum ...>". 17880fca6ea1SDimitry Andric if (Previous && Previous->isOneOf(tok::less, tok::arrow, tok::comma)) { 17890b57cec5SDimitry Andric nextToken(); 17900b57cec5SDimitry Andric break; 17910b57cec5SDimitry Andric } 17920b57cec5SDimitry Andric 17930b57cec5SDimitry Andric // parseEnum falls through and does not yet add an unwrapped line as an 17940b57cec5SDimitry Andric // enum definition can start a structural element. 17950b57cec5SDimitry Andric if (!parseEnum()) 17960b57cec5SDimitry Andric break; 179706c3fb27SDimitry Andric // This only applies to C++ and Verilog. 17980fca6ea1SDimitry Andric if (!IsCpp && !Style.isVerilog()) { 17990b57cec5SDimitry Andric addUnwrappedLine(); 18000b57cec5SDimitry Andric return; 18010b57cec5SDimitry Andric } 18020b57cec5SDimitry Andric break; 18030b57cec5SDimitry Andric case tok::kw_typedef: 18040b57cec5SDimitry Andric nextToken(); 18050b57cec5SDimitry Andric if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS, 1806a7dea167SDimitry Andric Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS, 1807a7dea167SDimitry Andric Keywords.kw_CF_CLOSED_ENUM, 180881ad6265SDimitry Andric Keywords.kw_NS_CLOSED_ENUM)) { 18090b57cec5SDimitry Andric parseEnum(); 181081ad6265SDimitry Andric } 18110b57cec5SDimitry Andric break; 1812bdd1243dSDimitry Andric case tok::kw_class: 1813bdd1243dSDimitry Andric if (Style.isVerilog()) { 1814bdd1243dSDimitry Andric parseBlock(); 1815bdd1243dSDimitry Andric addUnwrappedLine(); 1816bdd1243dSDimitry Andric return; 1817bdd1243dSDimitry Andric } 18187a6dacacSDimitry Andric if (Style.isTableGen()) { 18197a6dacacSDimitry Andric // Do nothing special. In this case the l_brace becomes FunctionLBrace. 18207a6dacacSDimitry Andric // This is same as def and so on. 18217a6dacacSDimitry Andric nextToken(); 18227a6dacacSDimitry Andric break; 18237a6dacacSDimitry Andric } 1824bdd1243dSDimitry Andric [[fallthrough]]; 18250b57cec5SDimitry Andric case tok::kw_struct: 18260b57cec5SDimitry Andric case tok::kw_union: 182781ad6265SDimitry Andric if (parseStructLike()) 18280b57cec5SDimitry Andric return; 18290b57cec5SDimitry Andric break; 1830bdb86d1aSDimitry Andric case tok::kw_decltype: 1831bdb86d1aSDimitry Andric nextToken(); 1832bdb86d1aSDimitry Andric if (FormatTok->is(tok::l_paren)) { 1833bdb86d1aSDimitry Andric parseParens(); 1834bdb86d1aSDimitry Andric assert(FormatTok->Previous); 1835bdb86d1aSDimitry Andric if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto, 1836bdb86d1aSDimitry Andric tok::l_paren)) { 1837bdb86d1aSDimitry Andric Line->SeenDecltypeAuto = true; 1838bdb86d1aSDimitry Andric } 1839bdb86d1aSDimitry Andric } 1840bdb86d1aSDimitry Andric break; 18410b57cec5SDimitry Andric case tok::period: 18420b57cec5SDimitry Andric nextToken(); 18430b57cec5SDimitry Andric // In Java, classes have an implicit static member "class". 18440b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Java && FormatTok && 184581ad6265SDimitry Andric FormatTok->is(tok::kw_class)) { 18460b57cec5SDimitry Andric nextToken(); 184781ad6265SDimitry Andric } 18480eae32dcSDimitry Andric if (Style.isJavaScript() && FormatTok && 184981ad6265SDimitry Andric FormatTok->Tok.getIdentifierInfo()) { 18500b57cec5SDimitry Andric // JavaScript only has pseudo keywords, all keywords are allowed to 18510b57cec5SDimitry Andric // appear in "IdentifierName" positions. See http://es5.github.io/#x7.6 18520b57cec5SDimitry Andric nextToken(); 185381ad6265SDimitry Andric } 18540b57cec5SDimitry Andric break; 18550b57cec5SDimitry Andric case tok::semi: 18560b57cec5SDimitry Andric nextToken(); 18570b57cec5SDimitry Andric addUnwrappedLine(); 18580b57cec5SDimitry Andric return; 18590b57cec5SDimitry Andric case tok::r_brace: 18600b57cec5SDimitry Andric addUnwrappedLine(); 18610b57cec5SDimitry Andric return; 18628c6f6c0cSDimitry Andric case tok::l_paren: { 18630b57cec5SDimitry Andric parseParens(); 1864fe6060f1SDimitry Andric // Break the unwrapped line if a K&R C function definition has a parameter 1865fe6060f1SDimitry Andric // declaration. 18660fca6ea1SDimitry Andric if (OpeningBrace || !IsCpp || !Previous || eof()) 1867fe6060f1SDimitry Andric break; 1868bdd1243dSDimitry Andric if (isC78ParameterDecl(FormatTok, 1869bdd1243dSDimitry Andric Tokens->peekNextToken(/*SkipComment=*/true), 1870bdd1243dSDimitry Andric Previous)) { 1871fe6060f1SDimitry Andric addUnwrappedLine(); 1872fe6060f1SDimitry Andric return; 1873fe6060f1SDimitry Andric } 18740b57cec5SDimitry Andric break; 18758c6f6c0cSDimitry Andric } 18760b57cec5SDimitry Andric case tok::kw_operator: 18770b57cec5SDimitry Andric nextToken(); 18780b57cec5SDimitry Andric if (FormatTok->isBinaryOperator()) 18790b57cec5SDimitry Andric nextToken(); 18800b57cec5SDimitry Andric break; 18810b57cec5SDimitry Andric case tok::caret: 18820b57cec5SDimitry Andric nextToken(); 188306c3fb27SDimitry Andric // Block return type. 18840fca6ea1SDimitry Andric if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) { 18850b57cec5SDimitry Andric nextToken(); 188606c3fb27SDimitry Andric // Return types: pointers are ok too. 188706c3fb27SDimitry Andric while (FormatTok->is(tok::star)) 188806c3fb27SDimitry Andric nextToken(); 188981ad6265SDimitry Andric } 189006c3fb27SDimitry Andric // Block argument list. 18910b57cec5SDimitry Andric if (FormatTok->is(tok::l_paren)) 18920b57cec5SDimitry Andric parseParens(); 189306c3fb27SDimitry Andric // Block body. 18940b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) 18950b57cec5SDimitry Andric parseChildBlock(); 18960b57cec5SDimitry Andric break; 18970b57cec5SDimitry Andric case tok::l_brace: 18985f757f3fSDimitry Andric if (InRequiresExpression) 18995f757f3fSDimitry Andric FormatTok->setFinalizedType(TT_BracedListLBrace); 19005ffd83dbSDimitry Andric if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) { 1901bdb86d1aSDimitry Andric IsDecltypeAutoFunction = Line->SeenDecltypeAuto; 19020b57cec5SDimitry Andric // A block outside of parentheses must be the last part of a 19030b57cec5SDimitry Andric // structural element. 19040b57cec5SDimitry Andric // FIXME: Figure out cases where this is not true, and add projections 19050b57cec5SDimitry Andric // for them (the one we know is missing are lambdas). 190604eeddc0SDimitry Andric if (Style.Language == FormatStyle::LK_Java && 190704eeddc0SDimitry Andric Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) { 190804eeddc0SDimitry Andric // If necessary, we could set the type to something different than 190904eeddc0SDimitry Andric // TT_FunctionLBrace. 191004eeddc0SDimitry Andric if (Style.BraceWrapping.AfterControlStatement == 191181ad6265SDimitry Andric FormatStyle::BWACS_Always) { 19120b57cec5SDimitry Andric addUnwrappedLine(); 191381ad6265SDimitry Andric } 191404eeddc0SDimitry Andric } else if (Style.BraceWrapping.AfterFunction) { 191504eeddc0SDimitry Andric addUnwrappedLine(); 191604eeddc0SDimitry Andric } 19170fca6ea1SDimitry Andric if (!Previous || Previous->isNot(TT_TypeDeclarationParen)) 191881ad6265SDimitry Andric FormatTok->setFinalizedType(TT_FunctionLBrace); 1919349cc55cSDimitry Andric parseBlock(); 1920bdb86d1aSDimitry Andric IsDecltypeAutoFunction = false; 19210b57cec5SDimitry Andric addUnwrappedLine(); 19220b57cec5SDimitry Andric return; 19230b57cec5SDimitry Andric } 19240b57cec5SDimitry Andric // Otherwise this was a braced init list, and the structural 19250b57cec5SDimitry Andric // element continues. 19260b57cec5SDimitry Andric break; 19270b57cec5SDimitry Andric case tok::kw_try: 19280eae32dcSDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 19295ffd83dbSDimitry Andric // field/method declaration. 19305ffd83dbSDimitry Andric nextToken(); 19315ffd83dbSDimitry Andric break; 19325ffd83dbSDimitry Andric } 19330b57cec5SDimitry Andric // We arrive here when parsing function-try blocks. 19340b57cec5SDimitry Andric if (Style.BraceWrapping.AfterFunction) 19350b57cec5SDimitry Andric addUnwrappedLine(); 19360b57cec5SDimitry Andric parseTryCatch(); 19370b57cec5SDimitry Andric return; 19380b57cec5SDimitry Andric case tok::identifier: { 19395ffd83dbSDimitry Andric if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) && 19405ffd83dbSDimitry Andric Line->MustBeDeclaration) { 19415ffd83dbSDimitry Andric addUnwrappedLine(); 19425ffd83dbSDimitry Andric parseCSharpGenericTypeConstraint(); 19435ffd83dbSDimitry Andric break; 19445ffd83dbSDimitry Andric } 19450b57cec5SDimitry Andric if (FormatTok->is(TT_MacroBlockEnd)) { 19460b57cec5SDimitry Andric addUnwrappedLine(); 19470b57cec5SDimitry Andric return; 19480b57cec5SDimitry Andric } 19490b57cec5SDimitry Andric 19500b57cec5SDimitry Andric // Function declarations (as opposed to function expressions) are parsed 19510b57cec5SDimitry Andric // on their own unwrapped line by continuing this loop. Function 19520b57cec5SDimitry Andric // expressions (functions that are not on their own line) must not create 19530b57cec5SDimitry Andric // a new unwrapped line, so they are special cased below. 19540b57cec5SDimitry Andric size_t TokenCount = Line->Tokens.size(); 19550eae32dcSDimitry Andric if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) && 19565f757f3fSDimitry Andric (TokenCount > 1 || 19575f757f3fSDimitry Andric (TokenCount == 1 && 19585f757f3fSDimitry Andric Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) { 19590b57cec5SDimitry Andric tryToParseJSFunction(); 19600b57cec5SDimitry Andric break; 19610b57cec5SDimitry Andric } 19620eae32dcSDimitry Andric if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) && 19630b57cec5SDimitry Andric FormatTok->is(Keywords.kw_interface)) { 19640eae32dcSDimitry Andric if (Style.isJavaScript()) { 19650b57cec5SDimitry Andric // In JavaScript/TypeScript, "interface" can be used as a standalone 19660b57cec5SDimitry Andric // identifier, e.g. in `var interface = 1;`. If "interface" is 19670b57cec5SDimitry Andric // followed by another identifier, it is very like to be an actual 19680b57cec5SDimitry Andric // interface declaration. 19690b57cec5SDimitry Andric unsigned StoredPosition = Tokens->getPosition(); 19700b57cec5SDimitry Andric FormatToken *Next = Tokens->getNextToken(); 19710b57cec5SDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 19724824e7fdSDimitry Andric if (!mustBeJSIdent(Keywords, Next)) { 19730b57cec5SDimitry Andric nextToken(); 19740b57cec5SDimitry Andric break; 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric parseRecord(); 19780b57cec5SDimitry Andric addUnwrappedLine(); 19790b57cec5SDimitry Andric return; 19800b57cec5SDimitry Andric } 19810b57cec5SDimitry Andric 1982bdd1243dSDimitry Andric if (Style.isVerilog()) { 1983bdd1243dSDimitry Andric if (FormatTok->is(Keywords.kw_table)) { 1984bdd1243dSDimitry Andric parseVerilogTable(); 1985bdd1243dSDimitry Andric return; 1986bdd1243dSDimitry Andric } 1987bdd1243dSDimitry Andric if (Keywords.isVerilogBegin(*FormatTok) || 1988bdd1243dSDimitry Andric Keywords.isVerilogHierarchy(*FormatTok)) { 1989bdd1243dSDimitry Andric parseBlock(); 1990bdd1243dSDimitry Andric addUnwrappedLine(); 1991bdd1243dSDimitry Andric return; 1992bdd1243dSDimitry Andric } 1993bdd1243dSDimitry Andric } 1994bdd1243dSDimitry Andric 19950fca6ea1SDimitry Andric if (!IsCpp && FormatTok->is(Keywords.kw_interface)) { 199681ad6265SDimitry Andric if (parseStructLike()) 1997fe6060f1SDimitry Andric return; 1998fe6060f1SDimitry Andric break; 1999fe6060f1SDimitry Andric } 2000fe6060f1SDimitry Andric 20010fca6ea1SDimitry Andric if (IsCpp && FormatTok->is(TT_StatementMacro)) { 20020b57cec5SDimitry Andric parseStatementMacro(); 20030b57cec5SDimitry Andric return; 20040b57cec5SDimitry Andric } 20050b57cec5SDimitry Andric 20060b57cec5SDimitry Andric // See if the following token should start a new unwrapped line. 20070b57cec5SDimitry Andric StringRef Text = FormatTok->TokenText; 200804eeddc0SDimitry Andric 200904eeddc0SDimitry Andric FormatToken *PreviousToken = FormatTok; 20100b57cec5SDimitry Andric nextToken(); 20110b57cec5SDimitry Andric 20120b57cec5SDimitry Andric // JS doesn't have macros, and within classes colons indicate fields, not 20130b57cec5SDimitry Andric // labels. 20140eae32dcSDimitry Andric if (Style.isJavaScript()) 20150b57cec5SDimitry Andric break; 20160b57cec5SDimitry Andric 201781ad6265SDimitry Andric auto OneTokenSoFar = [&]() { 2018753f127fSDimitry Andric auto I = Line->Tokens.begin(), E = Line->Tokens.end(); 2019753f127fSDimitry Andric while (I != E && I->Tok->is(tok::comment)) 2020753f127fSDimitry Andric ++I; 20215f757f3fSDimitry Andric if (Style.isVerilog()) 20225f757f3fSDimitry Andric while (I != E && I->Tok->is(tok::hash)) 2023753f127fSDimitry Andric ++I; 2024753f127fSDimitry Andric return I != E && (++I == E); 202581ad6265SDimitry Andric }; 202681ad6265SDimitry Andric if (OneTokenSoFar()) { 20270b57cec5SDimitry Andric // Recognize function-like macro usages without trailing semicolon as 20280b57cec5SDimitry Andric // well as free-standing macros like Q_OBJECT. 20290b57cec5SDimitry Andric bool FunctionLike = FormatTok->is(tok::l_paren); 20300b57cec5SDimitry Andric if (FunctionLike) 20310b57cec5SDimitry Andric parseParens(); 20320b57cec5SDimitry Andric 20330b57cec5SDimitry Andric bool FollowedByNewline = 20340b57cec5SDimitry Andric CommentsBeforeNextToken.empty() 20350b57cec5SDimitry Andric ? FormatTok->NewlinesBefore > 0 20360b57cec5SDimitry Andric : CommentsBeforeNextToken.front()->NewlinesBefore > 0; 20370b57cec5SDimitry Andric 20380b57cec5SDimitry Andric if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) && 20395ffd83dbSDimitry Andric tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) { 2040bdd1243dSDimitry Andric if (PreviousToken->isNot(TT_UntouchableMacroFunc)) 204181ad6265SDimitry Andric PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro); 20420b57cec5SDimitry Andric addUnwrappedLine(); 20430b57cec5SDimitry Andric return; 20440b57cec5SDimitry Andric } 20450b57cec5SDimitry Andric } 20460b57cec5SDimitry Andric break; 20470b57cec5SDimitry Andric } 20480b57cec5SDimitry Andric case tok::equal: 20490eae32dcSDimitry Andric if ((Style.isJavaScript() || Style.isCSharp()) && 20500eae32dcSDimitry Andric FormatTok->is(TT_FatArrow)) { 20510eae32dcSDimitry Andric tryToParseChildBlock(); 20520b57cec5SDimitry Andric break; 20530b57cec5SDimitry Andric } 20540b57cec5SDimitry Andric 20550b57cec5SDimitry Andric nextToken(); 205681ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 20575ffd83dbSDimitry Andric // Block kind should probably be set to BK_BracedInit for any language. 20585ffd83dbSDimitry Andric // C# needs this change to ensure that array initialisers and object 20595ffd83dbSDimitry Andric // initialisers are indented the same way. 20605ffd83dbSDimitry Andric if (Style.isCSharp()) 2061e8d8bef9SDimitry Andric FormatTok->setBlockKind(BK_BracedInit); 20627a6dacacSDimitry Andric // TableGen's defset statement has syntax of the form, 20637a6dacacSDimitry Andric // `defset <type> <name> = { <statement>... }` 20647a6dacacSDimitry Andric if (Style.isTableGen() && 20657a6dacacSDimitry Andric Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) { 20667a6dacacSDimitry Andric FormatTok->setFinalizedType(TT_FunctionLBrace); 20677a6dacacSDimitry Andric parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, 20687a6dacacSDimitry Andric /*MunchSemi=*/false); 20697a6dacacSDimitry Andric addUnwrappedLine(); 20707a6dacacSDimitry Andric break; 20717a6dacacSDimitry Andric } 20720b57cec5SDimitry Andric nextToken(); 20730b57cec5SDimitry Andric parseBracedList(); 20740b57cec5SDimitry Andric } else if (Style.Language == FormatStyle::LK_Proto && 207581ad6265SDimitry Andric FormatTok->is(tok::less)) { 20760b57cec5SDimitry Andric nextToken(); 20775f757f3fSDimitry Andric parseBracedList(/*IsAngleBracket=*/true); 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric break; 20800b57cec5SDimitry Andric case tok::l_square: 20810b57cec5SDimitry Andric parseSquare(); 20820b57cec5SDimitry Andric break; 20830b57cec5SDimitry Andric case tok::kw_new: 20840b57cec5SDimitry Andric parseNew(); 20850b57cec5SDimitry Andric break; 20860fca6ea1SDimitry Andric case tok::kw_switch: 20870fca6ea1SDimitry Andric if (Style.Language == FormatStyle::LK_Java) 20880fca6ea1SDimitry Andric parseSwitch(/*IsExpr=*/true); 2089415efcecSDimitry Andric else 20900fca6ea1SDimitry Andric nextToken(); 20910fca6ea1SDimitry Andric break; 209281ad6265SDimitry Andric case tok::kw_case: 2093bdd1243dSDimitry Andric // Proto: there are no switch/case statements. 20945f757f3fSDimitry Andric if (Style.Language == FormatStyle::LK_Proto) { 2095bdd1243dSDimitry Andric nextToken(); 2096bdd1243dSDimitry Andric return; 2097bdd1243dSDimitry Andric } 2098bdd1243dSDimitry Andric // In Verilog switch is called case. 2099bdd1243dSDimitry Andric if (Style.isVerilog()) { 2100bdd1243dSDimitry Andric parseBlock(); 2101bdd1243dSDimitry Andric addUnwrappedLine(); 2102bdd1243dSDimitry Andric return; 2103bdd1243dSDimitry Andric } 210481ad6265SDimitry Andric if (Style.isJavaScript() && Line->MustBeDeclaration) { 210581ad6265SDimitry Andric // 'case: string' field declaration. 210681ad6265SDimitry Andric nextToken(); 210781ad6265SDimitry Andric break; 210881ad6265SDimitry Andric } 210981ad6265SDimitry Andric parseCaseLabel(); 211081ad6265SDimitry Andric break; 2111bdd1243dSDimitry Andric case tok::kw_default: 2112bdd1243dSDimitry Andric nextToken(); 2113bdd1243dSDimitry Andric if (Style.isVerilog()) { 2114bdd1243dSDimitry Andric if (FormatTok->is(tok::colon)) { 2115bdd1243dSDimitry Andric // The label will be handled in the next iteration. 2116bdd1243dSDimitry Andric break; 2117bdd1243dSDimitry Andric } 2118bdd1243dSDimitry Andric if (FormatTok->is(Keywords.kw_clocking)) { 2119bdd1243dSDimitry Andric // A default clocking block. 2120bdd1243dSDimitry Andric parseBlock(); 2121bdd1243dSDimitry Andric addUnwrappedLine(); 2122bdd1243dSDimitry Andric return; 2123bdd1243dSDimitry Andric } 2124bdd1243dSDimitry Andric parseVerilogCaseLabel(); 2125bdd1243dSDimitry Andric return; 2126bdd1243dSDimitry Andric } 2127bdd1243dSDimitry Andric break; 2128bdd1243dSDimitry Andric case tok::colon: 2129bdd1243dSDimitry Andric nextToken(); 2130bdd1243dSDimitry Andric if (Style.isVerilog()) { 2131bdd1243dSDimitry Andric parseVerilogCaseLabel(); 2132bdd1243dSDimitry Andric return; 2133bdd1243dSDimitry Andric } 2134bdd1243dSDimitry Andric break; 21355deeebd8SDimitry Andric case tok::greater: 21365deeebd8SDimitry Andric nextToken(); 21375deeebd8SDimitry Andric if (FormatTok->is(tok::l_brace)) 21385deeebd8SDimitry Andric FormatTok->Previous->setFinalizedType(TT_TemplateCloser); 21395deeebd8SDimitry Andric break; 21400b57cec5SDimitry Andric default: 21410b57cec5SDimitry Andric nextToken(); 21420b57cec5SDimitry Andric break; 21430b57cec5SDimitry Andric } 21440fca6ea1SDimitry Andric } 21450b57cec5SDimitry Andric } 21460b57cec5SDimitry Andric 21475ffd83dbSDimitry Andric bool UnwrappedLineParser::tryToParsePropertyAccessor() { 21485ffd83dbSDimitry Andric assert(FormatTok->is(tok::l_brace)); 21495ffd83dbSDimitry Andric if (!Style.isCSharp()) 21505ffd83dbSDimitry Andric return false; 21515ffd83dbSDimitry Andric // See if it's a property accessor. 21525ffd83dbSDimitry Andric if (FormatTok->Previous->isNot(tok::identifier)) 21535ffd83dbSDimitry Andric return false; 21545ffd83dbSDimitry Andric 21555ffd83dbSDimitry Andric // See if we are inside a property accessor. 21565ffd83dbSDimitry Andric // 21575ffd83dbSDimitry Andric // Record the current tokenPosition so that we can advance and 21585ffd83dbSDimitry Andric // reset the current token. `Next` is not set yet so we need 21595ffd83dbSDimitry Andric // another way to advance along the token stream. 21605ffd83dbSDimitry Andric unsigned int StoredPosition = Tokens->getPosition(); 21615ffd83dbSDimitry Andric FormatToken *Tok = Tokens->getNextToken(); 21625ffd83dbSDimitry Andric 21635ffd83dbSDimitry Andric // A trivial property accessor is of the form: 216481ad6265SDimitry Andric // { [ACCESS_SPECIFIER] [get]; [ACCESS_SPECIFIER] [set|init] } 21655ffd83dbSDimitry Andric // Track these as they do not require line breaks to be introduced. 216681ad6265SDimitry Andric bool HasSpecialAccessor = false; 21675ffd83dbSDimitry Andric bool IsTrivialPropertyAccessor = true; 21685ffd83dbSDimitry Andric while (!eof()) { 21690fca6ea1SDimitry Andric if (Tok->isAccessSpecifierKeyword() || 21700fca6ea1SDimitry Andric Tok->isOneOf(tok::semi, Keywords.kw_internal, Keywords.kw_get, 217181ad6265SDimitry Andric Keywords.kw_init, Keywords.kw_set)) { 217281ad6265SDimitry Andric if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set)) 217381ad6265SDimitry Andric HasSpecialAccessor = true; 21745ffd83dbSDimitry Andric Tok = Tokens->getNextToken(); 21755ffd83dbSDimitry Andric continue; 21765ffd83dbSDimitry Andric } 21775ffd83dbSDimitry Andric if (Tok->isNot(tok::r_brace)) 21785ffd83dbSDimitry Andric IsTrivialPropertyAccessor = false; 21795ffd83dbSDimitry Andric break; 21805ffd83dbSDimitry Andric } 21815ffd83dbSDimitry Andric 218281ad6265SDimitry Andric if (!HasSpecialAccessor) { 21835ffd83dbSDimitry Andric Tokens->setPosition(StoredPosition); 21845ffd83dbSDimitry Andric return false; 21855ffd83dbSDimitry Andric } 21865ffd83dbSDimitry Andric 21875ffd83dbSDimitry Andric // Try to parse the property accessor: 21885ffd83dbSDimitry Andric // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties 21895ffd83dbSDimitry Andric Tokens->setPosition(StoredPosition); 21900eae32dcSDimitry Andric if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction) 21915ffd83dbSDimitry Andric addUnwrappedLine(); 21925ffd83dbSDimitry Andric nextToken(); 21935ffd83dbSDimitry Andric do { 21945ffd83dbSDimitry Andric switch (FormatTok->Tok.getKind()) { 21955ffd83dbSDimitry Andric case tok::r_brace: 21965ffd83dbSDimitry Andric nextToken(); 21975ffd83dbSDimitry Andric if (FormatTok->is(tok::equal)) { 21985ffd83dbSDimitry Andric while (!eof() && FormatTok->isNot(tok::semi)) 21995ffd83dbSDimitry Andric nextToken(); 22005ffd83dbSDimitry Andric nextToken(); 22015ffd83dbSDimitry Andric } 22025ffd83dbSDimitry Andric addUnwrappedLine(); 22035ffd83dbSDimitry Andric return true; 22045ffd83dbSDimitry Andric case tok::l_brace: 22055ffd83dbSDimitry Andric ++Line->Level; 22065ffd83dbSDimitry Andric parseBlock(/*MustBeDeclaration=*/true); 22075ffd83dbSDimitry Andric addUnwrappedLine(); 22085ffd83dbSDimitry Andric --Line->Level; 22095ffd83dbSDimitry Andric break; 22105ffd83dbSDimitry Andric case tok::equal: 2211fe6060f1SDimitry Andric if (FormatTok->is(TT_FatArrow)) { 22125ffd83dbSDimitry Andric ++Line->Level; 22135ffd83dbSDimitry Andric do { 22145ffd83dbSDimitry Andric nextToken(); 22155ffd83dbSDimitry Andric } while (!eof() && FormatTok->isNot(tok::semi)); 22165ffd83dbSDimitry Andric nextToken(); 22175ffd83dbSDimitry Andric addUnwrappedLine(); 22185ffd83dbSDimitry Andric --Line->Level; 22195ffd83dbSDimitry Andric break; 22205ffd83dbSDimitry Andric } 22215ffd83dbSDimitry Andric nextToken(); 22225ffd83dbSDimitry Andric break; 22235ffd83dbSDimitry Andric default: 222481ad6265SDimitry Andric if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init, 222581ad6265SDimitry Andric Keywords.kw_set) && 22265ffd83dbSDimitry Andric !IsTrivialPropertyAccessor) { 22275ffd83dbSDimitry Andric // Non-trivial get/set needs to be on its own line. 22285ffd83dbSDimitry Andric addUnwrappedLine(); 22295ffd83dbSDimitry Andric } 22305ffd83dbSDimitry Andric nextToken(); 22315ffd83dbSDimitry Andric } 22325ffd83dbSDimitry Andric } while (!eof()); 22335ffd83dbSDimitry Andric 22345ffd83dbSDimitry Andric // Unreachable for well-formed code (paired '{' and '}'). 22355ffd83dbSDimitry Andric return true; 22365ffd83dbSDimitry Andric } 22375ffd83dbSDimitry Andric 22380b57cec5SDimitry Andric bool UnwrappedLineParser::tryToParseLambda() { 223981ad6265SDimitry Andric assert(FormatTok->is(tok::l_square)); 22400fca6ea1SDimitry Andric if (!IsCpp) { 22410b57cec5SDimitry Andric nextToken(); 22420b57cec5SDimitry Andric return false; 22430b57cec5SDimitry Andric } 22440b57cec5SDimitry Andric FormatToken &LSquare = *FormatTok; 22450b57cec5SDimitry Andric if (!tryToParseLambdaIntroducer()) 22460b57cec5SDimitry Andric return false; 22470b57cec5SDimitry Andric 22480b57cec5SDimitry Andric bool SeenArrow = false; 224904eeddc0SDimitry Andric bool InTemplateParameterList = false; 22500b57cec5SDimitry Andric 22510b57cec5SDimitry Andric while (FormatTok->isNot(tok::l_brace)) { 22520fca6ea1SDimitry Andric if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) { 22530b57cec5SDimitry Andric nextToken(); 22540b57cec5SDimitry Andric continue; 22550b57cec5SDimitry Andric } 22560b57cec5SDimitry Andric switch (FormatTok->Tok.getKind()) { 22570b57cec5SDimitry Andric case tok::l_brace: 22580b57cec5SDimitry Andric break; 22590b57cec5SDimitry Andric case tok::l_paren: 226006c3fb27SDimitry Andric parseParens(/*AmpAmpTokenType=*/TT_PointerOrReference); 22610b57cec5SDimitry Andric break; 226204eeddc0SDimitry Andric case tok::l_square: 226304eeddc0SDimitry Andric parseSquare(); 226404eeddc0SDimitry Andric break; 2265bdd1243dSDimitry Andric case tok::less: 226604eeddc0SDimitry Andric assert(FormatTok->Previous); 2267bdd1243dSDimitry Andric if (FormatTok->Previous->is(tok::r_square)) 226804eeddc0SDimitry Andric InTemplateParameterList = true; 226904eeddc0SDimitry Andric nextToken(); 227004eeddc0SDimitry Andric break; 2271bdd1243dSDimitry Andric case tok::kw_auto: 2272bdd1243dSDimitry Andric case tok::kw_class: 22730fca6ea1SDimitry Andric case tok::kw_struct: 22740fca6ea1SDimitry Andric case tok::kw_union: 2275bdd1243dSDimitry Andric case tok::kw_template: 2276bdd1243dSDimitry Andric case tok::kw_typename: 22770b57cec5SDimitry Andric case tok::amp: 22780b57cec5SDimitry Andric case tok::star: 22790b57cec5SDimitry Andric case tok::kw_const: 2280fcaf7f86SDimitry Andric case tok::kw_constexpr: 2281bdd1243dSDimitry Andric case tok::kw_consteval: 22820b57cec5SDimitry Andric case tok::comma: 22830b57cec5SDimitry Andric case tok::greater: 22840b57cec5SDimitry Andric case tok::identifier: 22850b57cec5SDimitry Andric case tok::numeric_constant: 22860b57cec5SDimitry Andric case tok::coloncolon: 22870b57cec5SDimitry Andric case tok::kw_mutable: 22880b57cec5SDimitry Andric case tok::kw_noexcept: 2289bdd1243dSDimitry Andric case tok::kw_static: 22900b57cec5SDimitry Andric nextToken(); 22910b57cec5SDimitry Andric break; 22920b57cec5SDimitry Andric // Specialization of a template with an integer parameter can contain 22930b57cec5SDimitry Andric // arithmetic, logical, comparison and ternary operators. 22940b57cec5SDimitry Andric // 22950b57cec5SDimitry Andric // FIXME: This also accepts sequences of operators that are not in the scope 22960b57cec5SDimitry Andric // of a template argument list. 22970b57cec5SDimitry Andric // 22980b57cec5SDimitry Andric // In a C++ lambda a template type can only occur after an arrow. We use 22990b57cec5SDimitry Andric // this as an heuristic to distinguish between Objective-C expressions 23000b57cec5SDimitry Andric // followed by an `a->b` expression, such as: 23010b57cec5SDimitry Andric // ([obj func:arg] + a->b) 23020b57cec5SDimitry Andric // Otherwise the code below would parse as a lambda. 23030b57cec5SDimitry Andric case tok::plus: 23040b57cec5SDimitry Andric case tok::minus: 23050b57cec5SDimitry Andric case tok::exclaim: 23060b57cec5SDimitry Andric case tok::tilde: 23070b57cec5SDimitry Andric case tok::slash: 23080b57cec5SDimitry Andric case tok::percent: 23090b57cec5SDimitry Andric case tok::lessless: 23100b57cec5SDimitry Andric case tok::pipe: 23110b57cec5SDimitry Andric case tok::pipepipe: 23120b57cec5SDimitry Andric case tok::ampamp: 23130b57cec5SDimitry Andric case tok::caret: 23140b57cec5SDimitry Andric case tok::equalequal: 23150b57cec5SDimitry Andric case tok::exclaimequal: 23160b57cec5SDimitry Andric case tok::greaterequal: 23170b57cec5SDimitry Andric case tok::lessequal: 23180b57cec5SDimitry Andric case tok::question: 23190b57cec5SDimitry Andric case tok::colon: 23205ffd83dbSDimitry Andric case tok::ellipsis: 23210b57cec5SDimitry Andric case tok::kw_true: 23220b57cec5SDimitry Andric case tok::kw_false: 232304eeddc0SDimitry Andric if (SeenArrow || InTemplateParameterList) { 23240b57cec5SDimitry Andric nextToken(); 23250b57cec5SDimitry Andric break; 23260b57cec5SDimitry Andric } 23270b57cec5SDimitry Andric return true; 23280b57cec5SDimitry Andric case tok::arrow: 23290b57cec5SDimitry Andric // This might or might not actually be a lambda arrow (this could be an 23300b57cec5SDimitry Andric // ObjC method invocation followed by a dereferencing arrow). We might 23310b57cec5SDimitry Andric // reset this back to TT_Unknown in TokenAnnotator. 23326c4b055cSDimitry Andric FormatTok->setFinalizedType(TT_LambdaArrow); 23330b57cec5SDimitry Andric SeenArrow = true; 23340b57cec5SDimitry Andric nextToken(); 23350b57cec5SDimitry Andric break; 233606c3fb27SDimitry Andric case tok::kw_requires: { 233706c3fb27SDimitry Andric auto *RequiresToken = FormatTok; 233806c3fb27SDimitry Andric nextToken(); 233906c3fb27SDimitry Andric parseRequiresClause(RequiresToken); 234006c3fb27SDimitry Andric break; 234106c3fb27SDimitry Andric } 23425f757f3fSDimitry Andric case tok::equal: 23435f757f3fSDimitry Andric if (!InTemplateParameterList) 23445f757f3fSDimitry Andric return true; 23455f757f3fSDimitry Andric nextToken(); 23465f757f3fSDimitry Andric break; 23470b57cec5SDimitry Andric default: 23480b57cec5SDimitry Andric return true; 23490b57cec5SDimitry Andric } 23500b57cec5SDimitry Andric } 2351bdb86d1aSDimitry Andric 235281ad6265SDimitry Andric FormatTok->setFinalizedType(TT_LambdaLBrace); 235381ad6265SDimitry Andric LSquare.setFinalizedType(TT_LambdaLSquare); 2354bdb86d1aSDimitry Andric 2355bdb86d1aSDimitry Andric NestedLambdas.push_back(Line->SeenDecltypeAuto); 23560b57cec5SDimitry Andric parseChildBlock(); 2357bdb86d1aSDimitry Andric assert(!NestedLambdas.empty()); 2358bdb86d1aSDimitry Andric NestedLambdas.pop_back(); 2359bdb86d1aSDimitry Andric 23600b57cec5SDimitry Andric return true; 23610b57cec5SDimitry Andric } 23620b57cec5SDimitry Andric 23630b57cec5SDimitry Andric bool UnwrappedLineParser::tryToParseLambdaIntroducer() { 23640b57cec5SDimitry Andric const FormatToken *Previous = FormatTok->Previous; 236581ad6265SDimitry Andric const FormatToken *LeftSquare = FormatTok; 236681ad6265SDimitry Andric nextToken(); 236706c3fb27SDimitry Andric if ((Previous && ((Previous->Tok.getIdentifierInfo() && 236806c3fb27SDimitry Andric !Previous->isOneOf(tok::kw_return, tok::kw_co_await, 236906c3fb27SDimitry Andric tok::kw_co_yield, tok::kw_co_return)) || 237006c3fb27SDimitry Andric Previous->closesScope())) || 23710fca6ea1SDimitry Andric LeftSquare->isCppStructuredBinding(IsCpp)) { 23720b57cec5SDimitry Andric return false; 23730b57cec5SDimitry Andric } 2374297eecfbSDimitry Andric if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind())) 237581ad6265SDimitry Andric return false; 237681ad6265SDimitry Andric if (FormatTok->is(tok::r_square)) { 2377bdd1243dSDimitry Andric const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true); 237881ad6265SDimitry Andric if (Next->is(tok::greater)) 23790b57cec5SDimitry Andric return false; 23800b57cec5SDimitry Andric } 23810b57cec5SDimitry Andric parseSquare(/*LambdaIntroducer=*/true); 23820b57cec5SDimitry Andric return true; 23830b57cec5SDimitry Andric } 23840b57cec5SDimitry Andric 23850b57cec5SDimitry Andric void UnwrappedLineParser::tryToParseJSFunction() { 23865f757f3fSDimitry Andric assert(FormatTok->is(Keywords.kw_function)); 23870b57cec5SDimitry Andric if (FormatTok->is(Keywords.kw_async)) 23880b57cec5SDimitry Andric nextToken(); 23890b57cec5SDimitry Andric // Consume "function". 23900b57cec5SDimitry Andric nextToken(); 23910b57cec5SDimitry Andric 23920b57cec5SDimitry Andric // Consume * (generator function). Treat it like C++'s overloaded operators. 23930b57cec5SDimitry Andric if (FormatTok->is(tok::star)) { 239481ad6265SDimitry Andric FormatTok->setFinalizedType(TT_OverloadedOperator); 23950b57cec5SDimitry Andric nextToken(); 23960b57cec5SDimitry Andric } 23970b57cec5SDimitry Andric 23980b57cec5SDimitry Andric // Consume function name. 23990b57cec5SDimitry Andric if (FormatTok->is(tok::identifier)) 24000b57cec5SDimitry Andric nextToken(); 24010b57cec5SDimitry Andric 24020b57cec5SDimitry Andric if (FormatTok->isNot(tok::l_paren)) 24030b57cec5SDimitry Andric return; 24040b57cec5SDimitry Andric 24050b57cec5SDimitry Andric // Parse formal parameter list. 24060b57cec5SDimitry Andric parseParens(); 24070b57cec5SDimitry Andric 24080b57cec5SDimitry Andric if (FormatTok->is(tok::colon)) { 24090b57cec5SDimitry Andric // Parse a type definition. 24100b57cec5SDimitry Andric nextToken(); 24110b57cec5SDimitry Andric 24120b57cec5SDimitry Andric // Eat the type declaration. For braced inline object types, balance braces, 24130b57cec5SDimitry Andric // otherwise just parse until finding an l_brace for the function body. 24140b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) 24150b57cec5SDimitry Andric tryToParseBracedList(); 24160b57cec5SDimitry Andric else 24170b57cec5SDimitry Andric while (!FormatTok->isOneOf(tok::l_brace, tok::semi) && !eof()) 24180b57cec5SDimitry Andric nextToken(); 24190b57cec5SDimitry Andric } 24200b57cec5SDimitry Andric 24210b57cec5SDimitry Andric if (FormatTok->is(tok::semi)) 24220b57cec5SDimitry Andric return; 24230b57cec5SDimitry Andric 24240b57cec5SDimitry Andric parseChildBlock(); 24250b57cec5SDimitry Andric } 24260b57cec5SDimitry Andric 24270b57cec5SDimitry Andric bool UnwrappedLineParser::tryToParseBracedList() { 2428e8d8bef9SDimitry Andric if (FormatTok->is(BK_Unknown)) 24290b57cec5SDimitry Andric calculateBraceTypes(); 2430e8d8bef9SDimitry Andric assert(FormatTok->isNot(BK_Unknown)); 2431e8d8bef9SDimitry Andric if (FormatTok->is(BK_Block)) 24320b57cec5SDimitry Andric return false; 24330b57cec5SDimitry Andric nextToken(); 24340b57cec5SDimitry Andric parseBracedList(); 24350b57cec5SDimitry Andric return true; 24360b57cec5SDimitry Andric } 24370b57cec5SDimitry Andric 24380eae32dcSDimitry Andric bool UnwrappedLineParser::tryToParseChildBlock() { 24390eae32dcSDimitry Andric assert(Style.isJavaScript() || Style.isCSharp()); 24400eae32dcSDimitry Andric assert(FormatTok->is(TT_FatArrow)); 24410eae32dcSDimitry Andric // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType TT_FatArrow. 24420eae32dcSDimitry Andric // They always start an expression or a child block if followed by a curly 24430eae32dcSDimitry Andric // brace. 24440eae32dcSDimitry Andric nextToken(); 24450eae32dcSDimitry Andric if (FormatTok->isNot(tok::l_brace)) 24460eae32dcSDimitry Andric return false; 24470eae32dcSDimitry Andric parseChildBlock(); 24480eae32dcSDimitry Andric return true; 24490eae32dcSDimitry Andric } 24500eae32dcSDimitry Andric 24515f757f3fSDimitry Andric bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) { 24520fca6ea1SDimitry Andric assert(!IsAngleBracket || !IsEnum); 24530b57cec5SDimitry Andric bool HasError = false; 24540b57cec5SDimitry Andric 24550b57cec5SDimitry Andric // FIXME: Once we have an expression parser in the UnwrappedLineParser, 2456fe6060f1SDimitry Andric // replace this by using parseAssignmentExpression() inside. 24570b57cec5SDimitry Andric do { 24580eae32dcSDimitry Andric if (Style.isCSharp() && FormatTok->is(TT_FatArrow) && 245981ad6265SDimitry Andric tryToParseChildBlock()) { 24605ffd83dbSDimitry Andric continue; 246181ad6265SDimitry Andric } 24620eae32dcSDimitry Andric if (Style.isJavaScript()) { 24635f757f3fSDimitry Andric if (FormatTok->is(Keywords.kw_function)) { 24640b57cec5SDimitry Andric tryToParseJSFunction(); 24650b57cec5SDimitry Andric continue; 24660b57cec5SDimitry Andric } 24670b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 24680b57cec5SDimitry Andric // Could be a method inside of a braced list `{a() { return 1; }}`. 24690b57cec5SDimitry Andric if (tryToParseBracedList()) 24700b57cec5SDimitry Andric continue; 24710b57cec5SDimitry Andric parseChildBlock(); 24720b57cec5SDimitry Andric } 24730b57cec5SDimitry Andric } 24745f757f3fSDimitry Andric if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) { 24750fca6ea1SDimitry Andric if (IsEnum) { 24760fca6ea1SDimitry Andric FormatTok->setBlockKind(BK_Block); 24770fca6ea1SDimitry Andric if (!Style.AllowShortEnumsOnASingleLine) 24785ffd83dbSDimitry Andric addUnwrappedLine(); 24790fca6ea1SDimitry Andric } 24800b57cec5SDimitry Andric nextToken(); 24810b57cec5SDimitry Andric return !HasError; 24820b57cec5SDimitry Andric } 24830b57cec5SDimitry Andric switch (FormatTok->Tok.getKind()) { 24840b57cec5SDimitry Andric case tok::l_square: 24855ffd83dbSDimitry Andric if (Style.isCSharp()) 24865ffd83dbSDimitry Andric parseSquare(); 24875ffd83dbSDimitry Andric else 24880b57cec5SDimitry Andric tryToParseLambda(); 24890b57cec5SDimitry Andric break; 24900b57cec5SDimitry Andric case tok::l_paren: 24910b57cec5SDimitry Andric parseParens(); 24920b57cec5SDimitry Andric // JavaScript can just have free standing methods and getters/setters in 24930b57cec5SDimitry Andric // object literals. Detect them by a "{" following ")". 24940eae32dcSDimitry Andric if (Style.isJavaScript()) { 24950b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) 24960b57cec5SDimitry Andric parseChildBlock(); 24970b57cec5SDimitry Andric break; 24980b57cec5SDimitry Andric } 24990b57cec5SDimitry Andric break; 25000b57cec5SDimitry Andric case tok::l_brace: 25010b57cec5SDimitry Andric // Assume there are no blocks inside a braced init list apart 25020b57cec5SDimitry Andric // from the ones we explicitly parse out (like lambdas). 2503e8d8bef9SDimitry Andric FormatTok->setBlockKind(BK_BracedInit); 2504d686ce93SDimitry Andric if (!IsAngleBracket) { 2505d686ce93SDimitry Andric auto *Prev = FormatTok->Previous; 2506d686ce93SDimitry Andric if (Prev && Prev->is(tok::greater)) 2507d686ce93SDimitry Andric Prev->setFinalizedType(TT_TemplateCloser); 2508d686ce93SDimitry Andric } 25090b57cec5SDimitry Andric nextToken(); 25100b57cec5SDimitry Andric parseBracedList(); 25110b57cec5SDimitry Andric break; 25120b57cec5SDimitry Andric case tok::less: 25130b57cec5SDimitry Andric nextToken(); 25145f757f3fSDimitry Andric if (IsAngleBracket) 25155f757f3fSDimitry Andric parseBracedList(/*IsAngleBracket=*/true); 25160b57cec5SDimitry Andric break; 25170b57cec5SDimitry Andric case tok::semi: 25180b57cec5SDimitry Andric // JavaScript (or more precisely TypeScript) can have semicolons in braced 25190b57cec5SDimitry Andric // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be 25200b57cec5SDimitry Andric // used for error recovery if we have otherwise determined that this is 25210b57cec5SDimitry Andric // a braced list. 25220eae32dcSDimitry Andric if (Style.isJavaScript()) { 25230b57cec5SDimitry Andric nextToken(); 25240b57cec5SDimitry Andric break; 25250b57cec5SDimitry Andric } 25260b57cec5SDimitry Andric HasError = true; 25275f757f3fSDimitry Andric if (!IsEnum) 25285f757f3fSDimitry Andric return false; 25290b57cec5SDimitry Andric nextToken(); 25300b57cec5SDimitry Andric break; 25310b57cec5SDimitry Andric case tok::comma: 25320b57cec5SDimitry Andric nextToken(); 25335ffd83dbSDimitry Andric if (IsEnum && !Style.AllowShortEnumsOnASingleLine) 25345ffd83dbSDimitry Andric addUnwrappedLine(); 25350b57cec5SDimitry Andric break; 25360b57cec5SDimitry Andric default: 25370b57cec5SDimitry Andric nextToken(); 25380b57cec5SDimitry Andric break; 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric } while (!eof()); 25410b57cec5SDimitry Andric return false; 25420b57cec5SDimitry Andric } 25430b57cec5SDimitry Andric 254481ad6265SDimitry Andric /// \brief Parses a pair of parentheses (and everything between them). 254581ad6265SDimitry Andric /// \param AmpAmpTokenType If different than TT_Unknown sets this type for all 254606c3fb27SDimitry Andric /// double ampersands. This applies for all nested scopes as well. 254706c3fb27SDimitry Andric /// 254806c3fb27SDimitry Andric /// Returns whether there is a `=` token between the parentheses. 254906c3fb27SDimitry Andric bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { 255081ad6265SDimitry Andric assert(FormatTok->is(tok::l_paren) && "'(' expected."); 255106c3fb27SDimitry Andric auto *LeftParen = FormatTok; 255206c3fb27SDimitry Andric bool SeenEqual = false; 25533a079333SDimitry Andric bool MightBeFoldExpr = false; 255406c3fb27SDimitry Andric const bool MightBeStmtExpr = Tokens->peekNextToken()->is(tok::l_brace); 25550b57cec5SDimitry Andric nextToken(); 25560b57cec5SDimitry Andric do { 25570b57cec5SDimitry Andric switch (FormatTok->Tok.getKind()) { 25580b57cec5SDimitry Andric case tok::l_paren: 255906c3fb27SDimitry Andric if (parseParens(AmpAmpTokenType)) 256006c3fb27SDimitry Andric SeenEqual = true; 25610b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace)) 25620b57cec5SDimitry Andric parseChildBlock(); 25630b57cec5SDimitry Andric break; 25640fca6ea1SDimitry Andric case tok::r_paren: { 25655deeebd8SDimitry Andric auto *Prev = LeftParen->Previous; 25663a079333SDimitry Andric if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody && 256706c3fb27SDimitry Andric Style.RemoveParentheses > FormatStyle::RPS_Leave) { 256806c3fb27SDimitry Andric const auto *Next = Tokens->peekNextToken(); 256906c3fb27SDimitry Andric const bool DoubleParens = 257006c3fb27SDimitry Andric Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren); 257106c3fb27SDimitry Andric const auto *PrevPrev = Prev ? Prev->getPreviousNonComment() : nullptr; 257206c3fb27SDimitry Andric const bool Blacklisted = 257306c3fb27SDimitry Andric PrevPrev && 25748a4dda33SDimitry Andric (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) || 257506c3fb27SDimitry Andric (SeenEqual && 257606c3fb27SDimitry Andric (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) || 257706c3fb27SDimitry Andric PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if)))); 257806c3fb27SDimitry Andric const bool ReturnParens = 257906c3fb27SDimitry Andric Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement && 2580bdb86d1aSDimitry Andric ((NestedLambdas.empty() && !IsDecltypeAutoFunction) || 2581bdb86d1aSDimitry Andric (!NestedLambdas.empty() && !NestedLambdas.back())) && 258206c3fb27SDimitry Andric Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next && 258306c3fb27SDimitry Andric Next->is(tok::semi); 258406c3fb27SDimitry Andric if ((DoubleParens && !Blacklisted) || ReturnParens) { 258506c3fb27SDimitry Andric LeftParen->Optional = true; 258606c3fb27SDimitry Andric FormatTok->Optional = true; 258706c3fb27SDimitry Andric } 258806c3fb27SDimitry Andric } 25895deeebd8SDimitry Andric if (Prev) { 25905deeebd8SDimitry Andric if (Prev->is(TT_TypenameMacro)) { 25910fca6ea1SDimitry Andric LeftParen->setFinalizedType(TT_TypeDeclarationParen); 25920fca6ea1SDimitry Andric FormatTok->setFinalizedType(TT_TypeDeclarationParen); 25935deeebd8SDimitry Andric } else if (Prev->is(tok::greater) && FormatTok->Previous == LeftParen) { 25945deeebd8SDimitry Andric Prev->setFinalizedType(TT_TemplateCloser); 25955deeebd8SDimitry Andric } 25960fca6ea1SDimitry Andric } 25970b57cec5SDimitry Andric nextToken(); 259806c3fb27SDimitry Andric return SeenEqual; 25990fca6ea1SDimitry Andric } 26000b57cec5SDimitry Andric case tok::r_brace: 26010b57cec5SDimitry Andric // A "}" inside parenthesis is an error if there wasn't a matching "{". 260206c3fb27SDimitry Andric return SeenEqual; 26030b57cec5SDimitry Andric case tok::l_square: 26040b57cec5SDimitry Andric tryToParseLambda(); 26050b57cec5SDimitry Andric break; 26060b57cec5SDimitry Andric case tok::l_brace: 26070b57cec5SDimitry Andric if (!tryToParseBracedList()) 26080b57cec5SDimitry Andric parseChildBlock(); 26090b57cec5SDimitry Andric break; 26100b57cec5SDimitry Andric case tok::at: 26110b57cec5SDimitry Andric nextToken(); 261281ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 26130b57cec5SDimitry Andric nextToken(); 26140b57cec5SDimitry Andric parseBracedList(); 26150b57cec5SDimitry Andric } 26160b57cec5SDimitry Andric break; 26173a079333SDimitry Andric case tok::ellipsis: 26183a079333SDimitry Andric MightBeFoldExpr = true; 26193a079333SDimitry Andric nextToken(); 26203a079333SDimitry Andric break; 2621fe6060f1SDimitry Andric case tok::equal: 262206c3fb27SDimitry Andric SeenEqual = true; 2623fe6060f1SDimitry Andric if (Style.isCSharp() && FormatTok->is(TT_FatArrow)) 26240eae32dcSDimitry Andric tryToParseChildBlock(); 2625fe6060f1SDimitry Andric else 2626fe6060f1SDimitry Andric nextToken(); 2627fe6060f1SDimitry Andric break; 26280b57cec5SDimitry Andric case tok::kw_class: 26290eae32dcSDimitry Andric if (Style.isJavaScript()) 26300b57cec5SDimitry Andric parseRecord(/*ParseAsExpr=*/true); 26310b57cec5SDimitry Andric else 26320b57cec5SDimitry Andric nextToken(); 26330b57cec5SDimitry Andric break; 26340b57cec5SDimitry Andric case tok::identifier: 26355f757f3fSDimitry Andric if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function))) 26360b57cec5SDimitry Andric tryToParseJSFunction(); 26375f757f3fSDimitry Andric else 26380b57cec5SDimitry Andric nextToken(); 26390b57cec5SDimitry Andric break; 26400fca6ea1SDimitry Andric case tok::kw_switch: 2641415efcecSDimitry Andric if (Style.Language == FormatStyle::LK_Java) 26420fca6ea1SDimitry Andric parseSwitch(/*IsExpr=*/true); 2643415efcecSDimitry Andric else 2644415efcecSDimitry Andric nextToken(); 26450fca6ea1SDimitry Andric break; 264681ad6265SDimitry Andric case tok::kw_requires: { 264781ad6265SDimitry Andric auto RequiresToken = FormatTok; 264881ad6265SDimitry Andric nextToken(); 264981ad6265SDimitry Andric parseRequiresExpression(RequiresToken); 265081ad6265SDimitry Andric break; 265181ad6265SDimitry Andric } 265281ad6265SDimitry Andric case tok::ampamp: 265381ad6265SDimitry Andric if (AmpAmpTokenType != TT_Unknown) 265481ad6265SDimitry Andric FormatTok->setFinalizedType(AmpAmpTokenType); 2655bdd1243dSDimitry Andric [[fallthrough]]; 26560b57cec5SDimitry Andric default: 26570b57cec5SDimitry Andric nextToken(); 26580b57cec5SDimitry Andric break; 26590b57cec5SDimitry Andric } 26600b57cec5SDimitry Andric } while (!eof()); 266106c3fb27SDimitry Andric return SeenEqual; 26620b57cec5SDimitry Andric } 26630b57cec5SDimitry Andric 26640b57cec5SDimitry Andric void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) { 26650b57cec5SDimitry Andric if (!LambdaIntroducer) { 266681ad6265SDimitry Andric assert(FormatTok->is(tok::l_square) && "'[' expected."); 26670b57cec5SDimitry Andric if (tryToParseLambda()) 26680b57cec5SDimitry Andric return; 26690b57cec5SDimitry Andric } 26700b57cec5SDimitry Andric do { 26710b57cec5SDimitry Andric switch (FormatTok->Tok.getKind()) { 26720b57cec5SDimitry Andric case tok::l_paren: 26730b57cec5SDimitry Andric parseParens(); 26740b57cec5SDimitry Andric break; 26750b57cec5SDimitry Andric case tok::r_square: 26760b57cec5SDimitry Andric nextToken(); 26770b57cec5SDimitry Andric return; 26780b57cec5SDimitry Andric case tok::r_brace: 26790b57cec5SDimitry Andric // A "}" inside parenthesis is an error if there wasn't a matching "{". 26800b57cec5SDimitry Andric return; 26810b57cec5SDimitry Andric case tok::l_square: 26820b57cec5SDimitry Andric parseSquare(); 26830b57cec5SDimitry Andric break; 26840b57cec5SDimitry Andric case tok::l_brace: { 26850b57cec5SDimitry Andric if (!tryToParseBracedList()) 26860b57cec5SDimitry Andric parseChildBlock(); 26870b57cec5SDimitry Andric break; 26880b57cec5SDimitry Andric } 26890b57cec5SDimitry Andric case tok::at: 26906c4b055cSDimitry Andric case tok::colon: 26910b57cec5SDimitry Andric nextToken(); 269281ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 26930b57cec5SDimitry Andric nextToken(); 26940b57cec5SDimitry Andric parseBracedList(); 26950b57cec5SDimitry Andric } 26960b57cec5SDimitry Andric break; 26970b57cec5SDimitry Andric default: 26980b57cec5SDimitry Andric nextToken(); 26990b57cec5SDimitry Andric break; 27000b57cec5SDimitry Andric } 27010b57cec5SDimitry Andric } while (!eof()); 27020b57cec5SDimitry Andric } 27030b57cec5SDimitry Andric 270404eeddc0SDimitry Andric void UnwrappedLineParser::keepAncestorBraces() { 270504eeddc0SDimitry Andric if (!Style.RemoveBracesLLVM) 270604eeddc0SDimitry Andric return; 270704eeddc0SDimitry Andric 270804eeddc0SDimitry Andric const int MaxNestingLevels = 2; 270904eeddc0SDimitry Andric const int Size = NestedTooDeep.size(); 271004eeddc0SDimitry Andric if (Size >= MaxNestingLevels) 271104eeddc0SDimitry Andric NestedTooDeep[Size - MaxNestingLevels] = true; 271204eeddc0SDimitry Andric NestedTooDeep.push_back(false); 271304eeddc0SDimitry Andric } 271404eeddc0SDimitry Andric 271581ad6265SDimitry Andric static FormatToken *getLastNonComment(const UnwrappedLine &Line) { 271681ad6265SDimitry Andric for (const auto &Token : llvm::reverse(Line.Tokens)) 271781ad6265SDimitry Andric if (Token.Tok->isNot(tok::comment)) 271881ad6265SDimitry Andric return Token.Tok; 271981ad6265SDimitry Andric 272081ad6265SDimitry Andric return nullptr; 272181ad6265SDimitry Andric } 272281ad6265SDimitry Andric 272381ad6265SDimitry Andric void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) { 272481ad6265SDimitry Andric FormatToken *Tok = nullptr; 272581ad6265SDimitry Andric 272681ad6265SDimitry Andric if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() && 2727bdd1243dSDimitry Andric PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) { 2728bdd1243dSDimitry Andric Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never 2729bdd1243dSDimitry Andric ? getLastNonComment(*Line) 2730bdd1243dSDimitry Andric : Line->Tokens.back().Tok; 273181ad6265SDimitry Andric assert(Tok); 273281ad6265SDimitry Andric if (Tok->BraceCount < 0) { 273381ad6265SDimitry Andric assert(Tok->BraceCount == -1); 273481ad6265SDimitry Andric Tok = nullptr; 273581ad6265SDimitry Andric } else { 273681ad6265SDimitry Andric Tok->BraceCount = -1; 273781ad6265SDimitry Andric } 273881ad6265SDimitry Andric } 273981ad6265SDimitry Andric 274081ad6265SDimitry Andric addUnwrappedLine(); 274181ad6265SDimitry Andric ++Line->Level; 27420fca6ea1SDimitry Andric ++Line->UnbracedBodyLevel; 274381ad6265SDimitry Andric parseStructuralElement(); 27440fca6ea1SDimitry Andric --Line->UnbracedBodyLevel; 274581ad6265SDimitry Andric 274681ad6265SDimitry Andric if (Tok) { 274781ad6265SDimitry Andric assert(!Line->InPPDirective); 274881ad6265SDimitry Andric Tok = nullptr; 274981ad6265SDimitry Andric for (const auto &L : llvm::reverse(*CurrentLines)) { 275081ad6265SDimitry Andric if (!L.InPPDirective && getLastNonComment(L)) { 275181ad6265SDimitry Andric Tok = L.Tokens.back().Tok; 275281ad6265SDimitry Andric break; 275381ad6265SDimitry Andric } 275481ad6265SDimitry Andric } 275581ad6265SDimitry Andric assert(Tok); 275681ad6265SDimitry Andric ++Tok->BraceCount; 275781ad6265SDimitry Andric } 275881ad6265SDimitry Andric 2759bdd1243dSDimitry Andric if (CheckEOF && eof()) 276081ad6265SDimitry Andric addUnwrappedLine(); 276181ad6265SDimitry Andric 276281ad6265SDimitry Andric --Line->Level; 276381ad6265SDimitry Andric } 276481ad6265SDimitry Andric 276504eeddc0SDimitry Andric static void markOptionalBraces(FormatToken *LeftBrace) { 276604eeddc0SDimitry Andric if (!LeftBrace) 276704eeddc0SDimitry Andric return; 276804eeddc0SDimitry Andric 276904eeddc0SDimitry Andric assert(LeftBrace->is(tok::l_brace)); 277004eeddc0SDimitry Andric 277104eeddc0SDimitry Andric FormatToken *RightBrace = LeftBrace->MatchingParen; 277204eeddc0SDimitry Andric if (!RightBrace) { 277304eeddc0SDimitry Andric assert(!LeftBrace->Optional); 277404eeddc0SDimitry Andric return; 277504eeddc0SDimitry Andric } 277604eeddc0SDimitry Andric 277704eeddc0SDimitry Andric assert(RightBrace->is(tok::r_brace)); 277804eeddc0SDimitry Andric assert(RightBrace->MatchingParen == LeftBrace); 277904eeddc0SDimitry Andric assert(LeftBrace->Optional == RightBrace->Optional); 278004eeddc0SDimitry Andric 278104eeddc0SDimitry Andric LeftBrace->Optional = true; 278204eeddc0SDimitry Andric RightBrace->Optional = true; 278304eeddc0SDimitry Andric } 278404eeddc0SDimitry Andric 278581ad6265SDimitry Andric void UnwrappedLineParser::handleAttributes() { 27860eae32dcSDimitry Andric // Handle AttributeMacro, e.g. `if (x) UNLIKELY`. 27875f757f3fSDimitry Andric if (FormatTok->isAttribute()) 27880eae32dcSDimitry Andric nextToken(); 27895f757f3fSDimitry Andric else if (FormatTok->is(tok::l_square)) 279081ad6265SDimitry Andric handleCppAttributes(); 279181ad6265SDimitry Andric } 27920eae32dcSDimitry Andric 279381ad6265SDimitry Andric bool UnwrappedLineParser::handleCppAttributes() { 279481ad6265SDimitry Andric // Handle [[likely]] / [[unlikely]] attributes. 27951ac55f4cSDimitry Andric assert(FormatTok->is(tok::l_square)); 27961ac55f4cSDimitry Andric if (!tryToParseSimpleAttribute()) 27971ac55f4cSDimitry Andric return false; 279881ad6265SDimitry Andric parseSquare(); 279981ad6265SDimitry Andric return true; 280081ad6265SDimitry Andric } 280181ad6265SDimitry Andric 2802bdd1243dSDimitry Andric /// Returns whether \c Tok begins a block. 2803bdd1243dSDimitry Andric bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const { 2804bdd1243dSDimitry Andric // FIXME: rename the function or make 2805bdd1243dSDimitry Andric // Tok.isOneOf(tok::l_brace, TT_MacroBlockBegin) work. 2806bdd1243dSDimitry Andric return Style.isVerilog() ? Keywords.isVerilogBegin(Tok) 2807bdd1243dSDimitry Andric : Tok.is(tok::l_brace); 2808bdd1243dSDimitry Andric } 2809bdd1243dSDimitry Andric 281081ad6265SDimitry Andric FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, 281106c3fb27SDimitry Andric bool KeepBraces, 281206c3fb27SDimitry Andric bool IsVerilogAssert) { 281306c3fb27SDimitry Andric assert((FormatTok->is(tok::kw_if) || 281406c3fb27SDimitry Andric (Style.isVerilog() && 281506c3fb27SDimitry Andric FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert, 281606c3fb27SDimitry Andric Keywords.kw_assume, Keywords.kw_cover))) && 281706c3fb27SDimitry Andric "'if' expected"); 28180b57cec5SDimitry Andric nextToken(); 281906c3fb27SDimitry Andric 282006c3fb27SDimitry Andric if (IsVerilogAssert) { 282106c3fb27SDimitry Andric // Handle `assert #0` and `assert final`. 282206c3fb27SDimitry Andric if (FormatTok->is(Keywords.kw_verilogHash)) { 282306c3fb27SDimitry Andric nextToken(); 282406c3fb27SDimitry Andric if (FormatTok->is(tok::numeric_constant)) 282506c3fb27SDimitry Andric nextToken(); 282606c3fb27SDimitry Andric } else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property, 282706c3fb27SDimitry Andric Keywords.kw_sequence)) { 282806c3fb27SDimitry Andric nextToken(); 282906c3fb27SDimitry Andric } 283006c3fb27SDimitry Andric } 283106c3fb27SDimitry Andric 28327a6dacacSDimitry Andric // TableGen's if statement has the form of `if <cond> then { ... }`. 28337a6dacacSDimitry Andric if (Style.isTableGen()) { 28347a6dacacSDimitry Andric while (!eof() && FormatTok->isNot(Keywords.kw_then)) { 28357a6dacacSDimitry Andric // Simply skip until then. This range only contains a value. 28367a6dacacSDimitry Andric nextToken(); 28377a6dacacSDimitry Andric } 28387a6dacacSDimitry Andric } 28397a6dacacSDimitry Andric 284006c3fb27SDimitry Andric // Handle `if !consteval`. 284181ad6265SDimitry Andric if (FormatTok->is(tok::exclaim)) 28420b57cec5SDimitry Andric nextToken(); 284381ad6265SDimitry Andric 284481ad6265SDimitry Andric bool KeepIfBraces = true; 284581ad6265SDimitry Andric if (FormatTok->is(tok::kw_consteval)) { 284681ad6265SDimitry Andric nextToken(); 284781ad6265SDimitry Andric } else { 284881ad6265SDimitry Andric KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces; 284981ad6265SDimitry Andric if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier)) 285081ad6265SDimitry Andric nextToken(); 285106c3fb27SDimitry Andric if (FormatTok->is(tok::l_paren)) { 285206c3fb27SDimitry Andric FormatTok->setFinalizedType(TT_ConditionLParen); 28530b57cec5SDimitry Andric parseParens(); 285481ad6265SDimitry Andric } 285506c3fb27SDimitry Andric } 285681ad6265SDimitry Andric handleAttributes(); 285706c3fb27SDimitry Andric // The then action is optional in Verilog assert statements. 285806c3fb27SDimitry Andric if (IsVerilogAssert && FormatTok->is(tok::semi)) { 285906c3fb27SDimitry Andric nextToken(); 286006c3fb27SDimitry Andric addUnwrappedLine(); 286106c3fb27SDimitry Andric return nullptr; 286206c3fb27SDimitry Andric } 286304eeddc0SDimitry Andric 28640b57cec5SDimitry Andric bool NeedsUnwrappedLine = false; 286504eeddc0SDimitry Andric keepAncestorBraces(); 286604eeddc0SDimitry Andric 286704eeddc0SDimitry Andric FormatToken *IfLeftBrace = nullptr; 286804eeddc0SDimitry Andric IfStmtKind IfBlockKind = IfStmtKind::NotIf; 286904eeddc0SDimitry Andric 2870bdd1243dSDimitry Andric if (isBlockBegin(*FormatTok)) { 287181ad6265SDimitry Andric FormatTok->setFinalizedType(TT_ControlStatementLBrace); 287204eeddc0SDimitry Andric IfLeftBrace = FormatTok; 28730b57cec5SDimitry Andric CompoundStatementIndenter Indenter(this, Style, Line->Level); 287481ad6265SDimitry Andric parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, 287581ad6265SDimitry Andric /*MunchSemi=*/true, KeepIfBraces, &IfBlockKind); 28765f757f3fSDimitry Andric setPreviousRBraceType(TT_ControlStatementRBrace); 28770b57cec5SDimitry Andric if (Style.BraceWrapping.BeforeElse) 28780b57cec5SDimitry Andric addUnwrappedLine(); 28790b57cec5SDimitry Andric else 28800b57cec5SDimitry Andric NeedsUnwrappedLine = true; 288106c3fb27SDimitry Andric } else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) { 288206c3fb27SDimitry Andric addUnwrappedLine(); 28830b57cec5SDimitry Andric } else { 288481ad6265SDimitry Andric parseUnbracedBody(); 28850b57cec5SDimitry Andric } 288604eeddc0SDimitry Andric 288704eeddc0SDimitry Andric if (Style.RemoveBracesLLVM) { 288804eeddc0SDimitry Andric assert(!NestedTooDeep.empty()); 288981ad6265SDimitry Andric KeepIfBraces = KeepIfBraces || 289081ad6265SDimitry Andric (IfLeftBrace && !IfLeftBrace->MatchingParen) || 289104eeddc0SDimitry Andric NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly || 289204eeddc0SDimitry Andric IfBlockKind == IfStmtKind::IfElseIf; 289304eeddc0SDimitry Andric } 289404eeddc0SDimitry Andric 289581ad6265SDimitry Andric bool KeepElseBraces = KeepIfBraces; 289604eeddc0SDimitry Andric FormatToken *ElseLeftBrace = nullptr; 289704eeddc0SDimitry Andric IfStmtKind Kind = IfStmtKind::IfOnly; 289804eeddc0SDimitry Andric 289981ad6265SDimitry Andric if (FormatTok->is(tok::kw_else)) { 290004eeddc0SDimitry Andric if (Style.RemoveBracesLLVM) { 290104eeddc0SDimitry Andric NestedTooDeep.back() = false; 290204eeddc0SDimitry Andric Kind = IfStmtKind::IfElse; 290304eeddc0SDimitry Andric } 29040b57cec5SDimitry Andric nextToken(); 290581ad6265SDimitry Andric handleAttributes(); 2906bdd1243dSDimitry Andric if (isBlockBegin(*FormatTok)) { 290781ad6265SDimitry Andric const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if); 290881ad6265SDimitry Andric FormatTok->setFinalizedType(TT_ElseLBrace); 290904eeddc0SDimitry Andric ElseLeftBrace = FormatTok; 29100b57cec5SDimitry Andric CompoundStatementIndenter Indenter(this, Style, Line->Level); 291181ad6265SDimitry Andric IfStmtKind ElseBlockKind = IfStmtKind::NotIf; 291281ad6265SDimitry Andric FormatToken *IfLBrace = 291381ad6265SDimitry Andric parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, 291481ad6265SDimitry Andric /*MunchSemi=*/true, KeepElseBraces, &ElseBlockKind); 29155f757f3fSDimitry Andric setPreviousRBraceType(TT_ElseRBrace); 291681ad6265SDimitry Andric if (FormatTok->is(tok::kw_else)) { 291781ad6265SDimitry Andric KeepElseBraces = KeepElseBraces || 291881ad6265SDimitry Andric ElseBlockKind == IfStmtKind::IfOnly || 291981ad6265SDimitry Andric ElseBlockKind == IfStmtKind::IfElseIf; 292081ad6265SDimitry Andric } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) { 292181ad6265SDimitry Andric KeepElseBraces = true; 292281ad6265SDimitry Andric assert(ElseLeftBrace->MatchingParen); 292381ad6265SDimitry Andric markOptionalBraces(ElseLeftBrace); 292481ad6265SDimitry Andric } 29250b57cec5SDimitry Andric addUnwrappedLine(); 292606c3fb27SDimitry Andric } else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) { 292781ad6265SDimitry Andric const FormatToken *Previous = Tokens->getPreviousToken(); 292881ad6265SDimitry Andric assert(Previous); 292981ad6265SDimitry Andric const bool IsPrecededByComment = Previous->is(tok::comment); 293004eeddc0SDimitry Andric if (IsPrecededByComment) { 2931fe6060f1SDimitry Andric addUnwrappedLine(); 2932fe6060f1SDimitry Andric ++Line->Level; 2933fe6060f1SDimitry Andric } 293404eeddc0SDimitry Andric bool TooDeep = true; 293504eeddc0SDimitry Andric if (Style.RemoveBracesLLVM) { 293604eeddc0SDimitry Andric Kind = IfStmtKind::IfElseIf; 293704eeddc0SDimitry Andric TooDeep = NestedTooDeep.pop_back_val(); 293804eeddc0SDimitry Andric } 293981ad6265SDimitry Andric ElseLeftBrace = parseIfThenElse(/*IfKind=*/nullptr, KeepIfBraces); 294004eeddc0SDimitry Andric if (Style.RemoveBracesLLVM) 294104eeddc0SDimitry Andric NestedTooDeep.push_back(TooDeep); 294204eeddc0SDimitry Andric if (IsPrecededByComment) 2943fe6060f1SDimitry Andric --Line->Level; 29440b57cec5SDimitry Andric } else { 294581ad6265SDimitry Andric parseUnbracedBody(/*CheckEOF=*/true); 29460b57cec5SDimitry Andric } 294704eeddc0SDimitry Andric } else { 294804eeddc0SDimitry Andric KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse; 294904eeddc0SDimitry Andric if (NeedsUnwrappedLine) 29500b57cec5SDimitry Andric addUnwrappedLine(); 29510b57cec5SDimitry Andric } 295204eeddc0SDimitry Andric 295304eeddc0SDimitry Andric if (!Style.RemoveBracesLLVM) 295404eeddc0SDimitry Andric return nullptr; 295504eeddc0SDimitry Andric 295604eeddc0SDimitry Andric assert(!NestedTooDeep.empty()); 295781ad6265SDimitry Andric KeepElseBraces = KeepElseBraces || 295881ad6265SDimitry Andric (ElseLeftBrace && !ElseLeftBrace->MatchingParen) || 295981ad6265SDimitry Andric NestedTooDeep.back(); 296004eeddc0SDimitry Andric 296104eeddc0SDimitry Andric NestedTooDeep.pop_back(); 296204eeddc0SDimitry Andric 296381ad6265SDimitry Andric if (!KeepIfBraces && !KeepElseBraces) { 296404eeddc0SDimitry Andric markOptionalBraces(IfLeftBrace); 296504eeddc0SDimitry Andric markOptionalBraces(ElseLeftBrace); 296604eeddc0SDimitry Andric } else if (IfLeftBrace) { 296704eeddc0SDimitry Andric FormatToken *IfRightBrace = IfLeftBrace->MatchingParen; 296804eeddc0SDimitry Andric if (IfRightBrace) { 296904eeddc0SDimitry Andric assert(IfRightBrace->MatchingParen == IfLeftBrace); 297004eeddc0SDimitry Andric assert(!IfLeftBrace->Optional); 297104eeddc0SDimitry Andric assert(!IfRightBrace->Optional); 297204eeddc0SDimitry Andric IfLeftBrace->MatchingParen = nullptr; 297304eeddc0SDimitry Andric IfRightBrace->MatchingParen = nullptr; 297404eeddc0SDimitry Andric } 297504eeddc0SDimitry Andric } 297604eeddc0SDimitry Andric 297704eeddc0SDimitry Andric if (IfKind) 297804eeddc0SDimitry Andric *IfKind = Kind; 297904eeddc0SDimitry Andric 298004eeddc0SDimitry Andric return IfLeftBrace; 29810b57cec5SDimitry Andric } 29820b57cec5SDimitry Andric 29830b57cec5SDimitry Andric void UnwrappedLineParser::parseTryCatch() { 29840b57cec5SDimitry Andric assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected"); 29850b57cec5SDimitry Andric nextToken(); 29860b57cec5SDimitry Andric bool NeedsUnwrappedLine = false; 29870fca6ea1SDimitry Andric bool HasCtorInitializer = false; 29880b57cec5SDimitry Andric if (FormatTok->is(tok::colon)) { 29890fca6ea1SDimitry Andric auto *Colon = FormatTok; 29900b57cec5SDimitry Andric // We are in a function try block, what comes is an initializer list. 29910b57cec5SDimitry Andric nextToken(); 29920fca6ea1SDimitry Andric if (FormatTok->is(tok::identifier)) { 29930fca6ea1SDimitry Andric HasCtorInitializer = true; 29940fca6ea1SDimitry Andric Colon->setFinalizedType(TT_CtorInitializerColon); 29950fca6ea1SDimitry Andric } 29965ffd83dbSDimitry Andric 29975ffd83dbSDimitry Andric // In case identifiers were removed by clang-tidy, what might follow is 29985ffd83dbSDimitry Andric // multiple commas in sequence - before the first identifier. 29995ffd83dbSDimitry Andric while (FormatTok->is(tok::comma)) 30005ffd83dbSDimitry Andric nextToken(); 30015ffd83dbSDimitry Andric 30020b57cec5SDimitry Andric while (FormatTok->is(tok::identifier)) { 30030b57cec5SDimitry Andric nextToken(); 30040fca6ea1SDimitry Andric if (FormatTok->is(tok::l_paren)) { 30050b57cec5SDimitry Andric parseParens(); 30060fca6ea1SDimitry Andric } else if (FormatTok->is(tok::l_brace)) { 3007e8d8bef9SDimitry Andric nextToken(); 30080fca6ea1SDimitry Andric parseBracedList(); 3009e8d8bef9SDimitry Andric } 30105ffd83dbSDimitry Andric 30115ffd83dbSDimitry Andric // In case identifiers were removed by clang-tidy, what might follow is 30125ffd83dbSDimitry Andric // multiple commas in sequence - after the first identifier. 30135ffd83dbSDimitry Andric while (FormatTok->is(tok::comma)) 30140b57cec5SDimitry Andric nextToken(); 30150b57cec5SDimitry Andric } 30160b57cec5SDimitry Andric } 30170b57cec5SDimitry Andric // Parse try with resource. 301881ad6265SDimitry Andric if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren)) 30190b57cec5SDimitry Andric parseParens(); 302004eeddc0SDimitry Andric 302104eeddc0SDimitry Andric keepAncestorBraces(); 302204eeddc0SDimitry Andric 30230b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 30240fca6ea1SDimitry Andric if (HasCtorInitializer) 30250fca6ea1SDimitry Andric FormatTok->setFinalizedType(TT_FunctionLBrace); 30260b57cec5SDimitry Andric CompoundStatementIndenter Indenter(this, Style, Line->Level); 3027349cc55cSDimitry Andric parseBlock(); 302881ad6265SDimitry Andric if (Style.BraceWrapping.BeforeCatch) 30290b57cec5SDimitry Andric addUnwrappedLine(); 303081ad6265SDimitry Andric else 30310b57cec5SDimitry Andric NeedsUnwrappedLine = true; 30325f757f3fSDimitry Andric } else if (FormatTok->isNot(tok::kw_catch)) { 30330b57cec5SDimitry Andric // The C++ standard requires a compound-statement after a try. 30340b57cec5SDimitry Andric // If there's none, we try to assume there's a structuralElement 30350b57cec5SDimitry Andric // and try to continue. 30360b57cec5SDimitry Andric addUnwrappedLine(); 30370b57cec5SDimitry Andric ++Line->Level; 30380b57cec5SDimitry Andric parseStructuralElement(); 30390b57cec5SDimitry Andric --Line->Level; 30400b57cec5SDimitry Andric } 304104eeddc0SDimitry Andric while (true) { 30420b57cec5SDimitry Andric if (FormatTok->is(tok::at)) 30430b57cec5SDimitry Andric nextToken(); 30440b57cec5SDimitry Andric if (!(FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except, 30450b57cec5SDimitry Andric tok::kw___finally) || 30460eae32dcSDimitry Andric ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && 30470b57cec5SDimitry Andric FormatTok->is(Keywords.kw_finally)) || 304881ad6265SDimitry Andric (FormatTok->isObjCAtKeyword(tok::objc_catch) || 304981ad6265SDimitry Andric FormatTok->isObjCAtKeyword(tok::objc_finally)))) { 30500b57cec5SDimitry Andric break; 305181ad6265SDimitry Andric } 30520b57cec5SDimitry Andric nextToken(); 30530b57cec5SDimitry Andric while (FormatTok->isNot(tok::l_brace)) { 30540b57cec5SDimitry Andric if (FormatTok->is(tok::l_paren)) { 30550b57cec5SDimitry Andric parseParens(); 30560b57cec5SDimitry Andric continue; 30570b57cec5SDimitry Andric } 305804eeddc0SDimitry Andric if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof)) { 305904eeddc0SDimitry Andric if (Style.RemoveBracesLLVM) 306004eeddc0SDimitry Andric NestedTooDeep.pop_back(); 30610b57cec5SDimitry Andric return; 306204eeddc0SDimitry Andric } 30630b57cec5SDimitry Andric nextToken(); 30640b57cec5SDimitry Andric } 30650b57cec5SDimitry Andric NeedsUnwrappedLine = false; 306681ad6265SDimitry Andric Line->MustBeDeclaration = false; 30670b57cec5SDimitry Andric CompoundStatementIndenter Indenter(this, Style, Line->Level); 3068349cc55cSDimitry Andric parseBlock(); 30690b57cec5SDimitry Andric if (Style.BraceWrapping.BeforeCatch) 30700b57cec5SDimitry Andric addUnwrappedLine(); 30710b57cec5SDimitry Andric else 30720b57cec5SDimitry Andric NeedsUnwrappedLine = true; 30730b57cec5SDimitry Andric } 307404eeddc0SDimitry Andric 307504eeddc0SDimitry Andric if (Style.RemoveBracesLLVM) 307604eeddc0SDimitry Andric NestedTooDeep.pop_back(); 307704eeddc0SDimitry Andric 30780b57cec5SDimitry Andric if (NeedsUnwrappedLine) 30790b57cec5SDimitry Andric addUnwrappedLine(); 30800b57cec5SDimitry Andric } 30810b57cec5SDimitry Andric 30820b57cec5SDimitry Andric void UnwrappedLineParser::parseNamespace() { 30830b57cec5SDimitry Andric assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) && 30840b57cec5SDimitry Andric "'namespace' expected"); 30850b57cec5SDimitry Andric 30860b57cec5SDimitry Andric const FormatToken &InitialToken = *FormatTok; 30870b57cec5SDimitry Andric nextToken(); 30880b57cec5SDimitry Andric if (InitialToken.is(TT_NamespaceMacro)) { 30890b57cec5SDimitry Andric parseParens(); 30900b57cec5SDimitry Andric } else { 3091a7dea167SDimitry Andric while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline, 309281ad6265SDimitry Andric tok::l_square, tok::period, tok::l_paren) || 309304eeddc0SDimitry Andric (Style.isCSharp() && FormatTok->is(tok::kw_union))) { 3094a7dea167SDimitry Andric if (FormatTok->is(tok::l_square)) 3095a7dea167SDimitry Andric parseSquare(); 309681ad6265SDimitry Andric else if (FormatTok->is(tok::l_paren)) 309781ad6265SDimitry Andric parseParens(); 3098a7dea167SDimitry Andric else 30990b57cec5SDimitry Andric nextToken(); 31000b57cec5SDimitry Andric } 3101a7dea167SDimitry Andric } 310281ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 31035f757f3fSDimitry Andric FormatTok->setFinalizedType(TT_NamespaceLBrace); 31045f757f3fSDimitry Andric 31050b57cec5SDimitry Andric if (ShouldBreakBeforeBrace(Style, InitialToken)) 31060b57cec5SDimitry Andric addUnwrappedLine(); 31070b57cec5SDimitry Andric 310823408297SDimitry Andric unsigned AddLevels = 310923408297SDimitry Andric Style.NamespaceIndentation == FormatStyle::NI_All || 31100b57cec5SDimitry Andric (Style.NamespaceIndentation == FormatStyle::NI_Inner && 311123408297SDimitry Andric DeclarationScopeStack.size() > 1) 311223408297SDimitry Andric ? 1u 311323408297SDimitry Andric : 0u; 311423408297SDimitry Andric bool ManageWhitesmithsBraces = 311523408297SDimitry Andric AddLevels == 0u && 311623408297SDimitry Andric Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; 311723408297SDimitry Andric 311823408297SDimitry Andric // If we're in Whitesmiths mode, indent the brace if we're not indenting 311923408297SDimitry Andric // the whole block. 312023408297SDimitry Andric if (ManageWhitesmithsBraces) 312123408297SDimitry Andric ++Line->Level; 312223408297SDimitry Andric 312306c3fb27SDimitry Andric // Munch the semicolon after a namespace. This is more common than one would 312406c3fb27SDimitry Andric // think. Putting the semicolon into its own line is very ugly. 312581ad6265SDimitry Andric parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true, 312681ad6265SDimitry Andric /*KeepBraces=*/true, /*IfKind=*/nullptr, 312781ad6265SDimitry Andric ManageWhitesmithsBraces); 312823408297SDimitry Andric 312923408297SDimitry Andric addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep); 313023408297SDimitry Andric 313123408297SDimitry Andric if (ManageWhitesmithsBraces) 313223408297SDimitry Andric --Line->Level; 31330b57cec5SDimitry Andric } 31340b57cec5SDimitry Andric // FIXME: Add error handling. 31350b57cec5SDimitry Andric } 31360b57cec5SDimitry Andric 31370b57cec5SDimitry Andric void UnwrappedLineParser::parseNew() { 31380b57cec5SDimitry Andric assert(FormatTok->is(tok::kw_new) && "'new' expected"); 31390b57cec5SDimitry Andric nextToken(); 31405ffd83dbSDimitry Andric 31415ffd83dbSDimitry Andric if (Style.isCSharp()) { 31425ffd83dbSDimitry Andric do { 3143bdd1243dSDimitry Andric // Handle constructor invocation, e.g. `new(field: value)`. 3144bdd1243dSDimitry Andric if (FormatTok->is(tok::l_paren)) 3145bdd1243dSDimitry Andric parseParens(); 3146bdd1243dSDimitry Andric 3147bdd1243dSDimitry Andric // Handle array initialization syntax, e.g. `new[] {10, 20, 30}`. 31485ffd83dbSDimitry Andric if (FormatTok->is(tok::l_brace)) 31495ffd83dbSDimitry Andric parseBracedList(); 31505ffd83dbSDimitry Andric 31515ffd83dbSDimitry Andric if (FormatTok->isOneOf(tok::semi, tok::comma)) 31525ffd83dbSDimitry Andric return; 31535ffd83dbSDimitry Andric 31545ffd83dbSDimitry Andric nextToken(); 31555ffd83dbSDimitry Andric } while (!eof()); 31565ffd83dbSDimitry Andric } 31575ffd83dbSDimitry Andric 31580b57cec5SDimitry Andric if (Style.Language != FormatStyle::LK_Java) 31590b57cec5SDimitry Andric return; 31600b57cec5SDimitry Andric 31610b57cec5SDimitry Andric // In Java, we can parse everything up to the parens, which aren't optional. 31620b57cec5SDimitry Andric do { 31630b57cec5SDimitry Andric // There should not be a ;, { or } before the new's open paren. 31640b57cec5SDimitry Andric if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace)) 31650b57cec5SDimitry Andric return; 31660b57cec5SDimitry Andric 31670b57cec5SDimitry Andric // Consume the parens. 31680b57cec5SDimitry Andric if (FormatTok->is(tok::l_paren)) { 31690b57cec5SDimitry Andric parseParens(); 31700b57cec5SDimitry Andric 31710b57cec5SDimitry Andric // If there is a class body of an anonymous class, consume that as child. 31720b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) 31730b57cec5SDimitry Andric parseChildBlock(); 31740b57cec5SDimitry Andric return; 31750b57cec5SDimitry Andric } 31760b57cec5SDimitry Andric nextToken(); 31770b57cec5SDimitry Andric } while (!eof()); 31780b57cec5SDimitry Andric } 31790b57cec5SDimitry Andric 318081ad6265SDimitry Andric void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) { 318181ad6265SDimitry Andric keepAncestorBraces(); 318281ad6265SDimitry Andric 3183bdd1243dSDimitry Andric if (isBlockBegin(*FormatTok)) { 318481ad6265SDimitry Andric FormatTok->setFinalizedType(TT_ControlStatementLBrace); 318581ad6265SDimitry Andric FormatToken *LeftBrace = FormatTok; 318681ad6265SDimitry Andric CompoundStatementIndenter Indenter(this, Style, Line->Level); 318781ad6265SDimitry Andric parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, 318881ad6265SDimitry Andric /*MunchSemi=*/true, KeepBraces); 31895f757f3fSDimitry Andric setPreviousRBraceType(TT_ControlStatementRBrace); 319081ad6265SDimitry Andric if (!KeepBraces) { 319181ad6265SDimitry Andric assert(!NestedTooDeep.empty()); 319281ad6265SDimitry Andric if (!NestedTooDeep.back()) 319381ad6265SDimitry Andric markOptionalBraces(LeftBrace); 319481ad6265SDimitry Andric } 319581ad6265SDimitry Andric if (WrapRightBrace) 319681ad6265SDimitry Andric addUnwrappedLine(); 319781ad6265SDimitry Andric } else { 319881ad6265SDimitry Andric parseUnbracedBody(); 319981ad6265SDimitry Andric } 320081ad6265SDimitry Andric 320181ad6265SDimitry Andric if (!KeepBraces) 320281ad6265SDimitry Andric NestedTooDeep.pop_back(); 320381ad6265SDimitry Andric } 320481ad6265SDimitry Andric 320506c3fb27SDimitry Andric void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) { 320606c3fb27SDimitry Andric assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) || 320706c3fb27SDimitry Andric (Style.isVerilog() && 320806c3fb27SDimitry Andric FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb, 320906c3fb27SDimitry Andric Keywords.kw_always_ff, Keywords.kw_always_latch, 321006c3fb27SDimitry Andric Keywords.kw_final, Keywords.kw_initial, 321106c3fb27SDimitry Andric Keywords.kw_foreach, Keywords.kw_forever, 321206c3fb27SDimitry Andric Keywords.kw_repeat))) && 32130b57cec5SDimitry Andric "'for', 'while' or foreach macro expected"); 321481ad6265SDimitry Andric const bool KeepBraces = !Style.RemoveBracesLLVM || 321581ad6265SDimitry Andric !FormatTok->isOneOf(tok::kw_for, tok::kw_while); 321681ad6265SDimitry Andric 32170b57cec5SDimitry Andric nextToken(); 32180b57cec5SDimitry Andric // JS' for await ( ... 32190eae32dcSDimitry Andric if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await)) 32200b57cec5SDimitry Andric nextToken(); 32210fca6ea1SDimitry Andric if (IsCpp && FormatTok->is(tok::kw_co_await)) 32224824e7fdSDimitry Andric nextToken(); 322306c3fb27SDimitry Andric if (HasParens && FormatTok->is(tok::l_paren)) { 322406c3fb27SDimitry Andric // The type is only set for Verilog basically because we were afraid to 322506c3fb27SDimitry Andric // change the existing behavior for loops. See the discussion on D121756 for 322606c3fb27SDimitry Andric // details. 322706c3fb27SDimitry Andric if (Style.isVerilog()) 322806c3fb27SDimitry Andric FormatTok->setFinalizedType(TT_ConditionLParen); 32290b57cec5SDimitry Andric parseParens(); 323006c3fb27SDimitry Andric } 32315f757f3fSDimitry Andric 32325f757f3fSDimitry Andric if (Style.isVerilog()) { 323306c3fb27SDimitry Andric // Event control. 323406c3fb27SDimitry Andric parseVerilogSensitivityList(); 32355f757f3fSDimitry Andric } else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) && 32365f757f3fSDimitry Andric Tokens->getPreviousToken()->is(tok::r_paren)) { 32375f757f3fSDimitry Andric nextToken(); 32385f757f3fSDimitry Andric addUnwrappedLine(); 32395f757f3fSDimitry Andric return; 32405f757f3fSDimitry Andric } 324104eeddc0SDimitry Andric 324281ad6265SDimitry Andric handleAttributes(); 324381ad6265SDimitry Andric parseLoopBody(KeepBraces, /*WrapRightBrace=*/true); 32440b57cec5SDimitry Andric } 32450b57cec5SDimitry Andric 32460b57cec5SDimitry Andric void UnwrappedLineParser::parseDoWhile() { 324781ad6265SDimitry Andric assert(FormatTok->is(tok::kw_do) && "'do' expected"); 32480b57cec5SDimitry Andric nextToken(); 324904eeddc0SDimitry Andric 325081ad6265SDimitry Andric parseLoopBody(/*KeepBraces=*/true, Style.BraceWrapping.BeforeWhile); 325104eeddc0SDimitry Andric 32520b57cec5SDimitry Andric // FIXME: Add error handling. 32535f757f3fSDimitry Andric if (FormatTok->isNot(tok::kw_while)) { 32540b57cec5SDimitry Andric addUnwrappedLine(); 32550b57cec5SDimitry Andric return; 32560b57cec5SDimitry Andric } 32570b57cec5SDimitry Andric 32585f757f3fSDimitry Andric FormatTok->setFinalizedType(TT_DoWhile); 32595f757f3fSDimitry Andric 326023408297SDimitry Andric // If in Whitesmiths mode, the line with the while() needs to be indented 326123408297SDimitry Andric // to the same level as the block. 326223408297SDimitry Andric if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) 326323408297SDimitry Andric ++Line->Level; 326423408297SDimitry Andric 32650b57cec5SDimitry Andric nextToken(); 32660b57cec5SDimitry Andric parseStructuralElement(); 32670b57cec5SDimitry Andric } 32680b57cec5SDimitry Andric 3269a7dea167SDimitry Andric void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) { 32700b57cec5SDimitry Andric nextToken(); 32710b57cec5SDimitry Andric unsigned OldLineLevel = Line->Level; 32720fca6ea1SDimitry Andric 3273a7dea167SDimitry Andric if (LeftAlignLabel) 3274a7dea167SDimitry Andric Line->Level = 0; 32750fca6ea1SDimitry Andric else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0)) 32760fca6ea1SDimitry Andric --Line->Level; 3277e8d8bef9SDimitry Andric 32785ffd83dbSDimitry Andric if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() && 327981ad6265SDimitry Andric FormatTok->is(tok::l_brace)) { 3280e8d8bef9SDimitry Andric 328123408297SDimitry Andric CompoundStatementIndenter Indenter(this, Line->Level, 328223408297SDimitry Andric Style.BraceWrapping.AfterCaseLabel, 328323408297SDimitry Andric Style.BraceWrapping.IndentBraces); 3284349cc55cSDimitry Andric parseBlock(); 328581ad6265SDimitry Andric if (FormatTok->is(tok::kw_break)) { 3286a7dea167SDimitry Andric if (Style.BraceWrapping.AfterControlStatement == 32875ffd83dbSDimitry Andric FormatStyle::BWACS_Always) { 32880b57cec5SDimitry Andric addUnwrappedLine(); 328923408297SDimitry Andric if (!Style.IndentCaseBlocks && 329023408297SDimitry Andric Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) { 329104eeddc0SDimitry Andric ++Line->Level; 32925ffd83dbSDimitry Andric } 32935ffd83dbSDimitry Andric } 32940b57cec5SDimitry Andric parseStructuralElement(); 32950b57cec5SDimitry Andric } 32960b57cec5SDimitry Andric addUnwrappedLine(); 32970b57cec5SDimitry Andric } else { 32980b57cec5SDimitry Andric if (FormatTok->is(tok::semi)) 32990b57cec5SDimitry Andric nextToken(); 33000b57cec5SDimitry Andric addUnwrappedLine(); 33010b57cec5SDimitry Andric } 33020b57cec5SDimitry Andric Line->Level = OldLineLevel; 33030b57cec5SDimitry Andric if (FormatTok->isNot(tok::l_brace)) { 33040b57cec5SDimitry Andric parseStructuralElement(); 33050b57cec5SDimitry Andric addUnwrappedLine(); 33060b57cec5SDimitry Andric } 33070b57cec5SDimitry Andric } 33080b57cec5SDimitry Andric 33090b57cec5SDimitry Andric void UnwrappedLineParser::parseCaseLabel() { 331081ad6265SDimitry Andric assert(FormatTok->is(tok::kw_case) && "'case' expected"); 33110fca6ea1SDimitry Andric auto *Case = FormatTok; 3312e8d8bef9SDimitry Andric 33130b57cec5SDimitry Andric // FIXME: fix handling of complex expressions here. 33140b57cec5SDimitry Andric do { 33150b57cec5SDimitry Andric nextToken(); 331606c3fb27SDimitry Andric if (FormatTok->is(tok::colon)) { 331706c3fb27SDimitry Andric FormatTok->setFinalizedType(TT_CaseLabelColon); 331806c3fb27SDimitry Andric break; 331906c3fb27SDimitry Andric } 33200fca6ea1SDimitry Andric if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::arrow)) { 33210fca6ea1SDimitry Andric FormatTok->setFinalizedType(TT_CaseLabelArrow); 33220fca6ea1SDimitry Andric Case->setFinalizedType(TT_SwitchExpressionLabel); 33230fca6ea1SDimitry Andric break; 33240fca6ea1SDimitry Andric } 332506c3fb27SDimitry Andric } while (!eof()); 33260b57cec5SDimitry Andric parseLabel(); 33270b57cec5SDimitry Andric } 33280b57cec5SDimitry Andric 33290fca6ea1SDimitry Andric void UnwrappedLineParser::parseSwitch(bool IsExpr) { 333081ad6265SDimitry Andric assert(FormatTok->is(tok::kw_switch) && "'switch' expected"); 33310b57cec5SDimitry Andric nextToken(); 333281ad6265SDimitry Andric if (FormatTok->is(tok::l_paren)) 33330b57cec5SDimitry Andric parseParens(); 333404eeddc0SDimitry Andric 333504eeddc0SDimitry Andric keepAncestorBraces(); 333604eeddc0SDimitry Andric 333781ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 33380b57cec5SDimitry Andric CompoundStatementIndenter Indenter(this, Style, Line->Level); 33390fca6ea1SDimitry Andric FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace 33400fca6ea1SDimitry Andric : TT_ControlStatementLBrace); 33410fca6ea1SDimitry Andric if (IsExpr) 33420fca6ea1SDimitry Andric parseChildBlock(); 33430fca6ea1SDimitry Andric else 3344349cc55cSDimitry Andric parseBlock(); 33455f757f3fSDimitry Andric setPreviousRBraceType(TT_ControlStatementRBrace); 33460fca6ea1SDimitry Andric if (!IsExpr) 33470b57cec5SDimitry Andric addUnwrappedLine(); 33480b57cec5SDimitry Andric } else { 33490b57cec5SDimitry Andric addUnwrappedLine(); 33500b57cec5SDimitry Andric ++Line->Level; 33510b57cec5SDimitry Andric parseStructuralElement(); 33520b57cec5SDimitry Andric --Line->Level; 33530b57cec5SDimitry Andric } 335404eeddc0SDimitry Andric 335504eeddc0SDimitry Andric if (Style.RemoveBracesLLVM) 335604eeddc0SDimitry Andric NestedTooDeep.pop_back(); 33570b57cec5SDimitry Andric } 33580b57cec5SDimitry Andric 335981ad6265SDimitry Andric // Operators that can follow a C variable. 33600fca6ea1SDimitry Andric static bool isCOperatorFollowingVar(tok::TokenKind Kind) { 33610fca6ea1SDimitry Andric switch (Kind) { 336281ad6265SDimitry Andric case tok::ampamp: 336381ad6265SDimitry Andric case tok::ampequal: 336481ad6265SDimitry Andric case tok::arrow: 336581ad6265SDimitry Andric case tok::caret: 336681ad6265SDimitry Andric case tok::caretequal: 336781ad6265SDimitry Andric case tok::comma: 336881ad6265SDimitry Andric case tok::ellipsis: 336981ad6265SDimitry Andric case tok::equal: 337081ad6265SDimitry Andric case tok::equalequal: 337181ad6265SDimitry Andric case tok::exclaim: 337281ad6265SDimitry Andric case tok::exclaimequal: 337381ad6265SDimitry Andric case tok::greater: 337481ad6265SDimitry Andric case tok::greaterequal: 337581ad6265SDimitry Andric case tok::greatergreater: 337681ad6265SDimitry Andric case tok::greatergreaterequal: 337781ad6265SDimitry Andric case tok::l_paren: 337881ad6265SDimitry Andric case tok::l_square: 337981ad6265SDimitry Andric case tok::less: 338081ad6265SDimitry Andric case tok::lessequal: 338181ad6265SDimitry Andric case tok::lessless: 338281ad6265SDimitry Andric case tok::lesslessequal: 338381ad6265SDimitry Andric case tok::minus: 338481ad6265SDimitry Andric case tok::minusequal: 338581ad6265SDimitry Andric case tok::minusminus: 338681ad6265SDimitry Andric case tok::percent: 338781ad6265SDimitry Andric case tok::percentequal: 338881ad6265SDimitry Andric case tok::period: 338981ad6265SDimitry Andric case tok::pipe: 339081ad6265SDimitry Andric case tok::pipeequal: 339181ad6265SDimitry Andric case tok::pipepipe: 339281ad6265SDimitry Andric case tok::plus: 339381ad6265SDimitry Andric case tok::plusequal: 339481ad6265SDimitry Andric case tok::plusplus: 339581ad6265SDimitry Andric case tok::question: 339681ad6265SDimitry Andric case tok::r_brace: 339781ad6265SDimitry Andric case tok::r_paren: 339881ad6265SDimitry Andric case tok::r_square: 339981ad6265SDimitry Andric case tok::semi: 340081ad6265SDimitry Andric case tok::slash: 340181ad6265SDimitry Andric case tok::slashequal: 340281ad6265SDimitry Andric case tok::star: 340381ad6265SDimitry Andric case tok::starequal: 340481ad6265SDimitry Andric return true; 340581ad6265SDimitry Andric default: 340681ad6265SDimitry Andric return false; 340781ad6265SDimitry Andric } 340881ad6265SDimitry Andric } 340981ad6265SDimitry Andric 34100b57cec5SDimitry Andric void UnwrappedLineParser::parseAccessSpecifier() { 34111fd87a68SDimitry Andric FormatToken *AccessSpecifierCandidate = FormatTok; 34120b57cec5SDimitry Andric nextToken(); 34130b57cec5SDimitry Andric // Understand Qt's slots. 34140b57cec5SDimitry Andric if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots)) 34150b57cec5SDimitry Andric nextToken(); 34160b57cec5SDimitry Andric // Otherwise, we don't know what it is, and we'd better keep the next token. 341781ad6265SDimitry Andric if (FormatTok->is(tok::colon)) { 34180b57cec5SDimitry Andric nextToken(); 34190b57cec5SDimitry Andric addUnwrappedLine(); 34205f757f3fSDimitry Andric } else if (FormatTok->isNot(tok::coloncolon) && 342181ad6265SDimitry Andric !isCOperatorFollowingVar(FormatTok->Tok.getKind())) { 34221fd87a68SDimitry Andric // Not a variable name nor namespace name. 34231fd87a68SDimitry Andric addUnwrappedLine(); 34241fd87a68SDimitry Andric } else if (AccessSpecifierCandidate) { 34251fd87a68SDimitry Andric // Consider the access specifier to be a C identifier. 34261fd87a68SDimitry Andric AccessSpecifierCandidate->Tok.setKind(tok::identifier); 34271fd87a68SDimitry Andric } 34280b57cec5SDimitry Andric } 34290b57cec5SDimitry Andric 343081ad6265SDimitry Andric /// \brief Parses a requires, decides if it is a clause or an expression. 343181ad6265SDimitry Andric /// \pre The current token has to be the requires keyword. 343281ad6265SDimitry Andric /// \returns true if it parsed a clause. 34330fca6ea1SDimitry Andric bool UnwrappedLineParser::parseRequires() { 343481ad6265SDimitry Andric assert(FormatTok->is(tok::kw_requires) && "'requires' expected"); 343581ad6265SDimitry Andric auto RequiresToken = FormatTok; 343681ad6265SDimitry Andric 343781ad6265SDimitry Andric // We try to guess if it is a requires clause, or a requires expression. For 343881ad6265SDimitry Andric // that we first consume the keyword and check the next token. 343981ad6265SDimitry Andric nextToken(); 344081ad6265SDimitry Andric 344181ad6265SDimitry Andric switch (FormatTok->Tok.getKind()) { 344281ad6265SDimitry Andric case tok::l_brace: 344381ad6265SDimitry Andric // This can only be an expression, never a clause. 344481ad6265SDimitry Andric parseRequiresExpression(RequiresToken); 344581ad6265SDimitry Andric return false; 344681ad6265SDimitry Andric case tok::l_paren: 344781ad6265SDimitry Andric // Clauses and expression can start with a paren, it's unclear what we have. 344881ad6265SDimitry Andric break; 344981ad6265SDimitry Andric default: 345081ad6265SDimitry Andric // All other tokens can only be a clause. 345181ad6265SDimitry Andric parseRequiresClause(RequiresToken); 345281ad6265SDimitry Andric return true; 3453e8d8bef9SDimitry Andric } 345481ad6265SDimitry Andric 345581ad6265SDimitry Andric // Looking forward we would have to decide if there are function declaration 345681ad6265SDimitry Andric // like arguments to the requires expression: 345781ad6265SDimitry Andric // requires (T t) { 345881ad6265SDimitry Andric // Or there is a constraint expression for the requires clause: 345981ad6265SDimitry Andric // requires (C<T> && ... 346081ad6265SDimitry Andric 346181ad6265SDimitry Andric // But first let's look behind. 346281ad6265SDimitry Andric auto *PreviousNonComment = RequiresToken->getPreviousNonComment(); 346381ad6265SDimitry Andric 346481ad6265SDimitry Andric if (!PreviousNonComment || 346581ad6265SDimitry Andric PreviousNonComment->is(TT_RequiresExpressionLBrace)) { 346681ad6265SDimitry Andric // If there is no token, or an expression left brace, we are a requires 346781ad6265SDimitry Andric // clause within a requires expression. 346881ad6265SDimitry Andric parseRequiresClause(RequiresToken); 346981ad6265SDimitry Andric return true; 3470e8d8bef9SDimitry Andric } 347181ad6265SDimitry Andric 347281ad6265SDimitry Andric switch (PreviousNonComment->Tok.getKind()) { 347381ad6265SDimitry Andric case tok::greater: 347481ad6265SDimitry Andric case tok::r_paren: 347581ad6265SDimitry Andric case tok::kw_noexcept: 347681ad6265SDimitry Andric case tok::kw_const: 347781ad6265SDimitry Andric // This is a requires clause. 347881ad6265SDimitry Andric parseRequiresClause(RequiresToken); 347981ad6265SDimitry Andric return true; 348081ad6265SDimitry Andric case tok::amp: 348181ad6265SDimitry Andric case tok::ampamp: { 348281ad6265SDimitry Andric // This can be either: 348381ad6265SDimitry Andric // if (... && requires (T t) ...) 348481ad6265SDimitry Andric // Or 348581ad6265SDimitry Andric // void member(...) && requires (C<T> ... 348681ad6265SDimitry Andric // We check the one token before that for a const: 348781ad6265SDimitry Andric // void member(...) const && requires (C<T> ... 348881ad6265SDimitry Andric auto PrevPrev = PreviousNonComment->getPreviousNonComment(); 348981ad6265SDimitry Andric if (PrevPrev && PrevPrev->is(tok::kw_const)) { 349081ad6265SDimitry Andric parseRequiresClause(RequiresToken); 349181ad6265SDimitry Andric return true; 3492e8d8bef9SDimitry Andric } 3493e8d8bef9SDimitry Andric break; 3494e8d8bef9SDimitry Andric } 349581ad6265SDimitry Andric default: 34960fca6ea1SDimitry Andric if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) { 349781ad6265SDimitry Andric // This is a requires clause. 349881ad6265SDimitry Andric parseRequiresClause(RequiresToken); 349981ad6265SDimitry Andric return true; 350081ad6265SDimitry Andric } 350181ad6265SDimitry Andric // It's an expression. 350281ad6265SDimitry Andric parseRequiresExpression(RequiresToken); 350381ad6265SDimitry Andric return false; 350481ad6265SDimitry Andric } 350581ad6265SDimitry Andric 350681ad6265SDimitry Andric // Now we look forward and try to check if the paren content is a parameter 350781ad6265SDimitry Andric // list. The parameters can be cv-qualified and contain references or 350881ad6265SDimitry Andric // pointers. 350981ad6265SDimitry Andric // So we want basically to check for TYPE NAME, but TYPE can contain all kinds 351081ad6265SDimitry Andric // of stuff: typename, const, *, &, &&, ::, identifiers. 351181ad6265SDimitry Andric 3512bdd1243dSDimitry Andric unsigned StoredPosition = Tokens->getPosition(); 3513bdd1243dSDimitry Andric FormatToken *NextToken = Tokens->getNextToken(); 3514bdd1243dSDimitry Andric int Lookahead = 0; 3515bdd1243dSDimitry Andric auto PeekNext = [&Lookahead, &NextToken, this] { 3516bdd1243dSDimitry Andric ++Lookahead; 3517bdd1243dSDimitry Andric NextToken = Tokens->getNextToken(); 351881ad6265SDimitry Andric }; 351981ad6265SDimitry Andric 352081ad6265SDimitry Andric bool FoundType = false; 352181ad6265SDimitry Andric bool LastWasColonColon = false; 352281ad6265SDimitry Andric int OpenAngles = 0; 352381ad6265SDimitry Andric 3524bdd1243dSDimitry Andric for (; Lookahead < 50; PeekNext()) { 352581ad6265SDimitry Andric switch (NextToken->Tok.getKind()) { 352681ad6265SDimitry Andric case tok::kw_volatile: 352781ad6265SDimitry Andric case tok::kw_const: 352881ad6265SDimitry Andric case tok::comma: 35295f757f3fSDimitry Andric if (OpenAngles == 0) { 3530bdd1243dSDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 353181ad6265SDimitry Andric parseRequiresExpression(RequiresToken); 353281ad6265SDimitry Andric return false; 35335f757f3fSDimitry Andric } 35345f757f3fSDimitry Andric break; 353581ad6265SDimitry Andric case tok::eof: 353681ad6265SDimitry Andric // Break out of the loop. 3537bdd1243dSDimitry Andric Lookahead = 50; 353881ad6265SDimitry Andric break; 353981ad6265SDimitry Andric case tok::coloncolon: 354081ad6265SDimitry Andric LastWasColonColon = true; 354181ad6265SDimitry Andric break; 35420fca6ea1SDimitry Andric case tok::kw_decltype: 354381ad6265SDimitry Andric case tok::identifier: 354481ad6265SDimitry Andric if (FoundType && !LastWasColonColon && OpenAngles == 0) { 3545bdd1243dSDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 354681ad6265SDimitry Andric parseRequiresExpression(RequiresToken); 354781ad6265SDimitry Andric return false; 354881ad6265SDimitry Andric } 354981ad6265SDimitry Andric FoundType = true; 355081ad6265SDimitry Andric LastWasColonColon = false; 355181ad6265SDimitry Andric break; 355281ad6265SDimitry Andric case tok::less: 355381ad6265SDimitry Andric ++OpenAngles; 355481ad6265SDimitry Andric break; 355581ad6265SDimitry Andric case tok::greater: 355681ad6265SDimitry Andric --OpenAngles; 355781ad6265SDimitry Andric break; 355881ad6265SDimitry Andric default: 35590fca6ea1SDimitry Andric if (NextToken->isTypeName(LangOpts)) { 3560bdd1243dSDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 356181ad6265SDimitry Andric parseRequiresExpression(RequiresToken); 356281ad6265SDimitry Andric return false; 356381ad6265SDimitry Andric } 356481ad6265SDimitry Andric break; 356581ad6265SDimitry Andric } 356681ad6265SDimitry Andric } 356781ad6265SDimitry Andric // This seems to be a complicated expression, just assume it's a clause. 3568bdd1243dSDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 356981ad6265SDimitry Andric parseRequiresClause(RequiresToken); 357081ad6265SDimitry Andric return true; 357181ad6265SDimitry Andric } 357281ad6265SDimitry Andric 357381ad6265SDimitry Andric /// \brief Parses a requires clause. 357481ad6265SDimitry Andric /// \param RequiresToken The requires keyword token, which starts this clause. 357581ad6265SDimitry Andric /// \pre We need to be on the next token after the requires keyword. 357681ad6265SDimitry Andric /// \sa parseRequiresExpression 357781ad6265SDimitry Andric /// 357881ad6265SDimitry Andric /// Returns if it either has finished parsing the clause, or it detects, that 357981ad6265SDimitry Andric /// the clause is incorrect. 358081ad6265SDimitry Andric void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) { 358181ad6265SDimitry Andric assert(FormatTok->getPreviousNonComment() == RequiresToken); 358281ad6265SDimitry Andric assert(RequiresToken->is(tok::kw_requires) && "'requires' expected"); 358381ad6265SDimitry Andric 358481ad6265SDimitry Andric // If there is no previous token, we are within a requires expression, 358581ad6265SDimitry Andric // otherwise we will always have the template or function declaration in front 358681ad6265SDimitry Andric // of it. 358781ad6265SDimitry Andric bool InRequiresExpression = 358881ad6265SDimitry Andric !RequiresToken->Previous || 358981ad6265SDimitry Andric RequiresToken->Previous->is(TT_RequiresExpressionLBrace); 359081ad6265SDimitry Andric 359181ad6265SDimitry Andric RequiresToken->setFinalizedType(InRequiresExpression 359281ad6265SDimitry Andric ? TT_RequiresClauseInARequiresExpression 359381ad6265SDimitry Andric : TT_RequiresClause); 359481ad6265SDimitry Andric 3595bdd1243dSDimitry Andric // NOTE: parseConstraintExpression is only ever called from this function. 3596bdd1243dSDimitry Andric // It could be inlined into here. 359781ad6265SDimitry Andric parseConstraintExpression(); 359881ad6265SDimitry Andric 359981ad6265SDimitry Andric if (!InRequiresExpression) 360081ad6265SDimitry Andric FormatTok->Previous->ClosesRequiresClause = true; 360181ad6265SDimitry Andric } 360281ad6265SDimitry Andric 360381ad6265SDimitry Andric /// \brief Parses a requires expression. 360481ad6265SDimitry Andric /// \param RequiresToken The requires keyword token, which starts this clause. 360581ad6265SDimitry Andric /// \pre We need to be on the next token after the requires keyword. 360681ad6265SDimitry Andric /// \sa parseRequiresClause 360781ad6265SDimitry Andric /// 360881ad6265SDimitry Andric /// Returns if it either has finished parsing the expression, or it detects, 360981ad6265SDimitry Andric /// that the expression is incorrect. 361081ad6265SDimitry Andric void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) { 361181ad6265SDimitry Andric assert(FormatTok->getPreviousNonComment() == RequiresToken); 361281ad6265SDimitry Andric assert(RequiresToken->is(tok::kw_requires) && "'requires' expected"); 361381ad6265SDimitry Andric 361481ad6265SDimitry Andric RequiresToken->setFinalizedType(TT_RequiresExpression); 361581ad6265SDimitry Andric 361681ad6265SDimitry Andric if (FormatTok->is(tok::l_paren)) { 361781ad6265SDimitry Andric FormatTok->setFinalizedType(TT_RequiresExpressionLParen); 361881ad6265SDimitry Andric parseParens(); 361981ad6265SDimitry Andric } 362081ad6265SDimitry Andric 362181ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 362281ad6265SDimitry Andric FormatTok->setFinalizedType(TT_RequiresExpressionLBrace); 36235f757f3fSDimitry Andric parseChildBlock(); 362481ad6265SDimitry Andric } 362581ad6265SDimitry Andric } 362681ad6265SDimitry Andric 362781ad6265SDimitry Andric /// \brief Parses a constraint expression. 362881ad6265SDimitry Andric /// 3629bdd1243dSDimitry Andric /// This is the body of a requires clause. It returns, when the parsing is 3630bdd1243dSDimitry Andric /// complete, or the expression is incorrect. 363181ad6265SDimitry Andric void UnwrappedLineParser::parseConstraintExpression() { 363281ad6265SDimitry Andric // The special handling for lambdas is needed since tryToParseLambda() eats a 363381ad6265SDimitry Andric // token and if a requires expression is the last part of a requires clause 363481ad6265SDimitry Andric // and followed by an attribute like [[nodiscard]] the ClosesRequiresClause is 363581ad6265SDimitry Andric // not set on the correct token. Thus we need to be aware if we even expect a 363681ad6265SDimitry Andric // lambda to be possible. 363781ad6265SDimitry Andric // template <typename T> requires requires { ... } [[nodiscard]] ...; 363881ad6265SDimitry Andric bool LambdaNextTimeAllowed = true; 363906c3fb27SDimitry Andric 364006c3fb27SDimitry Andric // Within lambda declarations, it is permitted to put a requires clause after 364106c3fb27SDimitry Andric // its template parameter list, which would place the requires clause right 364206c3fb27SDimitry Andric // before the parentheses of the parameters of the lambda declaration. Thus, 364306c3fb27SDimitry Andric // we track if we expect to see grouping parentheses at all. 364406c3fb27SDimitry Andric // Without this check, `requires foo<T> (T t)` in the below example would be 364506c3fb27SDimitry Andric // seen as the whole requires clause, accidentally eating the parameters of 364606c3fb27SDimitry Andric // the lambda. 364706c3fb27SDimitry Andric // [&]<typename T> requires foo<T> (T t) { ... }; 364806c3fb27SDimitry Andric bool TopLevelParensAllowed = true; 364906c3fb27SDimitry Andric 365081ad6265SDimitry Andric do { 365181ad6265SDimitry Andric bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false); 365281ad6265SDimitry Andric 365381ad6265SDimitry Andric switch (FormatTok->Tok.getKind()) { 365481ad6265SDimitry Andric case tok::kw_requires: { 365581ad6265SDimitry Andric auto RequiresToken = FormatTok; 365681ad6265SDimitry Andric nextToken(); 365781ad6265SDimitry Andric parseRequiresExpression(RequiresToken); 365881ad6265SDimitry Andric break; 365981ad6265SDimitry Andric } 366081ad6265SDimitry Andric 366181ad6265SDimitry Andric case tok::l_paren: 366206c3fb27SDimitry Andric if (!TopLevelParensAllowed) 366306c3fb27SDimitry Andric return; 366481ad6265SDimitry Andric parseParens(/*AmpAmpTokenType=*/TT_BinaryOperator); 366506c3fb27SDimitry Andric TopLevelParensAllowed = false; 366681ad6265SDimitry Andric break; 366781ad6265SDimitry Andric 366881ad6265SDimitry Andric case tok::l_square: 366981ad6265SDimitry Andric if (!LambdaThisTimeAllowed || !tryToParseLambda()) 367081ad6265SDimitry Andric return; 367181ad6265SDimitry Andric break; 367281ad6265SDimitry Andric 367381ad6265SDimitry Andric case tok::kw_const: 367481ad6265SDimitry Andric case tok::semi: 367581ad6265SDimitry Andric case tok::kw_class: 367681ad6265SDimitry Andric case tok::kw_struct: 367781ad6265SDimitry Andric case tok::kw_union: 367881ad6265SDimitry Andric return; 367981ad6265SDimitry Andric 368081ad6265SDimitry Andric case tok::l_brace: 368181ad6265SDimitry Andric // Potential function body. 368281ad6265SDimitry Andric return; 368381ad6265SDimitry Andric 368481ad6265SDimitry Andric case tok::ampamp: 368581ad6265SDimitry Andric case tok::pipepipe: 368681ad6265SDimitry Andric FormatTok->setFinalizedType(TT_BinaryOperator); 368781ad6265SDimitry Andric nextToken(); 368881ad6265SDimitry Andric LambdaNextTimeAllowed = true; 368906c3fb27SDimitry Andric TopLevelParensAllowed = true; 369081ad6265SDimitry Andric break; 369181ad6265SDimitry Andric 369281ad6265SDimitry Andric case tok::comma: 369381ad6265SDimitry Andric case tok::comment: 369481ad6265SDimitry Andric LambdaNextTimeAllowed = LambdaThisTimeAllowed; 369581ad6265SDimitry Andric nextToken(); 369681ad6265SDimitry Andric break; 369781ad6265SDimitry Andric 369881ad6265SDimitry Andric case tok::kw_sizeof: 369981ad6265SDimitry Andric case tok::greater: 370081ad6265SDimitry Andric case tok::greaterequal: 370181ad6265SDimitry Andric case tok::greatergreater: 370281ad6265SDimitry Andric case tok::less: 370381ad6265SDimitry Andric case tok::lessequal: 370481ad6265SDimitry Andric case tok::lessless: 370581ad6265SDimitry Andric case tok::equalequal: 370681ad6265SDimitry Andric case tok::exclaim: 370781ad6265SDimitry Andric case tok::exclaimequal: 370881ad6265SDimitry Andric case tok::plus: 370981ad6265SDimitry Andric case tok::minus: 371081ad6265SDimitry Andric case tok::star: 371181ad6265SDimitry Andric case tok::slash: 371281ad6265SDimitry Andric LambdaNextTimeAllowed = true; 371306c3fb27SDimitry Andric TopLevelParensAllowed = true; 371481ad6265SDimitry Andric // Just eat them. 371581ad6265SDimitry Andric nextToken(); 371681ad6265SDimitry Andric break; 371781ad6265SDimitry Andric 371881ad6265SDimitry Andric case tok::numeric_constant: 371981ad6265SDimitry Andric case tok::coloncolon: 372081ad6265SDimitry Andric case tok::kw_true: 372181ad6265SDimitry Andric case tok::kw_false: 372206c3fb27SDimitry Andric TopLevelParensAllowed = false; 372381ad6265SDimitry Andric // Just eat them. 372481ad6265SDimitry Andric nextToken(); 372581ad6265SDimitry Andric break; 372681ad6265SDimitry Andric 372781ad6265SDimitry Andric case tok::kw_static_cast: 372881ad6265SDimitry Andric case tok::kw_const_cast: 372981ad6265SDimitry Andric case tok::kw_reinterpret_cast: 373081ad6265SDimitry Andric case tok::kw_dynamic_cast: 373181ad6265SDimitry Andric nextToken(); 37325f757f3fSDimitry Andric if (FormatTok->isNot(tok::less)) 373381ad6265SDimitry Andric return; 3734e8d8bef9SDimitry Andric 3735e8d8bef9SDimitry Andric nextToken(); 37365f757f3fSDimitry Andric parseBracedList(/*IsAngleBracket=*/true); 373781ad6265SDimitry Andric break; 3738e8d8bef9SDimitry Andric 373981ad6265SDimitry Andric default: 374081ad6265SDimitry Andric if (!FormatTok->Tok.getIdentifierInfo()) { 374181ad6265SDimitry Andric // Identifiers are part of the default case, we check for more then 374281ad6265SDimitry Andric // tok::identifier to handle builtin type traits. 374381ad6265SDimitry Andric return; 374481ad6265SDimitry Andric } 374581ad6265SDimitry Andric 374681ad6265SDimitry Andric // We need to differentiate identifiers for a template deduction guide, 374781ad6265SDimitry Andric // variables, or function return types (the constraint expression has 374881ad6265SDimitry Andric // ended before that), and basically all other cases. But it's easier to 374981ad6265SDimitry Andric // check the other way around. 375081ad6265SDimitry Andric assert(FormatTok->Previous); 375181ad6265SDimitry Andric switch (FormatTok->Previous->Tok.getKind()) { 375281ad6265SDimitry Andric case tok::coloncolon: // Nested identifier. 375381ad6265SDimitry Andric case tok::ampamp: // Start of a function or variable for the 3754bdd1243dSDimitry Andric case tok::pipepipe: // constraint expression. (binary) 3755bdd1243dSDimitry Andric case tok::exclaim: // The same as above, but unary. 375681ad6265SDimitry Andric case tok::kw_requires: // Initial identifier of a requires clause. 375781ad6265SDimitry Andric case tok::equal: // Initial identifier of a concept declaration. 375881ad6265SDimitry Andric break; 375981ad6265SDimitry Andric default: 376081ad6265SDimitry Andric return; 376181ad6265SDimitry Andric } 376281ad6265SDimitry Andric 376381ad6265SDimitry Andric // Read identifier with optional template declaration. 376481ad6265SDimitry Andric nextToken(); 376581ad6265SDimitry Andric if (FormatTok->is(tok::less)) { 376681ad6265SDimitry Andric nextToken(); 37675f757f3fSDimitry Andric parseBracedList(/*IsAngleBracket=*/true); 376881ad6265SDimitry Andric } 376906c3fb27SDimitry Andric TopLevelParensAllowed = false; 377081ad6265SDimitry Andric break; 377181ad6265SDimitry Andric } 377281ad6265SDimitry Andric } while (!eof()); 3773e8d8bef9SDimitry Andric } 3774e8d8bef9SDimitry Andric 37750b57cec5SDimitry Andric bool UnwrappedLineParser::parseEnum() { 377604eeddc0SDimitry Andric const FormatToken &InitialToken = *FormatTok; 377704eeddc0SDimitry Andric 37780b57cec5SDimitry Andric // Won't be 'enum' for NS_ENUMs. 377981ad6265SDimitry Andric if (FormatTok->is(tok::kw_enum)) 37800b57cec5SDimitry Andric nextToken(); 37810b57cec5SDimitry Andric 37820b57cec5SDimitry Andric // In TypeScript, "enum" can also be used as property name, e.g. in interface 37830b57cec5SDimitry Andric // declarations. An "enum" keyword followed by a colon would be a syntax 37840b57cec5SDimitry Andric // error and thus assume it is just an identifier. 37850eae32dcSDimitry Andric if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question)) 37860b57cec5SDimitry Andric return false; 37870b57cec5SDimitry Andric 37880b57cec5SDimitry Andric // In protobuf, "enum" can be used as a field name. 37890b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal)) 37900b57cec5SDimitry Andric return false; 37910b57cec5SDimitry Andric 37920fca6ea1SDimitry Andric if (IsCpp) { 37930b57cec5SDimitry Andric // Eat up enum class ... 379481ad6265SDimitry Andric if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct)) 37950b57cec5SDimitry Andric nextToken(); 37960fca6ea1SDimitry Andric while (FormatTok->is(tok::l_square)) 37970fca6ea1SDimitry Andric if (!handleCppAttributes()) 37980fca6ea1SDimitry Andric return false; 37990fca6ea1SDimitry Andric } 38000b57cec5SDimitry Andric 38010b57cec5SDimitry Andric while (FormatTok->Tok.getIdentifierInfo() || 38020b57cec5SDimitry Andric FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less, 380381ad6265SDimitry Andric tok::greater, tok::comma, tok::question, 38040fca6ea1SDimitry Andric tok::l_square)) { 380506c3fb27SDimitry Andric if (Style.isVerilog()) { 380606c3fb27SDimitry Andric FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName); 38070b57cec5SDimitry Andric nextToken(); 380806c3fb27SDimitry Andric // In Verilog the base type can have dimensions. 380906c3fb27SDimitry Andric while (FormatTok->is(tok::l_square)) 381006c3fb27SDimitry Andric parseSquare(); 381106c3fb27SDimitry Andric } else { 381206c3fb27SDimitry Andric nextToken(); 381306c3fb27SDimitry Andric } 38140b57cec5SDimitry Andric // We can have macros or attributes in between 'enum' and the enum name. 38150b57cec5SDimitry Andric if (FormatTok->is(tok::l_paren)) 38160b57cec5SDimitry Andric parseParens(); 38170b57cec5SDimitry Andric if (FormatTok->is(tok::identifier)) { 38180b57cec5SDimitry Andric nextToken(); 38190b57cec5SDimitry Andric // If there are two identifiers in a row, this is likely an elaborate 38200b57cec5SDimitry Andric // return type. In Java, this can be "implements", etc. 38210fca6ea1SDimitry Andric if (IsCpp && FormatTok->is(tok::identifier)) 38220b57cec5SDimitry Andric return false; 38230b57cec5SDimitry Andric } 38240b57cec5SDimitry Andric } 38250b57cec5SDimitry Andric 38260b57cec5SDimitry Andric // Just a declaration or something is wrong. 38270b57cec5SDimitry Andric if (FormatTok->isNot(tok::l_brace)) 38280b57cec5SDimitry Andric return true; 382981ad6265SDimitry Andric FormatTok->setFinalizedType(TT_EnumLBrace); 3830e8d8bef9SDimitry Andric FormatTok->setBlockKind(BK_Block); 38310b57cec5SDimitry Andric 38320b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Java) { 38330b57cec5SDimitry Andric // Java enums are different. 38340b57cec5SDimitry Andric parseJavaEnumBody(); 38350b57cec5SDimitry Andric return true; 38360b57cec5SDimitry Andric } 38370b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Proto) { 38380b57cec5SDimitry Andric parseBlock(/*MustBeDeclaration=*/true); 38390b57cec5SDimitry Andric return true; 38400b57cec5SDimitry Andric } 38410b57cec5SDimitry Andric 3842349cc55cSDimitry Andric if (!Style.AllowShortEnumsOnASingleLine && 384381ad6265SDimitry Andric ShouldBreakBeforeBrace(Style, InitialToken)) { 38445ffd83dbSDimitry Andric addUnwrappedLine(); 384581ad6265SDimitry Andric } 38460b57cec5SDimitry Andric // Parse enum body. 38470b57cec5SDimitry Andric nextToken(); 38485ffd83dbSDimitry Andric if (!Style.AllowShortEnumsOnASingleLine) { 38495ffd83dbSDimitry Andric addUnwrappedLine(); 38505ffd83dbSDimitry Andric Line->Level += 1; 38515ffd83dbSDimitry Andric } 38525f757f3fSDimitry Andric bool HasError = !parseBracedList(/*IsAngleBracket=*/false, /*IsEnum=*/true); 38535ffd83dbSDimitry Andric if (!Style.AllowShortEnumsOnASingleLine) 38545ffd83dbSDimitry Andric Line->Level -= 1; 38550b57cec5SDimitry Andric if (HasError) { 38560b57cec5SDimitry Andric if (FormatTok->is(tok::semi)) 38570b57cec5SDimitry Andric nextToken(); 38580b57cec5SDimitry Andric addUnwrappedLine(); 38590b57cec5SDimitry Andric } 38605f757f3fSDimitry Andric setPreviousRBraceType(TT_EnumRBrace); 38610b57cec5SDimitry Andric return true; 38620b57cec5SDimitry Andric 38630b57cec5SDimitry Andric // There is no addUnwrappedLine() here so that we fall through to parsing a 38640b57cec5SDimitry Andric // structural element afterwards. Thus, in "enum A {} n, m;", 38650b57cec5SDimitry Andric // "} n, m;" will end up in one unwrapped line. 38660b57cec5SDimitry Andric } 38670b57cec5SDimitry Andric 3868fe6060f1SDimitry Andric bool UnwrappedLineParser::parseStructLike() { 3869fe6060f1SDimitry Andric // parseRecord falls through and does not yet add an unwrapped line as a 3870fe6060f1SDimitry Andric // record declaration or definition can start a structural element. 3871fe6060f1SDimitry Andric parseRecord(); 3872fe6060f1SDimitry Andric // This does not apply to Java, JavaScript and C#. 38730eae32dcSDimitry Andric if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || 38740eae32dcSDimitry Andric Style.isCSharp()) { 3875fe6060f1SDimitry Andric if (FormatTok->is(tok::semi)) 3876fe6060f1SDimitry Andric nextToken(); 3877fe6060f1SDimitry Andric addUnwrappedLine(); 3878fe6060f1SDimitry Andric return true; 3879fe6060f1SDimitry Andric } 3880fe6060f1SDimitry Andric return false; 3881fe6060f1SDimitry Andric } 3882fe6060f1SDimitry Andric 38835ffd83dbSDimitry Andric namespace { 38845ffd83dbSDimitry Andric // A class used to set and restore the Token position when peeking 38855ffd83dbSDimitry Andric // ahead in the token source. 38865ffd83dbSDimitry Andric class ScopedTokenPosition { 38875ffd83dbSDimitry Andric unsigned StoredPosition; 38885ffd83dbSDimitry Andric FormatTokenSource *Tokens; 38895ffd83dbSDimitry Andric 38905ffd83dbSDimitry Andric public: 38915ffd83dbSDimitry Andric ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) { 38925ffd83dbSDimitry Andric assert(Tokens && "Tokens expected to not be null"); 38935ffd83dbSDimitry Andric StoredPosition = Tokens->getPosition(); 38945ffd83dbSDimitry Andric } 38955ffd83dbSDimitry Andric 38965ffd83dbSDimitry Andric ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); } 38975ffd83dbSDimitry Andric }; 38985ffd83dbSDimitry Andric } // namespace 38995ffd83dbSDimitry Andric 39005ffd83dbSDimitry Andric // Look to see if we have [[ by looking ahead, if 39015ffd83dbSDimitry Andric // its not then rewind to the original position. 39025ffd83dbSDimitry Andric bool UnwrappedLineParser::tryToParseSimpleAttribute() { 39035ffd83dbSDimitry Andric ScopedTokenPosition AutoPosition(Tokens); 39045ffd83dbSDimitry Andric FormatToken *Tok = Tokens->getNextToken(); 39055ffd83dbSDimitry Andric // We already read the first [ check for the second. 39065f757f3fSDimitry Andric if (Tok->isNot(tok::l_square)) 39075ffd83dbSDimitry Andric return false; 39085ffd83dbSDimitry Andric // Double check that the attribute is just something 39095ffd83dbSDimitry Andric // fairly simple. 39104824e7fdSDimitry Andric while (Tok->isNot(tok::eof)) { 391181ad6265SDimitry Andric if (Tok->is(tok::r_square)) 39125ffd83dbSDimitry Andric break; 39135ffd83dbSDimitry Andric Tok = Tokens->getNextToken(); 39145ffd83dbSDimitry Andric } 39154824e7fdSDimitry Andric if (Tok->is(tok::eof)) 39164824e7fdSDimitry Andric return false; 39175ffd83dbSDimitry Andric Tok = Tokens->getNextToken(); 39185f757f3fSDimitry Andric if (Tok->isNot(tok::r_square)) 39195ffd83dbSDimitry Andric return false; 39205ffd83dbSDimitry Andric Tok = Tokens->getNextToken(); 392181ad6265SDimitry Andric if (Tok->is(tok::semi)) 39225ffd83dbSDimitry Andric return false; 39235ffd83dbSDimitry Andric return true; 39245ffd83dbSDimitry Andric } 39255ffd83dbSDimitry Andric 39260b57cec5SDimitry Andric void UnwrappedLineParser::parseJavaEnumBody() { 392781ad6265SDimitry Andric assert(FormatTok->is(tok::l_brace)); 392881ad6265SDimitry Andric const FormatToken *OpeningBrace = FormatTok; 392981ad6265SDimitry Andric 39300b57cec5SDimitry Andric // Determine whether the enum is simple, i.e. does not have a semicolon or 39310b57cec5SDimitry Andric // constants with class bodies. Simple enums can be formatted like braced 39320b57cec5SDimitry Andric // lists, contracted to a single line, etc. 39330b57cec5SDimitry Andric unsigned StoredPosition = Tokens->getPosition(); 39340b57cec5SDimitry Andric bool IsSimple = true; 39350b57cec5SDimitry Andric FormatToken *Tok = Tokens->getNextToken(); 39365f757f3fSDimitry Andric while (Tok->isNot(tok::eof)) { 39370b57cec5SDimitry Andric if (Tok->is(tok::r_brace)) 39380b57cec5SDimitry Andric break; 39390b57cec5SDimitry Andric if (Tok->isOneOf(tok::l_brace, tok::semi)) { 39400b57cec5SDimitry Andric IsSimple = false; 39410b57cec5SDimitry Andric break; 39420b57cec5SDimitry Andric } 39430b57cec5SDimitry Andric // FIXME: This will also mark enums with braces in the arguments to enum 39440b57cec5SDimitry Andric // constants as "not simple". This is probably fine in practice, though. 39450b57cec5SDimitry Andric Tok = Tokens->getNextToken(); 39460b57cec5SDimitry Andric } 39470b57cec5SDimitry Andric FormatTok = Tokens->setPosition(StoredPosition); 39480b57cec5SDimitry Andric 39490b57cec5SDimitry Andric if (IsSimple) { 39500b57cec5SDimitry Andric nextToken(); 39510b57cec5SDimitry Andric parseBracedList(); 39520b57cec5SDimitry Andric addUnwrappedLine(); 39530b57cec5SDimitry Andric return; 39540b57cec5SDimitry Andric } 39550b57cec5SDimitry Andric 39560b57cec5SDimitry Andric // Parse the body of a more complex enum. 39570b57cec5SDimitry Andric // First add a line for everything up to the "{". 39580b57cec5SDimitry Andric nextToken(); 39590b57cec5SDimitry Andric addUnwrappedLine(); 39600b57cec5SDimitry Andric ++Line->Level; 39610b57cec5SDimitry Andric 39620b57cec5SDimitry Andric // Parse the enum constants. 3963bdd1243dSDimitry Andric while (!eof()) { 39640b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 39650b57cec5SDimitry Andric // Parse the constant's class body. 3966fe6060f1SDimitry Andric parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u, 39670b57cec5SDimitry Andric /*MunchSemi=*/false); 39680b57cec5SDimitry Andric } else if (FormatTok->is(tok::l_paren)) { 39690b57cec5SDimitry Andric parseParens(); 39700b57cec5SDimitry Andric } else if (FormatTok->is(tok::comma)) { 39710b57cec5SDimitry Andric nextToken(); 39720b57cec5SDimitry Andric addUnwrappedLine(); 39730b57cec5SDimitry Andric } else if (FormatTok->is(tok::semi)) { 39740b57cec5SDimitry Andric nextToken(); 39750b57cec5SDimitry Andric addUnwrappedLine(); 39760b57cec5SDimitry Andric break; 39770b57cec5SDimitry Andric } else if (FormatTok->is(tok::r_brace)) { 39780b57cec5SDimitry Andric addUnwrappedLine(); 39790b57cec5SDimitry Andric break; 39800b57cec5SDimitry Andric } else { 39810b57cec5SDimitry Andric nextToken(); 39820b57cec5SDimitry Andric } 39830b57cec5SDimitry Andric } 39840b57cec5SDimitry Andric 39850b57cec5SDimitry Andric // Parse the class body after the enum's ";" if any. 398681ad6265SDimitry Andric parseLevel(OpeningBrace); 39870b57cec5SDimitry Andric nextToken(); 39880b57cec5SDimitry Andric --Line->Level; 39890b57cec5SDimitry Andric addUnwrappedLine(); 39900b57cec5SDimitry Andric } 39910b57cec5SDimitry Andric 39920b57cec5SDimitry Andric void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { 39930b57cec5SDimitry Andric const FormatToken &InitialToken = *FormatTok; 39940b57cec5SDimitry Andric nextToken(); 39950b57cec5SDimitry Andric 39960fca6ea1SDimitry Andric const FormatToken *ClassName = nullptr; 39970fca6ea1SDimitry Andric bool IsDerived = false; 39987a6dacacSDimitry Andric auto IsNonMacroIdentifier = [](const FormatToken *Tok) { 39997a6dacacSDimitry Andric return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper(); 40007a6dacacSDimitry Andric }; 40016c4b055cSDimitry Andric // JavaScript/TypeScript supports anonymous classes like: 40026c4b055cSDimitry Andric // a = class extends foo { } 40036c4b055cSDimitry Andric bool JSPastExtendsOrImplements = false; 40040b57cec5SDimitry Andric // The actual identifier can be a nested name specifier, and in macros 40050b57cec5SDimitry Andric // it is often token-pasted. 40065ffd83dbSDimitry Andric // An [[attribute]] can be before the identifier. 40070b57cec5SDimitry Andric while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash, 40081ac55f4cSDimitry Andric tok::kw_alignas, tok::l_square) || 40095f757f3fSDimitry Andric FormatTok->isAttribute() || 40100eae32dcSDimitry Andric ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && 40110b57cec5SDimitry Andric FormatTok->isOneOf(tok::period, tok::comma))) { 40120eae32dcSDimitry Andric if (Style.isJavaScript() && 40130b57cec5SDimitry Andric FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) { 40146c4b055cSDimitry Andric JSPastExtendsOrImplements = true; 40150b57cec5SDimitry Andric // JavaScript/TypeScript supports inline object types in 40160b57cec5SDimitry Andric // extends/implements positions: 40170b57cec5SDimitry Andric // class Foo implements {bar: number} { } 40180b57cec5SDimitry Andric nextToken(); 40190b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 40200b57cec5SDimitry Andric tryToParseBracedList(); 40210b57cec5SDimitry Andric continue; 40220b57cec5SDimitry Andric } 40230b57cec5SDimitry Andric } 40241ac55f4cSDimitry Andric if (FormatTok->is(tok::l_square) && handleCppAttributes()) 40251ac55f4cSDimitry Andric continue; 40260fca6ea1SDimitry Andric const auto *Previous = FormatTok; 40270b57cec5SDimitry Andric nextToken(); 40280fca6ea1SDimitry Andric switch (FormatTok->Tok.getKind()) { 40290fca6ea1SDimitry Andric case tok::l_paren: 40301ac55f4cSDimitry Andric // We can have macros in between 'class' and the class name. 40310fca6ea1SDimitry Andric if (!IsNonMacroIdentifier(Previous) || 40320fca6ea1SDimitry Andric // e.g. `struct macro(a) S { int i; };` 40330fca6ea1SDimitry Andric Previous->Previous == &InitialToken) { 40340b57cec5SDimitry Andric parseParens(); 40350b57cec5SDimitry Andric } 40360fca6ea1SDimitry Andric break; 40370fca6ea1SDimitry Andric case tok::coloncolon: 40386c4b055cSDimitry Andric case tok::hashhash: 40390fca6ea1SDimitry Andric break; 40400fca6ea1SDimitry Andric default: 40416c4b055cSDimitry Andric if (!JSPastExtendsOrImplements && !ClassName && 40426c4b055cSDimitry Andric Previous->is(tok::identifier) && Previous->isNot(TT_AttributeMacro)) { 40430fca6ea1SDimitry Andric ClassName = Previous; 40447a6dacacSDimitry Andric } 40450fca6ea1SDimitry Andric } 40460fca6ea1SDimitry Andric } 40470fca6ea1SDimitry Andric 40480fca6ea1SDimitry Andric auto IsListInitialization = [&] { 40490fca6ea1SDimitry Andric if (!ClassName || IsDerived) 40500fca6ea1SDimitry Andric return false; 40510fca6ea1SDimitry Andric assert(FormatTok->is(tok::l_brace)); 40520fca6ea1SDimitry Andric const auto *Prev = FormatTok->getPreviousNonComment(); 40530fca6ea1SDimitry Andric assert(Prev); 40540fca6ea1SDimitry Andric return Prev != ClassName && Prev->is(tok::identifier) && 40550fca6ea1SDimitry Andric Prev->isNot(Keywords.kw_final) && tryToParseBracedList(); 40560fca6ea1SDimitry Andric }; 40570b57cec5SDimitry Andric 40580b57cec5SDimitry Andric if (FormatTok->isOneOf(tok::colon, tok::less)) { 40597a6dacacSDimitry Andric int AngleNestingLevel = 0; 406081ad6265SDimitry Andric do { 40617a6dacacSDimitry Andric if (FormatTok->is(tok::less)) 40627a6dacacSDimitry Andric ++AngleNestingLevel; 40637a6dacacSDimitry Andric else if (FormatTok->is(tok::greater)) 40647a6dacacSDimitry Andric --AngleNestingLevel; 40657a6dacacSDimitry Andric 40660fca6ea1SDimitry Andric if (AngleNestingLevel == 0) { 40670fca6ea1SDimitry Andric if (FormatTok->is(tok::colon)) { 40680fca6ea1SDimitry Andric IsDerived = true; 40690fca6ea1SDimitry Andric } else if (FormatTok->is(tok::identifier) && 40700fca6ea1SDimitry Andric FormatTok->Previous->is(tok::coloncolon)) { 40710fca6ea1SDimitry Andric ClassName = FormatTok; 40720fca6ea1SDimitry Andric } else if (FormatTok->is(tok::l_paren) && 40737a6dacacSDimitry Andric IsNonMacroIdentifier(FormatTok->Previous)) { 40747a6dacacSDimitry Andric break; 40757a6dacacSDimitry Andric } 40760fca6ea1SDimitry Andric } 40770b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 40780fca6ea1SDimitry Andric if (AngleNestingLevel == 0 && IsListInitialization()) 40790fca6ea1SDimitry Andric return; 40800b57cec5SDimitry Andric calculateBraceTypes(/*ExpectClassBody=*/true); 40810b57cec5SDimitry Andric if (!tryToParseBracedList()) 40820b57cec5SDimitry Andric break; 40830b57cec5SDimitry Andric } 408404eeddc0SDimitry Andric if (FormatTok->is(tok::l_square)) { 408504eeddc0SDimitry Andric FormatToken *Previous = FormatTok->Previous; 40860fca6ea1SDimitry Andric if (!Previous || (Previous->isNot(tok::r_paren) && 40870fca6ea1SDimitry Andric !Previous->isTypeOrIdentifier(LangOpts))) { 408804eeddc0SDimitry Andric // Don't try parsing a lambda if we had a closing parenthesis before, 408904eeddc0SDimitry Andric // it was probably a pointer to an array: int (*)[]. 409004eeddc0SDimitry Andric if (!tryToParseLambda()) 409106c3fb27SDimitry Andric continue; 409281ad6265SDimitry Andric } else { 409381ad6265SDimitry Andric parseSquare(); 409481ad6265SDimitry Andric continue; 409504eeddc0SDimitry Andric } 409604eeddc0SDimitry Andric } 409781ad6265SDimitry Andric if (FormatTok->is(tok::semi)) 40980b57cec5SDimitry Andric return; 40995ffd83dbSDimitry Andric if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) { 41005ffd83dbSDimitry Andric addUnwrappedLine(); 41015ffd83dbSDimitry Andric nextToken(); 41025ffd83dbSDimitry Andric parseCSharpGenericTypeConstraint(); 41035ffd83dbSDimitry Andric break; 41045ffd83dbSDimitry Andric } 41050b57cec5SDimitry Andric nextToken(); 410681ad6265SDimitry Andric } while (!eof()); 41070b57cec5SDimitry Andric } 410881ad6265SDimitry Andric 41095f757f3fSDimitry Andric auto GetBraceTypes = 41105f757f3fSDimitry Andric [](const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> { 411181ad6265SDimitry Andric switch (RecordTok.Tok.getKind()) { 411281ad6265SDimitry Andric case tok::kw_class: 41135f757f3fSDimitry Andric return {TT_ClassLBrace, TT_ClassRBrace}; 411481ad6265SDimitry Andric case tok::kw_struct: 41155f757f3fSDimitry Andric return {TT_StructLBrace, TT_StructRBrace}; 411681ad6265SDimitry Andric case tok::kw_union: 41175f757f3fSDimitry Andric return {TT_UnionLBrace, TT_UnionRBrace}; 411881ad6265SDimitry Andric default: 411981ad6265SDimitry Andric // Useful for e.g. interface. 41205f757f3fSDimitry Andric return {TT_RecordLBrace, TT_RecordRBrace}; 41210b57cec5SDimitry Andric } 412281ad6265SDimitry Andric }; 412381ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 41240fca6ea1SDimitry Andric if (IsListInitialization()) 41250fca6ea1SDimitry Andric return; 41265f757f3fSDimitry Andric auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken); 41275f757f3fSDimitry Andric FormatTok->setFinalizedType(OpenBraceType); 41280b57cec5SDimitry Andric if (ParseAsExpr) { 41290b57cec5SDimitry Andric parseChildBlock(); 41300b57cec5SDimitry Andric } else { 41310b57cec5SDimitry Andric if (ShouldBreakBeforeBrace(Style, InitialToken)) 41320b57cec5SDimitry Andric addUnwrappedLine(); 41330b57cec5SDimitry Andric 4134fe6060f1SDimitry Andric unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u; 4135fe6060f1SDimitry Andric parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/false); 41360b57cec5SDimitry Andric } 41375f757f3fSDimitry Andric setPreviousRBraceType(ClosingBraceType); 41380b57cec5SDimitry Andric } 41390b57cec5SDimitry Andric // There is no addUnwrappedLine() here so that we fall through to parsing a 41400b57cec5SDimitry Andric // structural element afterwards. Thus, in "class A {} n, m;", 41410b57cec5SDimitry Andric // "} n, m;" will end up in one unwrapped line. 41420b57cec5SDimitry Andric } 41430b57cec5SDimitry Andric 41440b57cec5SDimitry Andric void UnwrappedLineParser::parseObjCMethod() { 414581ad6265SDimitry Andric assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) && 41460b57cec5SDimitry Andric "'(' or identifier expected."); 41470b57cec5SDimitry Andric do { 414881ad6265SDimitry Andric if (FormatTok->is(tok::semi)) { 41490b57cec5SDimitry Andric nextToken(); 41500b57cec5SDimitry Andric addUnwrappedLine(); 41510b57cec5SDimitry Andric return; 415281ad6265SDimitry Andric } else if (FormatTok->is(tok::l_brace)) { 41530b57cec5SDimitry Andric if (Style.BraceWrapping.AfterFunction) 41540b57cec5SDimitry Andric addUnwrappedLine(); 4155349cc55cSDimitry Andric parseBlock(); 41560b57cec5SDimitry Andric addUnwrappedLine(); 41570b57cec5SDimitry Andric return; 41580b57cec5SDimitry Andric } else { 41590b57cec5SDimitry Andric nextToken(); 41600b57cec5SDimitry Andric } 41610b57cec5SDimitry Andric } while (!eof()); 41620b57cec5SDimitry Andric } 41630b57cec5SDimitry Andric 41640b57cec5SDimitry Andric void UnwrappedLineParser::parseObjCProtocolList() { 416581ad6265SDimitry Andric assert(FormatTok->is(tok::less) && "'<' expected."); 41660b57cec5SDimitry Andric do { 41670b57cec5SDimitry Andric nextToken(); 41680b57cec5SDimitry Andric // Early exit in case someone forgot a close angle. 41690b57cec5SDimitry Andric if (FormatTok->isOneOf(tok::semi, tok::l_brace) || 417081ad6265SDimitry Andric FormatTok->isObjCAtKeyword(tok::objc_end)) { 41710b57cec5SDimitry Andric return; 417281ad6265SDimitry Andric } 417381ad6265SDimitry Andric } while (!eof() && FormatTok->isNot(tok::greater)); 41740b57cec5SDimitry Andric nextToken(); // Skip '>'. 41750b57cec5SDimitry Andric } 41760b57cec5SDimitry Andric 41770b57cec5SDimitry Andric void UnwrappedLineParser::parseObjCUntilAtEnd() { 41780b57cec5SDimitry Andric do { 417981ad6265SDimitry Andric if (FormatTok->isObjCAtKeyword(tok::objc_end)) { 41800b57cec5SDimitry Andric nextToken(); 41810b57cec5SDimitry Andric addUnwrappedLine(); 41820b57cec5SDimitry Andric break; 41830b57cec5SDimitry Andric } 41840b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 4185349cc55cSDimitry Andric parseBlock(); 41860b57cec5SDimitry Andric // In ObjC interfaces, nothing should be following the "}". 41870b57cec5SDimitry Andric addUnwrappedLine(); 41880b57cec5SDimitry Andric } else if (FormatTok->is(tok::r_brace)) { 41890b57cec5SDimitry Andric // Ignore stray "}". parseStructuralElement doesn't consume them. 41900b57cec5SDimitry Andric nextToken(); 41910b57cec5SDimitry Andric addUnwrappedLine(); 41920b57cec5SDimitry Andric } else if (FormatTok->isOneOf(tok::minus, tok::plus)) { 41930b57cec5SDimitry Andric nextToken(); 41940b57cec5SDimitry Andric parseObjCMethod(); 41950b57cec5SDimitry Andric } else { 41960b57cec5SDimitry Andric parseStructuralElement(); 41970b57cec5SDimitry Andric } 41980b57cec5SDimitry Andric } while (!eof()); 41990b57cec5SDimitry Andric } 42000b57cec5SDimitry Andric 42010b57cec5SDimitry Andric void UnwrappedLineParser::parseObjCInterfaceOrImplementation() { 42020b57cec5SDimitry Andric assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_interface || 42030b57cec5SDimitry Andric FormatTok->Tok.getObjCKeywordID() == tok::objc_implementation); 42040b57cec5SDimitry Andric nextToken(); 42050b57cec5SDimitry Andric nextToken(); // interface name 42060b57cec5SDimitry Andric 42070b57cec5SDimitry Andric // @interface can be followed by a lightweight generic 42080b57cec5SDimitry Andric // specialization list, then either a base class or a category. 420981ad6265SDimitry Andric if (FormatTok->is(tok::less)) 4210e8d8bef9SDimitry Andric parseObjCLightweightGenerics(); 421181ad6265SDimitry Andric if (FormatTok->is(tok::colon)) { 4212e8d8bef9SDimitry Andric nextToken(); 4213e8d8bef9SDimitry Andric nextToken(); // base class name 4214e8d8bef9SDimitry Andric // The base class can also have lightweight generics applied to it. 421581ad6265SDimitry Andric if (FormatTok->is(tok::less)) 4216e8d8bef9SDimitry Andric parseObjCLightweightGenerics(); 421781ad6265SDimitry Andric } else if (FormatTok->is(tok::l_paren)) { 4218e8d8bef9SDimitry Andric // Skip category, if present. 4219e8d8bef9SDimitry Andric parseParens(); 422081ad6265SDimitry Andric } 4221e8d8bef9SDimitry Andric 422281ad6265SDimitry Andric if (FormatTok->is(tok::less)) 4223e8d8bef9SDimitry Andric parseObjCProtocolList(); 4224e8d8bef9SDimitry Andric 422581ad6265SDimitry Andric if (FormatTok->is(tok::l_brace)) { 4226e8d8bef9SDimitry Andric if (Style.BraceWrapping.AfterObjCDeclaration) 4227e8d8bef9SDimitry Andric addUnwrappedLine(); 4228e8d8bef9SDimitry Andric parseBlock(/*MustBeDeclaration=*/true); 4229e8d8bef9SDimitry Andric } 4230e8d8bef9SDimitry Andric 4231e8d8bef9SDimitry Andric // With instance variables, this puts '}' on its own line. Without instance 4232e8d8bef9SDimitry Andric // variables, this ends the @interface line. 4233e8d8bef9SDimitry Andric addUnwrappedLine(); 4234e8d8bef9SDimitry Andric 4235e8d8bef9SDimitry Andric parseObjCUntilAtEnd(); 4236e8d8bef9SDimitry Andric } 4237e8d8bef9SDimitry Andric 4238e8d8bef9SDimitry Andric void UnwrappedLineParser::parseObjCLightweightGenerics() { 423981ad6265SDimitry Andric assert(FormatTok->is(tok::less)); 42400b57cec5SDimitry Andric // Unlike protocol lists, generic parameterizations support 42410b57cec5SDimitry Andric // nested angles: 42420b57cec5SDimitry Andric // 42430b57cec5SDimitry Andric // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> : 42440b57cec5SDimitry Andric // NSObject <NSCopying, NSSecureCoding> 42450b57cec5SDimitry Andric // 42460b57cec5SDimitry Andric // so we need to count how many open angles we have left. 42470b57cec5SDimitry Andric unsigned NumOpenAngles = 1; 42480b57cec5SDimitry Andric do { 42490b57cec5SDimitry Andric nextToken(); 42500b57cec5SDimitry Andric // Early exit in case someone forgot a close angle. 42510b57cec5SDimitry Andric if (FormatTok->isOneOf(tok::semi, tok::l_brace) || 425281ad6265SDimitry Andric FormatTok->isObjCAtKeyword(tok::objc_end)) { 42530b57cec5SDimitry Andric break; 425481ad6265SDimitry Andric } 425581ad6265SDimitry Andric if (FormatTok->is(tok::less)) { 42560b57cec5SDimitry Andric ++NumOpenAngles; 425781ad6265SDimitry Andric } else if (FormatTok->is(tok::greater)) { 42580b57cec5SDimitry Andric assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative"); 42590b57cec5SDimitry Andric --NumOpenAngles; 42600b57cec5SDimitry Andric } 42610b57cec5SDimitry Andric } while (!eof() && NumOpenAngles != 0); 42620b57cec5SDimitry Andric nextToken(); // Skip '>'. 42630b57cec5SDimitry Andric } 42640b57cec5SDimitry Andric 42650b57cec5SDimitry Andric // Returns true for the declaration/definition form of @protocol, 42660b57cec5SDimitry Andric // false for the expression form. 42670b57cec5SDimitry Andric bool UnwrappedLineParser::parseObjCProtocol() { 42680b57cec5SDimitry Andric assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_protocol); 42690b57cec5SDimitry Andric nextToken(); 42700b57cec5SDimitry Andric 427181ad6265SDimitry Andric if (FormatTok->is(tok::l_paren)) { 42720b57cec5SDimitry Andric // The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);". 42730b57cec5SDimitry Andric return false; 427481ad6265SDimitry Andric } 42750b57cec5SDimitry Andric 42760b57cec5SDimitry Andric // The definition/declaration form, 42770b57cec5SDimitry Andric // @protocol Foo 42780b57cec5SDimitry Andric // - (int)someMethod; 42790b57cec5SDimitry Andric // @end 42800b57cec5SDimitry Andric 42810b57cec5SDimitry Andric nextToken(); // protocol name 42820b57cec5SDimitry Andric 428381ad6265SDimitry Andric if (FormatTok->is(tok::less)) 42840b57cec5SDimitry Andric parseObjCProtocolList(); 42850b57cec5SDimitry Andric 42860b57cec5SDimitry Andric // Check for protocol declaration. 428781ad6265SDimitry Andric if (FormatTok->is(tok::semi)) { 42880b57cec5SDimitry Andric nextToken(); 42890b57cec5SDimitry Andric addUnwrappedLine(); 42900b57cec5SDimitry Andric return true; 42910b57cec5SDimitry Andric } 42920b57cec5SDimitry Andric 42930b57cec5SDimitry Andric addUnwrappedLine(); 42940b57cec5SDimitry Andric parseObjCUntilAtEnd(); 42950b57cec5SDimitry Andric return true; 42960b57cec5SDimitry Andric } 42970b57cec5SDimitry Andric 42980b57cec5SDimitry Andric void UnwrappedLineParser::parseJavaScriptEs6ImportExport() { 42990b57cec5SDimitry Andric bool IsImport = FormatTok->is(Keywords.kw_import); 43000b57cec5SDimitry Andric assert(IsImport || FormatTok->is(tok::kw_export)); 43010b57cec5SDimitry Andric nextToken(); 43020b57cec5SDimitry Andric 43030b57cec5SDimitry Andric // Consume the "default" in "export default class/function". 43040b57cec5SDimitry Andric if (FormatTok->is(tok::kw_default)) 43050b57cec5SDimitry Andric nextToken(); 43060b57cec5SDimitry Andric 43070b57cec5SDimitry Andric // Consume "async function", "function" and "default function", so that these 43080b57cec5SDimitry Andric // get parsed as free-standing JS functions, i.e. do not require a trailing 43090b57cec5SDimitry Andric // semicolon. 43100b57cec5SDimitry Andric if (FormatTok->is(Keywords.kw_async)) 43110b57cec5SDimitry Andric nextToken(); 43120b57cec5SDimitry Andric if (FormatTok->is(Keywords.kw_function)) { 43130b57cec5SDimitry Andric nextToken(); 43140b57cec5SDimitry Andric return; 43150b57cec5SDimitry Andric } 43160b57cec5SDimitry Andric 43170b57cec5SDimitry Andric // For imports, `export *`, `export {...}`, consume the rest of the line up 43180b57cec5SDimitry Andric // to the terminating `;`. For everything else, just return and continue 43190b57cec5SDimitry Andric // parsing the structural element, i.e. the declaration or expression for 43200b57cec5SDimitry Andric // `export default`. 43210b57cec5SDimitry Andric if (!IsImport && !FormatTok->isOneOf(tok::l_brace, tok::star) && 432206c3fb27SDimitry Andric !FormatTok->isStringLiteral() && 432306c3fb27SDimitry Andric !(FormatTok->is(Keywords.kw_type) && 432406c3fb27SDimitry Andric Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) { 43250b57cec5SDimitry Andric return; 432681ad6265SDimitry Andric } 43270b57cec5SDimitry Andric 43280b57cec5SDimitry Andric while (!eof()) { 43290b57cec5SDimitry Andric if (FormatTok->is(tok::semi)) 43300b57cec5SDimitry Andric return; 43310b57cec5SDimitry Andric if (Line->Tokens.empty()) { 43320b57cec5SDimitry Andric // Common issue: Automatic Semicolon Insertion wrapped the line, so the 43330b57cec5SDimitry Andric // import statement should terminate. 43340b57cec5SDimitry Andric return; 43350b57cec5SDimitry Andric } 43360b57cec5SDimitry Andric if (FormatTok->is(tok::l_brace)) { 4337e8d8bef9SDimitry Andric FormatTok->setBlockKind(BK_Block); 43380b57cec5SDimitry Andric nextToken(); 43390b57cec5SDimitry Andric parseBracedList(); 43400b57cec5SDimitry Andric } else { 43410b57cec5SDimitry Andric nextToken(); 43420b57cec5SDimitry Andric } 43430b57cec5SDimitry Andric } 43440b57cec5SDimitry Andric } 43450b57cec5SDimitry Andric 43460b57cec5SDimitry Andric void UnwrappedLineParser::parseStatementMacro() { 43470b57cec5SDimitry Andric nextToken(); 43480b57cec5SDimitry Andric if (FormatTok->is(tok::l_paren)) 43490b57cec5SDimitry Andric parseParens(); 43500b57cec5SDimitry Andric if (FormatTok->is(tok::semi)) 43510b57cec5SDimitry Andric nextToken(); 43520b57cec5SDimitry Andric addUnwrappedLine(); 43530b57cec5SDimitry Andric } 43540b57cec5SDimitry Andric 4355bdd1243dSDimitry Andric void UnwrappedLineParser::parseVerilogHierarchyIdentifier() { 4356bdd1243dSDimitry Andric // consume things like a::`b.c[d:e] or a::* 4357bdd1243dSDimitry Andric while (true) { 4358bdd1243dSDimitry Andric if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar, 4359bdd1243dSDimitry Andric tok::coloncolon, tok::hash) || 4360bdd1243dSDimitry Andric Keywords.isVerilogIdentifier(*FormatTok)) { 4361bdd1243dSDimitry Andric nextToken(); 4362bdd1243dSDimitry Andric } else if (FormatTok->is(tok::l_square)) { 4363bdd1243dSDimitry Andric parseSquare(); 4364bdd1243dSDimitry Andric } else { 4365bdd1243dSDimitry Andric break; 43660b57cec5SDimitry Andric } 4367bdd1243dSDimitry Andric } 4368bdd1243dSDimitry Andric } 4369349cc55cSDimitry Andric 4370bdd1243dSDimitry Andric void UnwrappedLineParser::parseVerilogSensitivityList() { 43715f757f3fSDimitry Andric if (FormatTok->isNot(tok::at)) 4372bdd1243dSDimitry Andric return; 4373bdd1243dSDimitry Andric nextToken(); 4374bdd1243dSDimitry Andric // A block event expression has 2 at signs. 4375bdd1243dSDimitry Andric if (FormatTok->is(tok::at)) 4376bdd1243dSDimitry Andric nextToken(); 4377bdd1243dSDimitry Andric switch (FormatTok->Tok.getKind()) { 4378bdd1243dSDimitry Andric case tok::star: 4379bdd1243dSDimitry Andric nextToken(); 4380bdd1243dSDimitry Andric break; 4381bdd1243dSDimitry Andric case tok::l_paren: 4382bdd1243dSDimitry Andric parseParens(); 4383bdd1243dSDimitry Andric break; 4384bdd1243dSDimitry Andric default: 4385bdd1243dSDimitry Andric parseVerilogHierarchyIdentifier(); 4386bdd1243dSDimitry Andric break; 4387bdd1243dSDimitry Andric } 4388bdd1243dSDimitry Andric } 4389bdd1243dSDimitry Andric 4390bdd1243dSDimitry Andric unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() { 4391bdd1243dSDimitry Andric unsigned AddLevels = 0; 4392bdd1243dSDimitry Andric 4393bdd1243dSDimitry Andric if (FormatTok->is(Keywords.kw_clocking)) { 4394bdd1243dSDimitry Andric nextToken(); 4395bdd1243dSDimitry Andric if (Keywords.isVerilogIdentifier(*FormatTok)) 4396bdd1243dSDimitry Andric nextToken(); 4397bdd1243dSDimitry Andric parseVerilogSensitivityList(); 4398bdd1243dSDimitry Andric if (FormatTok->is(tok::semi)) 4399bdd1243dSDimitry Andric nextToken(); 4400bdd1243dSDimitry Andric } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex, 4401bdd1243dSDimitry Andric Keywords.kw_casez, Keywords.kw_randcase, 4402bdd1243dSDimitry Andric Keywords.kw_randsequence)) { 4403bdd1243dSDimitry Andric if (Style.IndentCaseLabels) 4404bdd1243dSDimitry Andric AddLevels++; 4405bdd1243dSDimitry Andric nextToken(); 4406bdd1243dSDimitry Andric if (FormatTok->is(tok::l_paren)) { 4407bdd1243dSDimitry Andric FormatTok->setFinalizedType(TT_ConditionLParen); 4408bdd1243dSDimitry Andric parseParens(); 4409bdd1243dSDimitry Andric } 4410bdd1243dSDimitry Andric if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches)) 4411bdd1243dSDimitry Andric nextToken(); 4412bdd1243dSDimitry Andric // The case header has no semicolon. 4413bdd1243dSDimitry Andric } else { 4414bdd1243dSDimitry Andric // "module" etc. 4415bdd1243dSDimitry Andric nextToken(); 4416bdd1243dSDimitry Andric // all the words like the name of the module and specifiers like 4417bdd1243dSDimitry Andric // "automatic" and the width of function return type 4418bdd1243dSDimitry Andric while (true) { 4419bdd1243dSDimitry Andric if (FormatTok->is(tok::l_square)) { 4420bdd1243dSDimitry Andric auto Prev = FormatTok->getPreviousNonComment(); 4421bdd1243dSDimitry Andric if (Prev && Keywords.isVerilogIdentifier(*Prev)) 4422bdd1243dSDimitry Andric Prev->setFinalizedType(TT_VerilogDimensionedTypeName); 4423bdd1243dSDimitry Andric parseSquare(); 4424bdd1243dSDimitry Andric } else if (Keywords.isVerilogIdentifier(*FormatTok) || 4425bdd1243dSDimitry Andric FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) { 4426bdd1243dSDimitry Andric nextToken(); 4427bdd1243dSDimitry Andric } else { 4428bdd1243dSDimitry Andric break; 4429bdd1243dSDimitry Andric } 4430bdd1243dSDimitry Andric } 4431bdd1243dSDimitry Andric 4432bdd1243dSDimitry Andric auto NewLine = [this]() { 4433bdd1243dSDimitry Andric addUnwrappedLine(); 4434bdd1243dSDimitry Andric Line->IsContinuation = true; 4435bdd1243dSDimitry Andric }; 4436bdd1243dSDimitry Andric 4437bdd1243dSDimitry Andric // package imports 4438bdd1243dSDimitry Andric while (FormatTok->is(Keywords.kw_import)) { 4439bdd1243dSDimitry Andric NewLine(); 4440bdd1243dSDimitry Andric nextToken(); 4441bdd1243dSDimitry Andric parseVerilogHierarchyIdentifier(); 4442bdd1243dSDimitry Andric if (FormatTok->is(tok::semi)) 4443bdd1243dSDimitry Andric nextToken(); 4444bdd1243dSDimitry Andric } 4445bdd1243dSDimitry Andric 4446bdd1243dSDimitry Andric // parameters and ports 4447bdd1243dSDimitry Andric if (FormatTok->is(Keywords.kw_verilogHash)) { 4448bdd1243dSDimitry Andric NewLine(); 4449bdd1243dSDimitry Andric nextToken(); 445006c3fb27SDimitry Andric if (FormatTok->is(tok::l_paren)) { 445106c3fb27SDimitry Andric FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen); 4452bdd1243dSDimitry Andric parseParens(); 4453bdd1243dSDimitry Andric } 445406c3fb27SDimitry Andric } 4455bdd1243dSDimitry Andric if (FormatTok->is(tok::l_paren)) { 4456bdd1243dSDimitry Andric NewLine(); 445706c3fb27SDimitry Andric FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen); 4458bdd1243dSDimitry Andric parseParens(); 4459bdd1243dSDimitry Andric } 4460bdd1243dSDimitry Andric 4461bdd1243dSDimitry Andric // extends and implements 4462bdd1243dSDimitry Andric if (FormatTok->is(Keywords.kw_extends)) { 4463bdd1243dSDimitry Andric NewLine(); 4464bdd1243dSDimitry Andric nextToken(); 4465bdd1243dSDimitry Andric parseVerilogHierarchyIdentifier(); 4466bdd1243dSDimitry Andric if (FormatTok->is(tok::l_paren)) 4467bdd1243dSDimitry Andric parseParens(); 4468bdd1243dSDimitry Andric } 4469bdd1243dSDimitry Andric if (FormatTok->is(Keywords.kw_implements)) { 4470bdd1243dSDimitry Andric NewLine(); 4471bdd1243dSDimitry Andric do { 4472bdd1243dSDimitry Andric nextToken(); 4473bdd1243dSDimitry Andric parseVerilogHierarchyIdentifier(); 4474bdd1243dSDimitry Andric } while (FormatTok->is(tok::comma)); 4475bdd1243dSDimitry Andric } 4476bdd1243dSDimitry Andric 4477bdd1243dSDimitry Andric // Coverage event for cover groups. 4478bdd1243dSDimitry Andric if (FormatTok->is(tok::at)) { 4479bdd1243dSDimitry Andric NewLine(); 4480bdd1243dSDimitry Andric parseVerilogSensitivityList(); 4481bdd1243dSDimitry Andric } 4482bdd1243dSDimitry Andric 4483bdd1243dSDimitry Andric if (FormatTok->is(tok::semi)) 4484bdd1243dSDimitry Andric nextToken(/*LevelDifference=*/1); 4485bdd1243dSDimitry Andric addUnwrappedLine(); 4486bdd1243dSDimitry Andric } 4487bdd1243dSDimitry Andric 4488bdd1243dSDimitry Andric return AddLevels; 4489bdd1243dSDimitry Andric } 4490bdd1243dSDimitry Andric 4491bdd1243dSDimitry Andric void UnwrappedLineParser::parseVerilogTable() { 4492bdd1243dSDimitry Andric assert(FormatTok->is(Keywords.kw_table)); 4493bdd1243dSDimitry Andric nextToken(/*LevelDifference=*/1); 4494bdd1243dSDimitry Andric addUnwrappedLine(); 4495bdd1243dSDimitry Andric 4496bdd1243dSDimitry Andric auto InitialLevel = Line->Level++; 4497bdd1243dSDimitry Andric while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) { 4498bdd1243dSDimitry Andric FormatToken *Tok = FormatTok; 4499bdd1243dSDimitry Andric nextToken(); 4500bdd1243dSDimitry Andric if (Tok->is(tok::semi)) 4501bdd1243dSDimitry Andric addUnwrappedLine(); 4502bdd1243dSDimitry Andric else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus)) 4503bdd1243dSDimitry Andric Tok->setFinalizedType(TT_VerilogTableItem); 4504bdd1243dSDimitry Andric } 4505bdd1243dSDimitry Andric Line->Level = InitialLevel; 4506bdd1243dSDimitry Andric nextToken(/*LevelDifference=*/-1); 4507bdd1243dSDimitry Andric addUnwrappedLine(); 4508bdd1243dSDimitry Andric } 4509bdd1243dSDimitry Andric 4510bdd1243dSDimitry Andric void UnwrappedLineParser::parseVerilogCaseLabel() { 4511bdd1243dSDimitry Andric // The label will get unindented in AnnotatingParser. If there are no leading 4512bdd1243dSDimitry Andric // spaces, indent the rest here so that things inside the block will be 4513bdd1243dSDimitry Andric // indented relative to things outside. We don't use parseLabel because we 4514bdd1243dSDimitry Andric // don't know whether this colon is a label or a ternary expression at this 4515bdd1243dSDimitry Andric // point. 4516bdd1243dSDimitry Andric auto OrigLevel = Line->Level; 4517bdd1243dSDimitry Andric auto FirstLine = CurrentLines->size(); 4518bdd1243dSDimitry Andric if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1)) 4519bdd1243dSDimitry Andric ++Line->Level; 4520bdd1243dSDimitry Andric else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok)) 4521bdd1243dSDimitry Andric --Line->Level; 4522bdd1243dSDimitry Andric parseStructuralElement(); 4523bdd1243dSDimitry Andric // Restore the indentation in both the new line and the line that has the 4524bdd1243dSDimitry Andric // label. 4525bdd1243dSDimitry Andric if (CurrentLines->size() > FirstLine) 4526bdd1243dSDimitry Andric (*CurrentLines)[FirstLine].Level = OrigLevel; 4527bdd1243dSDimitry Andric Line->Level = OrigLevel; 45280b57cec5SDimitry Andric } 45290b57cec5SDimitry Andric 453006c3fb27SDimitry Andric bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const { 453106c3fb27SDimitry Andric for (const auto &N : Line.Tokens) { 453206c3fb27SDimitry Andric if (N.Tok->MacroCtx) 453306c3fb27SDimitry Andric return true; 453406c3fb27SDimitry Andric for (const UnwrappedLine &Child : N.Children) 453506c3fb27SDimitry Andric if (containsExpansion(Child)) 453606c3fb27SDimitry Andric return true; 453706c3fb27SDimitry Andric } 453806c3fb27SDimitry Andric return false; 453906c3fb27SDimitry Andric } 454006c3fb27SDimitry Andric 454123408297SDimitry Andric void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { 45420b57cec5SDimitry Andric if (Line->Tokens.empty()) 45430b57cec5SDimitry Andric return; 45440b57cec5SDimitry Andric LLVM_DEBUG({ 454506c3fb27SDimitry Andric if (!parsingPPDirective()) { 454606c3fb27SDimitry Andric llvm::dbgs() << "Adding unwrapped line:\n"; 45470b57cec5SDimitry Andric printDebugInfo(*Line); 454806c3fb27SDimitry Andric } 45490b57cec5SDimitry Andric }); 455023408297SDimitry Andric 455123408297SDimitry Andric // If this line closes a block when in Whitesmiths mode, remember that 455223408297SDimitry Andric // information so that the level can be decreased after the line is added. 455323408297SDimitry Andric // This has to happen after the addition of the line since the line itself 455423408297SDimitry Andric // needs to be indented. 455523408297SDimitry Andric bool ClosesWhitesmithsBlock = 455623408297SDimitry Andric Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex && 455723408297SDimitry Andric Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; 455823408297SDimitry Andric 455906c3fb27SDimitry Andric // If the current line was expanded from a macro call, we use it to 456006c3fb27SDimitry Andric // reconstruct an unwrapped line from the structure of the expanded unwrapped 456106c3fb27SDimitry Andric // line and the unexpanded token stream. 456206c3fb27SDimitry Andric if (!parsingPPDirective() && !InExpansion && containsExpansion(*Line)) { 456306c3fb27SDimitry Andric if (!Reconstruct) 456406c3fb27SDimitry Andric Reconstruct.emplace(Line->Level, Unexpanded); 456506c3fb27SDimitry Andric Reconstruct->addLine(*Line); 456606c3fb27SDimitry Andric 456706c3fb27SDimitry Andric // While the reconstructed unexpanded lines are stored in the normal 456806c3fb27SDimitry Andric // flow of lines, the expanded lines are stored on the side to be analyzed 456906c3fb27SDimitry Andric // in an extra step. 457006c3fb27SDimitry Andric CurrentExpandedLines.push_back(std::move(*Line)); 457106c3fb27SDimitry Andric 457206c3fb27SDimitry Andric if (Reconstruct->finished()) { 457306c3fb27SDimitry Andric UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult(); 457406c3fb27SDimitry Andric assert(!Reconstructed.Tokens.empty() && 457506c3fb27SDimitry Andric "Reconstructed must at least contain the macro identifier."); 457606c3fb27SDimitry Andric assert(!parsingPPDirective()); 457706c3fb27SDimitry Andric LLVM_DEBUG({ 457806c3fb27SDimitry Andric llvm::dbgs() << "Adding unexpanded line:\n"; 457906c3fb27SDimitry Andric printDebugInfo(Reconstructed); 458006c3fb27SDimitry Andric }); 458106c3fb27SDimitry Andric ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines; 458206c3fb27SDimitry Andric Lines.push_back(std::move(Reconstructed)); 458306c3fb27SDimitry Andric CurrentExpandedLines.clear(); 458406c3fb27SDimitry Andric Reconstruct.reset(); 458506c3fb27SDimitry Andric } 458606c3fb27SDimitry Andric } else { 458706c3fb27SDimitry Andric // At the top level we only get here when no unexpansion is going on, or 458806c3fb27SDimitry Andric // when conditional formatting led to unfinished macro reconstructions. 458906c3fb27SDimitry Andric assert(!Reconstruct || (CurrentLines != &Lines) || PPStack.size() > 0); 45900b57cec5SDimitry Andric CurrentLines->push_back(std::move(*Line)); 459106c3fb27SDimitry Andric } 45920b57cec5SDimitry Andric Line->Tokens.clear(); 45930b57cec5SDimitry Andric Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex; 45940b57cec5SDimitry Andric Line->FirstStartColumn = 0; 4595bdd1243dSDimitry Andric Line->IsContinuation = false; 4596bdb86d1aSDimitry Andric Line->SeenDecltypeAuto = false; 459723408297SDimitry Andric 459823408297SDimitry Andric if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove) 459923408297SDimitry Andric --Line->Level; 460006c3fb27SDimitry Andric if (!parsingPPDirective() && !PreprocessorDirectives.empty()) { 46010b57cec5SDimitry Andric CurrentLines->append( 46020b57cec5SDimitry Andric std::make_move_iterator(PreprocessorDirectives.begin()), 46030b57cec5SDimitry Andric std::make_move_iterator(PreprocessorDirectives.end())); 46040b57cec5SDimitry Andric PreprocessorDirectives.clear(); 46050b57cec5SDimitry Andric } 46060b57cec5SDimitry Andric // Disconnect the current token from the last token on the previous line. 46070b57cec5SDimitry Andric FormatTok->Previous = nullptr; 46080b57cec5SDimitry Andric } 46090b57cec5SDimitry Andric 461081ad6265SDimitry Andric bool UnwrappedLineParser::eof() const { return FormatTok->is(tok::eof); } 46110b57cec5SDimitry Andric 46120b57cec5SDimitry Andric bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) { 46130b57cec5SDimitry Andric return (Line->InPPDirective || FormatTok.HasUnescapedNewline) && 46140b57cec5SDimitry Andric FormatTok.NewlinesBefore > 0; 46150b57cec5SDimitry Andric } 46160b57cec5SDimitry Andric 46170b57cec5SDimitry Andric // Checks if \p FormatTok is a line comment that continues the line comment 46180b57cec5SDimitry Andric // section on \p Line. 4619480093f4SDimitry Andric static bool 4620480093f4SDimitry Andric continuesLineCommentSection(const FormatToken &FormatTok, 46210b57cec5SDimitry Andric const UnwrappedLine &Line, 4622480093f4SDimitry Andric const llvm::Regex &CommentPragmasRegex) { 46230b57cec5SDimitry Andric if (Line.Tokens.empty()) 46240b57cec5SDimitry Andric return false; 46250b57cec5SDimitry Andric 46260b57cec5SDimitry Andric StringRef IndentContent = FormatTok.TokenText; 46275f757f3fSDimitry Andric if (FormatTok.TokenText.starts_with("//") || 46285f757f3fSDimitry Andric FormatTok.TokenText.starts_with("/*")) { 46290b57cec5SDimitry Andric IndentContent = FormatTok.TokenText.substr(2); 463081ad6265SDimitry Andric } 46310b57cec5SDimitry Andric if (CommentPragmasRegex.match(IndentContent)) 46320b57cec5SDimitry Andric return false; 46330b57cec5SDimitry Andric 46340b57cec5SDimitry Andric // If Line starts with a line comment, then FormatTok continues the comment 46350b57cec5SDimitry Andric // section if its original column is greater or equal to the original start 46360b57cec5SDimitry Andric // column of the line. 46370b57cec5SDimitry Andric // 46380b57cec5SDimitry Andric // Define the min column token of a line as follows: if a line ends in '{' or 46390b57cec5SDimitry Andric // contains a '{' followed by a line comment, then the min column token is 46400b57cec5SDimitry Andric // that '{'. Otherwise, the min column token of the line is the first token of 46410b57cec5SDimitry Andric // the line. 46420b57cec5SDimitry Andric // 46430b57cec5SDimitry Andric // If Line starts with a token other than a line comment, then FormatTok 46440b57cec5SDimitry Andric // continues the comment section if its original column is greater than the 46450b57cec5SDimitry Andric // original start column of the min column token of the line. 46460b57cec5SDimitry Andric // 46470b57cec5SDimitry Andric // For example, the second line comment continues the first in these cases: 46480b57cec5SDimitry Andric // 46490b57cec5SDimitry Andric // // first line 46500b57cec5SDimitry Andric // // second line 46510b57cec5SDimitry Andric // 46520b57cec5SDimitry Andric // and: 46530b57cec5SDimitry Andric // 46540b57cec5SDimitry Andric // // first line 46550b57cec5SDimitry Andric // // second line 46560b57cec5SDimitry Andric // 46570b57cec5SDimitry Andric // and: 46580b57cec5SDimitry Andric // 46590b57cec5SDimitry Andric // int i; // first line 46600b57cec5SDimitry Andric // // second line 46610b57cec5SDimitry Andric // 46620b57cec5SDimitry Andric // and: 46630b57cec5SDimitry Andric // 46640b57cec5SDimitry Andric // do { // first line 46650b57cec5SDimitry Andric // // second line 46660b57cec5SDimitry Andric // int i; 46670b57cec5SDimitry Andric // } while (true); 46680b57cec5SDimitry Andric // 46690b57cec5SDimitry Andric // and: 46700b57cec5SDimitry Andric // 46710b57cec5SDimitry Andric // enum { 46720b57cec5SDimitry Andric // a, // first line 46730b57cec5SDimitry Andric // // second line 46740b57cec5SDimitry Andric // b 46750b57cec5SDimitry Andric // }; 46760b57cec5SDimitry Andric // 46770b57cec5SDimitry Andric // The second line comment doesn't continue the first in these cases: 46780b57cec5SDimitry Andric // 46790b57cec5SDimitry Andric // // first line 46800b57cec5SDimitry Andric // // second line 46810b57cec5SDimitry Andric // 46820b57cec5SDimitry Andric // and: 46830b57cec5SDimitry Andric // 46840b57cec5SDimitry Andric // int i; // first line 46850b57cec5SDimitry Andric // // second line 46860b57cec5SDimitry Andric // 46870b57cec5SDimitry Andric // and: 46880b57cec5SDimitry Andric // 46890b57cec5SDimitry Andric // do { // first line 46900b57cec5SDimitry Andric // // second line 46910b57cec5SDimitry Andric // int i; 46920b57cec5SDimitry Andric // } while (true); 46930b57cec5SDimitry Andric // 46940b57cec5SDimitry Andric // and: 46950b57cec5SDimitry Andric // 46960b57cec5SDimitry Andric // enum { 46970b57cec5SDimitry Andric // a, // first line 46980b57cec5SDimitry Andric // // second line 46990b57cec5SDimitry Andric // }; 47000b57cec5SDimitry Andric const FormatToken *MinColumnToken = Line.Tokens.front().Tok; 47010b57cec5SDimitry Andric 47020b57cec5SDimitry Andric // Scan for '{//'. If found, use the column of '{' as a min column for line 47030b57cec5SDimitry Andric // comment section continuation. 47040b57cec5SDimitry Andric const FormatToken *PreviousToken = nullptr; 47050b57cec5SDimitry Andric for (const UnwrappedLineNode &Node : Line.Tokens) { 47060b57cec5SDimitry Andric if (PreviousToken && PreviousToken->is(tok::l_brace) && 47070b57cec5SDimitry Andric isLineComment(*Node.Tok)) { 47080b57cec5SDimitry Andric MinColumnToken = PreviousToken; 47090b57cec5SDimitry Andric break; 47100b57cec5SDimitry Andric } 47110b57cec5SDimitry Andric PreviousToken = Node.Tok; 47120b57cec5SDimitry Andric 47130b57cec5SDimitry Andric // Grab the last newline preceding a token in this unwrapped line. 471481ad6265SDimitry Andric if (Node.Tok->NewlinesBefore > 0) 47150b57cec5SDimitry Andric MinColumnToken = Node.Tok; 47160b57cec5SDimitry Andric } 471781ad6265SDimitry Andric if (PreviousToken && PreviousToken->is(tok::l_brace)) 47180b57cec5SDimitry Andric MinColumnToken = PreviousToken; 47190b57cec5SDimitry Andric 47200b57cec5SDimitry Andric return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok, 47210b57cec5SDimitry Andric MinColumnToken); 47220b57cec5SDimitry Andric } 47230b57cec5SDimitry Andric 47240b57cec5SDimitry Andric void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) { 47250b57cec5SDimitry Andric bool JustComments = Line->Tokens.empty(); 472604eeddc0SDimitry Andric for (FormatToken *Tok : CommentsBeforeNextToken) { 47270b57cec5SDimitry Andric // Line comments that belong to the same line comment section are put on the 47280b57cec5SDimitry Andric // same line since later we might want to reflow content between them. 47290b57cec5SDimitry Andric // Additional fine-grained breaking of line comment sections is controlled 47300b57cec5SDimitry Andric // by the class BreakableLineCommentSection in case it is desirable to keep 47310b57cec5SDimitry Andric // several line comment sections in the same unwrapped line. 47320b57cec5SDimitry Andric // 47330b57cec5SDimitry Andric // FIXME: Consider putting separate line comment sections as children to the 47340b57cec5SDimitry Andric // unwrapped line instead. 473504eeddc0SDimitry Andric Tok->ContinuesLineCommentSection = 473604eeddc0SDimitry Andric continuesLineCommentSection(*Tok, *Line, CommentPragmasRegex); 473704eeddc0SDimitry Andric if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection) 47380b57cec5SDimitry Andric addUnwrappedLine(); 473904eeddc0SDimitry Andric pushToken(Tok); 47400b57cec5SDimitry Andric } 47410b57cec5SDimitry Andric if (NewlineBeforeNext && JustComments) 47420b57cec5SDimitry Andric addUnwrappedLine(); 47430b57cec5SDimitry Andric CommentsBeforeNextToken.clear(); 47440b57cec5SDimitry Andric } 47450b57cec5SDimitry Andric 47460b57cec5SDimitry Andric void UnwrappedLineParser::nextToken(int LevelDifference) { 47470b57cec5SDimitry Andric if (eof()) 47480b57cec5SDimitry Andric return; 47490b57cec5SDimitry Andric flushComments(isOnNewLine(*FormatTok)); 47500b57cec5SDimitry Andric pushToken(FormatTok); 47510b57cec5SDimitry Andric FormatToken *Previous = FormatTok; 47520eae32dcSDimitry Andric if (!Style.isJavaScript()) 47530b57cec5SDimitry Andric readToken(LevelDifference); 47540b57cec5SDimitry Andric else 47550b57cec5SDimitry Andric readTokenWithJavaScriptASI(); 47560b57cec5SDimitry Andric FormatTok->Previous = Previous; 475781ad6265SDimitry Andric if (Style.isVerilog()) { 475881ad6265SDimitry Andric // Blocks in Verilog can have `begin` and `end` instead of braces. For 475981ad6265SDimitry Andric // keywords like `begin`, we can't treat them the same as left braces 476081ad6265SDimitry Andric // because some contexts require one of them. For example structs use 476181ad6265SDimitry Andric // braces and if blocks use keywords, and a left brace can occur in an if 476281ad6265SDimitry Andric // statement, but it is not a block. For keywords like `end`, we simply 476381ad6265SDimitry Andric // treat them the same as right braces. 476481ad6265SDimitry Andric if (Keywords.isVerilogEnd(*FormatTok)) 476581ad6265SDimitry Andric FormatTok->Tok.setKind(tok::r_brace); 476681ad6265SDimitry Andric } 47670b57cec5SDimitry Andric } 47680b57cec5SDimitry Andric 47690b57cec5SDimitry Andric void UnwrappedLineParser::distributeComments( 47700b57cec5SDimitry Andric const SmallVectorImpl<FormatToken *> &Comments, 47710b57cec5SDimitry Andric const FormatToken *NextTok) { 47720b57cec5SDimitry Andric // Whether or not a line comment token continues a line is controlled by 47730b57cec5SDimitry Andric // the method continuesLineCommentSection, with the following caveat: 47740b57cec5SDimitry Andric // 47750b57cec5SDimitry Andric // Define a trail of Comments to be a nonempty proper postfix of Comments such 47760b57cec5SDimitry Andric // that each comment line from the trail is aligned with the next token, if 47770b57cec5SDimitry Andric // the next token exists. If a trail exists, the beginning of the maximal 47780b57cec5SDimitry Andric // trail is marked as a start of a new comment section. 47790b57cec5SDimitry Andric // 47800b57cec5SDimitry Andric // For example in this code: 47810b57cec5SDimitry Andric // 47820b57cec5SDimitry Andric // int a; // line about a 47830b57cec5SDimitry Andric // // line 1 about b 47840b57cec5SDimitry Andric // // line 2 about b 47850b57cec5SDimitry Andric // int b; 47860b57cec5SDimitry Andric // 47870b57cec5SDimitry Andric // the two lines about b form a maximal trail, so there are two sections, the 47880b57cec5SDimitry Andric // first one consisting of the single comment "// line about a" and the 47890b57cec5SDimitry Andric // second one consisting of the next two comments. 47900b57cec5SDimitry Andric if (Comments.empty()) 47910b57cec5SDimitry Andric return; 47920b57cec5SDimitry Andric bool ShouldPushCommentsInCurrentLine = true; 47930b57cec5SDimitry Andric bool HasTrailAlignedWithNextToken = false; 47940b57cec5SDimitry Andric unsigned StartOfTrailAlignedWithNextToken = 0; 47950b57cec5SDimitry Andric if (NextTok) { 47960b57cec5SDimitry Andric // We are skipping the first element intentionally. 47970b57cec5SDimitry Andric for (unsigned i = Comments.size() - 1; i > 0; --i) { 47980b57cec5SDimitry Andric if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) { 47990b57cec5SDimitry Andric HasTrailAlignedWithNextToken = true; 48000b57cec5SDimitry Andric StartOfTrailAlignedWithNextToken = i; 48010b57cec5SDimitry Andric } 48020b57cec5SDimitry Andric } 48030b57cec5SDimitry Andric } 48040b57cec5SDimitry Andric for (unsigned i = 0, e = Comments.size(); i < e; ++i) { 48050b57cec5SDimitry Andric FormatToken *FormatTok = Comments[i]; 48060b57cec5SDimitry Andric if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) { 48070b57cec5SDimitry Andric FormatTok->ContinuesLineCommentSection = false; 48080b57cec5SDimitry Andric } else { 48090b57cec5SDimitry Andric FormatTok->ContinuesLineCommentSection = 48100b57cec5SDimitry Andric continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex); 48110b57cec5SDimitry Andric } 48120b57cec5SDimitry Andric if (!FormatTok->ContinuesLineCommentSection && 48130b57cec5SDimitry Andric (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) { 48140b57cec5SDimitry Andric ShouldPushCommentsInCurrentLine = false; 48150b57cec5SDimitry Andric } 481681ad6265SDimitry Andric if (ShouldPushCommentsInCurrentLine) 48170b57cec5SDimitry Andric pushToken(FormatTok); 481881ad6265SDimitry Andric else 48190b57cec5SDimitry Andric CommentsBeforeNextToken.push_back(FormatTok); 48200b57cec5SDimitry Andric } 48210b57cec5SDimitry Andric } 48220b57cec5SDimitry Andric 48230b57cec5SDimitry Andric void UnwrappedLineParser::readToken(int LevelDifference) { 48240b57cec5SDimitry Andric SmallVector<FormatToken *, 1> Comments; 482581ad6265SDimitry Andric bool PreviousWasComment = false; 482681ad6265SDimitry Andric bool FirstNonCommentOnLine = false; 48270b57cec5SDimitry Andric do { 48280b57cec5SDimitry Andric FormatTok = Tokens->getNextToken(); 48290b57cec5SDimitry Andric assert(FormatTok); 48300fca6ea1SDimitry Andric while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd, 48310fca6ea1SDimitry Andric TT_ConflictAlternative)) { 48320fca6ea1SDimitry Andric if (FormatTok->is(TT_ConflictStart)) 48334824e7fdSDimitry Andric conditionalCompilationStart(/*Unreachable=*/false); 48340fca6ea1SDimitry Andric else if (FormatTok->is(TT_ConflictAlternative)) 48354824e7fdSDimitry Andric conditionalCompilationAlternative(); 48360fca6ea1SDimitry Andric else if (FormatTok->is(TT_ConflictEnd)) 48374824e7fdSDimitry Andric conditionalCompilationEnd(); 48384824e7fdSDimitry Andric FormatTok = Tokens->getNextToken(); 48394824e7fdSDimitry Andric FormatTok->MustBreakBefore = true; 4840297eecfbSDimitry Andric FormatTok->MustBreakBeforeFinalized = true; 48414824e7fdSDimitry Andric } 48424824e7fdSDimitry Andric 484381ad6265SDimitry Andric auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine, 484481ad6265SDimitry Andric const FormatToken &Tok, 484581ad6265SDimitry Andric bool PreviousWasComment) { 484681ad6265SDimitry Andric auto IsFirstOnLine = [](const FormatToken &Tok) { 484781ad6265SDimitry Andric return Tok.HasUnescapedNewline || Tok.IsFirst; 484881ad6265SDimitry Andric }; 484981ad6265SDimitry Andric 485081ad6265SDimitry Andric // Consider preprocessor directives preceded by block comments as first 485181ad6265SDimitry Andric // on line. 485281ad6265SDimitry Andric if (PreviousWasComment) 485381ad6265SDimitry Andric return FirstNonCommentOnLine || IsFirstOnLine(Tok); 485481ad6265SDimitry Andric return IsFirstOnLine(Tok); 485581ad6265SDimitry Andric }; 485681ad6265SDimitry Andric 485781ad6265SDimitry Andric FirstNonCommentOnLine = IsFirstNonCommentOnLine( 485881ad6265SDimitry Andric FirstNonCommentOnLine, *FormatTok, PreviousWasComment); 485981ad6265SDimitry Andric PreviousWasComment = FormatTok->is(tok::comment); 486081ad6265SDimitry Andric 486181ad6265SDimitry Andric while (!Line->InPPDirective && FormatTok->is(tok::hash) && 486281ad6265SDimitry Andric (!Style.isVerilog() || 486381ad6265SDimitry Andric Keywords.isVerilogPPDirective(*Tokens->peekNextToken())) && 486481ad6265SDimitry Andric FirstNonCommentOnLine) { 48650b57cec5SDimitry Andric distributeComments(Comments, FormatTok); 48660b57cec5SDimitry Andric Comments.clear(); 48670b57cec5SDimitry Andric // If there is an unfinished unwrapped line, we flush the preprocessor 48680b57cec5SDimitry Andric // directives only after that unwrapped line was finished later. 48690b57cec5SDimitry Andric bool SwitchToPreprocessorLines = !Line->Tokens.empty(); 48700b57cec5SDimitry Andric ScopedLineState BlockState(*this, SwitchToPreprocessorLines); 48710b57cec5SDimitry Andric assert((LevelDifference >= 0 || 48720b57cec5SDimitry Andric static_cast<unsigned>(-LevelDifference) <= Line->Level) && 48730b57cec5SDimitry Andric "LevelDifference makes Line->Level negative"); 48740b57cec5SDimitry Andric Line->Level += LevelDifference; 48750b57cec5SDimitry Andric // Comments stored before the preprocessor directive need to be output 48760b57cec5SDimitry Andric // before the preprocessor directive, at the same level as the 48770b57cec5SDimitry Andric // preprocessor directive, as we consider them to apply to the directive. 48780b57cec5SDimitry Andric if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash && 487981ad6265SDimitry Andric PPBranchLevel > 0) { 48800b57cec5SDimitry Andric Line->Level += PPBranchLevel; 488181ad6265SDimitry Andric } 48820fca6ea1SDimitry Andric assert(Line->Level >= Line->UnbracedBodyLevel); 48830fca6ea1SDimitry Andric Line->Level -= Line->UnbracedBodyLevel; 48840b57cec5SDimitry Andric flushComments(isOnNewLine(*FormatTok)); 48850b57cec5SDimitry Andric parsePPDirective(); 488681ad6265SDimitry Andric PreviousWasComment = FormatTok->is(tok::comment); 488781ad6265SDimitry Andric FirstNonCommentOnLine = IsFirstNonCommentOnLine( 488881ad6265SDimitry Andric FirstNonCommentOnLine, *FormatTok, PreviousWasComment); 48890b57cec5SDimitry Andric } 48900b57cec5SDimitry Andric 48910b57cec5SDimitry Andric if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) && 48920b57cec5SDimitry Andric !Line->InPPDirective) { 48930b57cec5SDimitry Andric continue; 48940b57cec5SDimitry Andric } 48950b57cec5SDimitry Andric 489606c3fb27SDimitry Andric if (FormatTok->is(tok::identifier) && 489706c3fb27SDimitry Andric Macros.defined(FormatTok->TokenText) && 489806c3fb27SDimitry Andric // FIXME: Allow expanding macros in preprocessor directives. 489906c3fb27SDimitry Andric !Line->InPPDirective) { 490006c3fb27SDimitry Andric FormatToken *ID = FormatTok; 490106c3fb27SDimitry Andric unsigned Position = Tokens->getPosition(); 490206c3fb27SDimitry Andric 490306c3fb27SDimitry Andric // To correctly parse the code, we need to replace the tokens of the macro 490406c3fb27SDimitry Andric // call with its expansion. 490506c3fb27SDimitry Andric auto PreCall = std::move(Line); 490606c3fb27SDimitry Andric Line.reset(new UnwrappedLine); 490706c3fb27SDimitry Andric bool OldInExpansion = InExpansion; 490806c3fb27SDimitry Andric InExpansion = true; 490906c3fb27SDimitry Andric // We parse the macro call into a new line. 491006c3fb27SDimitry Andric auto Args = parseMacroCall(); 491106c3fb27SDimitry Andric InExpansion = OldInExpansion; 491206c3fb27SDimitry Andric assert(Line->Tokens.front().Tok == ID); 491306c3fb27SDimitry Andric // And remember the unexpanded macro call tokens. 491406c3fb27SDimitry Andric auto UnexpandedLine = std::move(Line); 491506c3fb27SDimitry Andric // Reset to the old line. 491606c3fb27SDimitry Andric Line = std::move(PreCall); 491706c3fb27SDimitry Andric 491806c3fb27SDimitry Andric LLVM_DEBUG({ 491906c3fb27SDimitry Andric llvm::dbgs() << "Macro call: " << ID->TokenText << "("; 492006c3fb27SDimitry Andric if (Args) { 492106c3fb27SDimitry Andric llvm::dbgs() << "("; 492206c3fb27SDimitry Andric for (const auto &Arg : Args.value()) 492306c3fb27SDimitry Andric for (const auto &T : Arg) 492406c3fb27SDimitry Andric llvm::dbgs() << T->TokenText << " "; 492506c3fb27SDimitry Andric llvm::dbgs() << ")"; 492606c3fb27SDimitry Andric } 492706c3fb27SDimitry Andric llvm::dbgs() << "\n"; 492806c3fb27SDimitry Andric }); 492906c3fb27SDimitry Andric if (Macros.objectLike(ID->TokenText) && Args && 493006c3fb27SDimitry Andric !Macros.hasArity(ID->TokenText, Args->size())) { 493106c3fb27SDimitry Andric // The macro is either 493206c3fb27SDimitry Andric // - object-like, but we got argumnets, or 493306c3fb27SDimitry Andric // - overloaded to be both object-like and function-like, but none of 493406c3fb27SDimitry Andric // the function-like arities match the number of arguments. 493506c3fb27SDimitry Andric // Thus, expand as object-like macro. 493606c3fb27SDimitry Andric LLVM_DEBUG(llvm::dbgs() 493706c3fb27SDimitry Andric << "Macro \"" << ID->TokenText 493806c3fb27SDimitry Andric << "\" not overloaded for arity " << Args->size() 493906c3fb27SDimitry Andric << "or not function-like, using object-like overload."); 494006c3fb27SDimitry Andric Args.reset(); 494106c3fb27SDimitry Andric UnexpandedLine->Tokens.resize(1); 494206c3fb27SDimitry Andric Tokens->setPosition(Position); 494306c3fb27SDimitry Andric nextToken(); 494406c3fb27SDimitry Andric assert(!Args && Macros.objectLike(ID->TokenText)); 494506c3fb27SDimitry Andric } 494606c3fb27SDimitry Andric if ((!Args && Macros.objectLike(ID->TokenText)) || 494706c3fb27SDimitry Andric (Args && Macros.hasArity(ID->TokenText, Args->size()))) { 494806c3fb27SDimitry Andric // Next, we insert the expanded tokens in the token stream at the 494906c3fb27SDimitry Andric // current position, and continue parsing. 495006c3fb27SDimitry Andric Unexpanded[ID] = std::move(UnexpandedLine); 495106c3fb27SDimitry Andric SmallVector<FormatToken *, 8> Expansion = 495206c3fb27SDimitry Andric Macros.expand(ID, std::move(Args)); 495306c3fb27SDimitry Andric if (!Expansion.empty()) 495406c3fb27SDimitry Andric FormatTok = Tokens->insertTokens(Expansion); 495506c3fb27SDimitry Andric 495606c3fb27SDimitry Andric LLVM_DEBUG({ 495706c3fb27SDimitry Andric llvm::dbgs() << "Expanded: "; 495806c3fb27SDimitry Andric for (const auto &T : Expansion) 495906c3fb27SDimitry Andric llvm::dbgs() << T->TokenText << " "; 496006c3fb27SDimitry Andric llvm::dbgs() << "\n"; 496106c3fb27SDimitry Andric }); 496206c3fb27SDimitry Andric } else { 496306c3fb27SDimitry Andric LLVM_DEBUG({ 496406c3fb27SDimitry Andric llvm::dbgs() << "Did not expand macro \"" << ID->TokenText 496506c3fb27SDimitry Andric << "\", because it was used "; 496606c3fb27SDimitry Andric if (Args) 496706c3fb27SDimitry Andric llvm::dbgs() << "with " << Args->size(); 496806c3fb27SDimitry Andric else 496906c3fb27SDimitry Andric llvm::dbgs() << "without"; 497006c3fb27SDimitry Andric llvm::dbgs() << " arguments, which doesn't match any definition.\n"; 497106c3fb27SDimitry Andric }); 497206c3fb27SDimitry Andric Tokens->setPosition(Position); 497306c3fb27SDimitry Andric FormatTok = ID; 497406c3fb27SDimitry Andric } 497506c3fb27SDimitry Andric } 497606c3fb27SDimitry Andric 49775f757f3fSDimitry Andric if (FormatTok->isNot(tok::comment)) { 49780b57cec5SDimitry Andric distributeComments(Comments, FormatTok); 49790b57cec5SDimitry Andric Comments.clear(); 49800b57cec5SDimitry Andric return; 49810b57cec5SDimitry Andric } 49820b57cec5SDimitry Andric 49830b57cec5SDimitry Andric Comments.push_back(FormatTok); 49840b57cec5SDimitry Andric } while (!eof()); 49850b57cec5SDimitry Andric 49860b57cec5SDimitry Andric distributeComments(Comments, nullptr); 49870b57cec5SDimitry Andric Comments.clear(); 49880b57cec5SDimitry Andric } 49890b57cec5SDimitry Andric 499006c3fb27SDimitry Andric namespace { 499106c3fb27SDimitry Andric template <typename Iterator> 499206c3fb27SDimitry Andric void pushTokens(Iterator Begin, Iterator End, 499306c3fb27SDimitry Andric llvm::SmallVectorImpl<FormatToken *> &Into) { 499406c3fb27SDimitry Andric for (auto I = Begin; I != End; ++I) { 499506c3fb27SDimitry Andric Into.push_back(I->Tok); 499606c3fb27SDimitry Andric for (const auto &Child : I->Children) 499706c3fb27SDimitry Andric pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into); 499806c3fb27SDimitry Andric } 499906c3fb27SDimitry Andric } 500006c3fb27SDimitry Andric } // namespace 500106c3fb27SDimitry Andric 500206c3fb27SDimitry Andric std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> 500306c3fb27SDimitry Andric UnwrappedLineParser::parseMacroCall() { 500406c3fb27SDimitry Andric std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args; 500506c3fb27SDimitry Andric assert(Line->Tokens.empty()); 500606c3fb27SDimitry Andric nextToken(); 50075f757f3fSDimitry Andric if (FormatTok->isNot(tok::l_paren)) 500806c3fb27SDimitry Andric return Args; 500906c3fb27SDimitry Andric unsigned Position = Tokens->getPosition(); 501006c3fb27SDimitry Andric FormatToken *Tok = FormatTok; 501106c3fb27SDimitry Andric nextToken(); 501206c3fb27SDimitry Andric Args.emplace(); 501306c3fb27SDimitry Andric auto ArgStart = std::prev(Line->Tokens.end()); 501406c3fb27SDimitry Andric 501506c3fb27SDimitry Andric int Parens = 0; 501606c3fb27SDimitry Andric do { 501706c3fb27SDimitry Andric switch (FormatTok->Tok.getKind()) { 501806c3fb27SDimitry Andric case tok::l_paren: 501906c3fb27SDimitry Andric ++Parens; 502006c3fb27SDimitry Andric nextToken(); 502106c3fb27SDimitry Andric break; 502206c3fb27SDimitry Andric case tok::r_paren: { 502306c3fb27SDimitry Andric if (Parens > 0) { 502406c3fb27SDimitry Andric --Parens; 502506c3fb27SDimitry Andric nextToken(); 502606c3fb27SDimitry Andric break; 502706c3fb27SDimitry Andric } 502806c3fb27SDimitry Andric Args->push_back({}); 502906c3fb27SDimitry Andric pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back()); 503006c3fb27SDimitry Andric nextToken(); 503106c3fb27SDimitry Andric return Args; 503206c3fb27SDimitry Andric } 503306c3fb27SDimitry Andric case tok::comma: { 503406c3fb27SDimitry Andric if (Parens > 0) { 503506c3fb27SDimitry Andric nextToken(); 503606c3fb27SDimitry Andric break; 503706c3fb27SDimitry Andric } 503806c3fb27SDimitry Andric Args->push_back({}); 503906c3fb27SDimitry Andric pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back()); 504006c3fb27SDimitry Andric nextToken(); 504106c3fb27SDimitry Andric ArgStart = std::prev(Line->Tokens.end()); 504206c3fb27SDimitry Andric break; 504306c3fb27SDimitry Andric } 504406c3fb27SDimitry Andric default: 504506c3fb27SDimitry Andric nextToken(); 504606c3fb27SDimitry Andric break; 504706c3fb27SDimitry Andric } 504806c3fb27SDimitry Andric } while (!eof()); 504906c3fb27SDimitry Andric Line->Tokens.resize(1); 505006c3fb27SDimitry Andric Tokens->setPosition(Position); 505106c3fb27SDimitry Andric FormatTok = Tok; 505206c3fb27SDimitry Andric return {}; 505306c3fb27SDimitry Andric } 505406c3fb27SDimitry Andric 50550b57cec5SDimitry Andric void UnwrappedLineParser::pushToken(FormatToken *Tok) { 50560b57cec5SDimitry Andric Line->Tokens.push_back(UnwrappedLineNode(Tok)); 50570b57cec5SDimitry Andric if (MustBreakBeforeNextToken) { 50580b57cec5SDimitry Andric Line->Tokens.back().Tok->MustBreakBefore = true; 5059297eecfbSDimitry Andric Line->Tokens.back().Tok->MustBreakBeforeFinalized = true; 50600b57cec5SDimitry Andric MustBreakBeforeNextToken = false; 50610b57cec5SDimitry Andric } 50620b57cec5SDimitry Andric } 50630b57cec5SDimitry Andric 50640b57cec5SDimitry Andric } // end namespace format 50650b57cec5SDimitry Andric } // end namespace clang 5066