xref: /freebsd-src/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp (revision 6c05f3a74f30934ee60919cc97e16ec69b542b06)
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