21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/Support/Debug.h"
24#include "llvm/Support/raw_os_ostream.h"
25#include "llvm/Support/raw_ostream.h"
29#define DEBUG_TYPE "format-parser"
36void printLine(llvm::raw_ostream &OS,
const UnwrappedLine &
Line,
37 StringRef Prefix =
"",
bool PrintText =
false) {
38 OS << Prefix <<
"Line(" <<
Line.Level <<
", FSC=" <<
Line.FirstStartColumn
39 <<
")" << (
Line.InPPDirective ?
" MACRO" :
"") <<
": ";
41 for (std::list<UnwrappedLineNode>::const_iterator I =
Line.Tokens.begin(),
42 E =
Line.Tokens.end();
48 OS << I->Tok->Tok.getName() <<
"["
49 <<
"T=" << (
unsigned)I->Tok->getType()
50 <<
", OC=" << I->Tok->OriginalColumn <<
", \"" << I->Tok->TokenText
52 for (
const auto *CI = I->Children.begin(), *CE = I->Children.end();
55 printLine(OS, *CI, (Prefix +
" ").str());
63[[maybe_unused]]
static void printDebugInfo(
const UnwrappedLine &
Line) {
64 printLine(llvm::dbgs(),
Line);
67class ScopedDeclarationState {
69 ScopedDeclarationState(UnwrappedLine &
Line, llvm::BitVector &Stack,
70 bool MustBeDeclaration)
72 Line.MustBeDeclaration = MustBeDeclaration;
73 Stack.push_back(MustBeDeclaration);
75 ~ScopedDeclarationState() {
78 Line.MustBeDeclaration = Stack.back();
80 Line.MustBeDeclaration =
true;
85 llvm::BitVector &Stack;
91 llvm::raw_os_ostream OS(Stream);
100 bool SwitchToPreprocessorLines =
false,
101 bool DiscardLines =
false)
102 : Parser(Parser), OriginalLines(Parser.CurrentLines),
103 DiscardLines(DiscardLines) {
104 if (SwitchToPreprocessorLines)
105 Parser.CurrentLines = &Parser.PreprocessorDirectives;
106 else if (!Parser.Line->Tokens.empty())
107 Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
108 OriginalNumLines = Parser.CurrentLines->size();
109 PreBlockLine = std::move(Parser.Line);
110 Parser.Line = std::make_unique<UnwrappedLine>();
111 Parser.Line->Level = PreBlockLine->Level;
112 Parser.Line->PPLevel = PreBlockLine->PPLevel;
113 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
114 Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
115 Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel;
119 if (!Parser.Line->Tokens.empty())
120 Parser.addUnwrappedLine();
121 assert(Parser.Line->Tokens.empty());
123 Parser.CurrentLines->truncate(OriginalNumLines);
124 Parser.Line = std::move(PreBlockLine);
125 if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
126 Parser.PP.AtEndOfPPLine =
true;
127 Parser.CurrentLines = OriginalLines;
133 std::unique_ptr<UnwrappedLine> PreBlockLine;
135 size_t OriginalNumLines;
144 Style.BraceWrapping.AfterControlStatement ==
146 Style.BraceWrapping.IndentBraces) {}
148 bool WrapBrace,
bool IndentBrace)
149 : LineLevel(LineLevel), OldLineLevel(LineLevel) {
151 Parser->addUnwrappedLine();
159 unsigned OldLineLevel;
166 llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
168 : Line(new
UnwrappedLine), CurrentLines(&Lines), Style(Style),
170 Keywords(Keywords), CommentPragmasRegex(Style.CommentPragmas),
171 Tokens(
nullptr), Callback(Callback), AllTokens(Tokens),
172 PP(getIncludeGuardState(Style.IndentPPDirectives)),
173 FirstStartColumn(FirstStartColumn),
174 Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}
176void UnwrappedLineParser::reset() {
178 PP.IncludeGuard = getIncludeGuardState(Style.IndentPPDirectives);
179 PP.IncludeGuardToken =
nullptr;
180 ParsedPPDirectives.clear();
182 CommentsBeforeNextToken.clear();
184 PP.AtEndOfPPLine =
false;
185 IsDecltypeAutoFunction =
false;
186 PreprocessorDirectives.clear();
187 CurrentLines = &Lines;
188 DeclarationScopeStack.clear();
189 NestedTooDeep.clear();
190 NestedLambdas.clear();
192 Line->FirstStartColumn = FirstStartColumn;
194 if (!Unexpanded.empty())
196 Token->MacroCtx.reset();
197 CurrentExpandedLines.clear();
198 ExpandedLines.clear();
206 Line->FirstStartColumn = FirstStartColumn;
208 LLVM_DEBUG(llvm::dbgs() <<
"----\n");
210 Tokens = &TokenSource;
218 if (PP.IncludeGuard == IG_Found) {
219 for (
auto &Line : Lines)
220 if (Line.InPPDirective && Line.Level > 0)
226 pushToken(FormatTok);
231 if (!ExpandedLines.empty()) {
232 LLVM_DEBUG(llvm::dbgs() <<
"Expanded lines:\n");
233 for (
const auto &Line : Lines) {
234 if (!Line.Tokens.empty()) {
235 auto it = ExpandedLines.find(Line.Tokens.begin()->Tok);
236 if (it != ExpandedLines.end()) {
237 for (
const auto &Expanded : it->second) {
238 LLVM_DEBUG(printDebugInfo(Expanded));
239 Callback.consumeUnwrappedLine(Expanded);
244 LLVM_DEBUG(printDebugInfo(Line));
245 Callback.consumeUnwrappedLine(Line);
247 Callback.finishRun();
250 LLVM_DEBUG(llvm::dbgs() <<
"Unwrapped lines:\n");
252 LLVM_DEBUG(printDebugInfo(Line));
253 Callback.consumeUnwrappedLine(Line);
255 Callback.finishRun();
257 while (!PP.LevelBranchIndex.empty() &&
258 PP.LevelBranchIndex.back() + 1 >= PP.LevelBranchCount.back()) {
259 PP.LevelBranchIndex.resize(PP.LevelBranchIndex.size() - 1);
260 PP.LevelBranchCount.resize(PP.LevelBranchCount.size() - 1);
262 if (!PP.LevelBranchIndex.empty()) {
263 ++PP.LevelBranchIndex.back();
264 assert(PP.LevelBranchIndex.size() == PP.LevelBranchCount.size());
265 assert(PP.LevelBranchIndex.back() <= PP.LevelBranchCount.back());
267 }
while (!PP.LevelBranchIndex.empty());
270void UnwrappedLineParser::parseFile() {
273 bool MustBeDeclaration = !
Line->InPPDirective && !Style.isJavaScript();
274 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
276 if (Style.isTextProto() || (Style.isJson() && FormatTok->
IsFirst))
290 if (Style.isTextProto() && !CommentsBeforeNextToken.empty())
296void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {
306 parseCSharpGenericTypeConstraint();
315void UnwrappedLineParser::parseCSharpAttribute() {
316 int UnpairedSquareBrackets = 1;
318 switch (FormatTok->Tok.getKind()) {
321 --UnpairedSquareBrackets;
322 if (UnpairedSquareBrackets == 0) {
328 ++UnpairedSquareBrackets;
338bool UnwrappedLineParser::precededByCommentOrPPDirective()
const {
339 if (!Lines.empty() && Lines.back().InPPDirective)
353bool UnwrappedLineParser::parseLevel(
const FormatToken *OpeningBrace,
356 bool *SeenExplicitAccessModifier) {
357 const bool InRequiresExpression =
358 OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
359 const bool IsPrecededByCommentOrPPDirective =
360 !Style.RemoveBracesLLVM || precededByCommentOrPPDirective();
362 bool HasDoWhile =
false;
363 bool HasLabel =
false;
364 unsigned StatementCount = 0;
365 bool SwitchLabelEncountered =
false;
368 if (FormatTok->isAttribute()) {
370 if (FormatTok->is(tok::l_paren))
375 if (FormatTok->is(TT_MacroBlockBegin))
377 else if (FormatTok->is(TT_MacroBlockEnd))
380 auto ParseDefault = [
this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
381 &HasLabel, &StatementCount,
382 SeenExplicitAccessModifier] {
383 if (SeenExplicitAccessModifier && !*SeenExplicitAccessModifier) {
384 const bool IsQtAccessLabel =
385 FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
386 Keywords.kw_slots, Keywords.kw_qslots) &&
387 Tokens->peekNextToken(
true)->is(tok::colon);
388 if (FormatTok->isAccessSpecifierKeyword() || IsQtAccessLabel) {
390 *SeenExplicitAccessModifier =
true;
393 parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,
394 HasDoWhile ?
nullptr : &HasDoWhile,
395 HasLabel ?
nullptr : &HasLabel);
397 assert(StatementCount > 0 &&
"StatementCount overflow!");
406 if (InRequiresExpression) {
407 FormatTok->setFinalizedType(TT_CompoundRequirementLBrace);
408 }
else if (FormatTok->Previous &&
409 FormatTok->Previous->ClosesRequiresClause) {
415 if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {
416 if (tryToParseBracedList())
418 FormatTok->setFinalizedType(TT_BlockLBrace);
422 assert(StatementCount > 0 &&
"StatementCount overflow!");
427 if (!Style.RemoveBracesLLVM || Line->InPPDirective ||
428 OpeningBrace->isNoneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
431 if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||
432 HasDoWhile || IsPrecededByCommentOrPPDirective ||
433 precededByCommentOrPPDirective()) {
437 if (
Next->is(tok::comment) &&
Next->NewlinesBefore == 0)
440 *IfLeftBrace = IfLBrace;
446 case tok::kw_default: {
447 unsigned StoredPosition = Tokens->getPosition();
448 auto *
Next = Tokens->getNextNonComment();
449 FormatTok = Tokens->setPosition(StoredPosition);
450 if (
Next->isNoneOf(tok::colon, tok::arrow)) {
453 parseStructuralElement();
461 (Style.isJavaScript() && Line->MustBeDeclaration)) {
469 if (!SwitchLabelEncountered &&
470 (Style.IndentCaseLabels ||
471 (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||
472 (Line->InPPDirective && Line->Level == 1))) {
475 SwitchLabelEncountered =
true;
476 parseStructuralElement();
479 if (Style.isCSharp()) {
481 parseCSharpAttribute();
484 if (handleCppAttributes())
496void UnwrappedLineParser::calculateBraceTypes(
bool ExpectClassBody) {
501 unsigned StoredPosition = Tokens->getPosition();
511 SmallVector<StackEntry, 8> LBraceStack;
512 assert(
Tok->is(tok::l_brace));
515 auto *NextTok = Tokens->getNextNonComment();
517 if (!Line->InMacroBody && !Style.isTableGen()) {
519 while (NextTok->is(tok::hash)) {
520 NextTok = Tokens->getNextToken();
521 if (NextTok->isOneOf(tok::pp_not_keyword, tok::pp_define))
524 NextTok = Tokens->getNextToken();
525 }
while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));
527 while (NextTok->is(tok::comment))
528 NextTok = Tokens->getNextToken();
532 switch (
Tok->Tok.getKind()) {
534 if (Style.isJavaScript() && PrevTok) {
535 if (PrevTok->isOneOf(tok::colon, tok::less)) {
546 }
else if (PrevTok->is(tok::r_paren)) {
550 }
else if (Style.isJava() && PrevTok && PrevTok->is(tok::arrow)) {
555 LBraceStack.push_back({
Tok, PrevTok});
558 if (LBraceStack.empty())
560 if (
auto *LBrace = LBraceStack.back().Tok; LBrace->is(
BK_Unknown)) {
561 bool ProbablyBracedList =
false;
563 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
564 }
else if (LBrace->isNot(TT_EnumLBrace)) {
567 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
568 NextTok->OriginalColumn == 0;
578 ProbablyBracedList = LBrace->is(TT_BracedListLBrace);
580 ProbablyBracedList = ProbablyBracedList ||
581 (Style.isJavaScript() &&
582 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
585 ProbablyBracedList ||
586 (IsCpp && (PrevTok->Tok.isLiteral() ||
587 NextTok->isOneOf(tok::l_paren, tok::arrow)));
594 ProbablyBracedList ||
595 NextTok->isOneOf(tok::comma, tok::period, tok::colon,
596 tok::r_paren, tok::r_square, tok::ellipsis);
601 ProbablyBracedList ||
602 (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&
603 LBraceStack.back().PrevTok->isOneOf(tok::identifier,
607 ProbablyBracedList ||
608 (NextTok->is(tok::identifier) &&
609 PrevTok->isNoneOf(tok::semi, tok::r_brace, tok::l_brace));
611 ProbablyBracedList = ProbablyBracedList ||
612 (NextTok->is(tok::semi) &&
613 (!ExpectClassBody || LBraceStack.size() != 1));
616 ProbablyBracedList ||
617 (NextTok->isBinaryOperator() && !NextIsObjCMethod);
619 if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
622 NextTok = Tokens->getNextToken();
623 ProbablyBracedList = NextTok->isNot(tok::l_square);
627 if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
628 !FormatTok->Previous && NextTok->is(tok::eof) &&
632 PrevTok->isNoneOf(tok::semi,
BK_Block, tok::colon)) {
633 ProbablyBracedList =
true;
637 Tok->setBlockKind(BlockKind);
638 LBrace->setBlockKind(BlockKind);
640 LBraceStack.pop_back();
642 case tok::identifier:
643 if (
Tok->isNot(TT_StatementMacro))
654 if (!LBraceStack.empty() && LBraceStack.back().Tok->is(
BK_Unknown))
655 LBraceStack.back().Tok->setBlockKind(
BK_Block);
663 }
while (
Tok->isNot(tok::eof) && !LBraceStack.empty());
666 for (
const auto &Entry : LBraceStack)
670 FormatTok = Tokens->setPosition(StoredPosition);
674void UnwrappedLineParser::setPreviousRBraceType(
TokenType Type) {
675 if (
auto Prev = FormatTok->getPreviousNonComment();
676 Prev && Prev->is(tok::r_brace)) {
677 Prev->setFinalizedType(
Type);
684 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
687size_t UnwrappedLineParser::computePPHash()
const {
689 for (
const auto &i : PP.Stack) {
700bool UnwrappedLineParser::mightFitOnOneLine(
702 const auto ColumnLimit = Style.ColumnLimit;
703 if (ColumnLimit == 0)
706 auto &Tokens = ParsedLine.Tokens;
707 assert(!Tokens.empty());
709 const auto *LastToken = Tokens.back().Tok;
712 SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());
715 for (
const auto &Token : Tokens) {
717 auto &SavedToken = SavedTokens[Index++];
719 SavedToken.Tok->copyFrom(*Token.Tok);
720 SavedToken.Children = std::move(Token.Children);
723 AnnotatedLine
Line(ParsedLine);
724 assert(Line.Last == LastToken);
726 TokenAnnotator Annotator(Style, Keywords);
727 Annotator.annotate(Line);
728 Annotator.calculateFormattingInformation(Line);
730 auto Length = LastToken->TotalLength;
732 assert(OpeningBrace != Tokens.front().Tok);
733 if (
auto Prev = OpeningBrace->Previous;
734 Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
735 Length -= ColumnLimit;
737 Length -= OpeningBrace->TokenText.size() + 1;
740 if (
const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
741 assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
742 Length -= FirstToken->TokenText.size() + 1;
746 for (
auto &Token : Tokens) {
747 const auto &SavedToken = SavedTokens[Index++];
748 Token.Tok->copyFrom(*SavedToken.Tok);
749 Token.Children = std::move(SavedToken.Children);
750 delete SavedToken.Tok;
754 assert(!Line.InMacroBody);
755 assert(!Line.InPPDirective);
756 return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
760 bool MustBeDeclaration,
unsigned AddLevels,
bool MunchSemi,
bool KeepBraces,
761 IfStmtKind *IfKind,
bool UnindentWhitesmithsBraces,
762 bool IndentAfterExplicitAccessModifier) {
763 auto HandleVerilogBlockLabel = [
this]() {
765 if (Style.isVerilog() && FormatTok->is(tok::colon)) {
767 if (Keywords.isVerilogIdentifier(*FormatTok))
774 const bool VerilogHierarchy =
775 Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);
776 assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
777 (Style.isVerilog() &&
778 (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
779 "'{' or macro block token expected");
781 const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
782 auto Index = CurrentLines->size();
783 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
786 const bool IsWhitesmiths =
791 if (!VerilogHierarchy && AddLevels > 0 && IsWhitesmiths)
794 size_t PPStartHash = computePPHash();
796 const unsigned InitialLevel = Line->Level;
797 if (VerilogHierarchy) {
798 AddLevels += parseVerilogHierarchyHeader();
800 nextToken(AddLevels);
801 HandleVerilogBlockLabel();
805 if (Line->Level > 300)
808 if (MacroBlock && FormatTok->is(tok::l_paren))
811 size_t NbPreprocessorDirectives =
812 !parsingPPDirective() ? PreprocessorDirectives.size() : 0;
814 size_t OpeningLineIndex =
815 CurrentLines->empty()
817 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
822 if (UnindentWhitesmithsBraces)
825 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
831 Line->Level += AddLevels - (IsWhitesmiths ? 1 : 0);
834 bool SeenExplicitAccessModifier =
false;
835 const bool SimpleBlock =
836 parseLevel(
Tok, IfKind, &IfLBrace,
837 IndentAfterExplicitAccessModifier ? &SeenExplicitAccessModifier
843 if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)
844 : FormatTok->isNot(tok::r_brace)) {
845 Line->Level = InitialLevel;
846 FormatTok->setBlockKind(BK_Block);
850 if (FormatTok->is(tok::r_brace)) {
851 FormatTok->setBlockKind(BK_Block);
852 if (Tok->is(TT_NamespaceLBrace))
853 FormatTok->setFinalizedType(TT_NamespaceRBrace);
856 const bool IsFunctionRBrace =
857 FormatTok->is(tok::r_brace) &&
Tok->is(TT_FunctionLBrace);
859 auto RemoveBraces = [=]()
mutable {
862 assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
863 assert(FormatTok->is(tok::r_brace));
864 const bool WrappedOpeningBrace = !Tok->Previous;
865 if (WrappedOpeningBrace && FollowedByComment)
867 const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
868 if (KeepBraces && !HasRequiredIfBraces)
870 if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
871 const FormatToken *Previous = Tokens->getPreviousToken();
873 if (Previous->is(tok::r_brace) && !Previous->Optional)
876 assert(!CurrentLines->empty());
877 auto &LastLine = CurrentLines->back();
878 if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
880 if (
Tok->is(TT_ElseLBrace))
882 if (WrappedOpeningBrace) {
887 return mightFitOnOneLine((*CurrentLines)[Index],
Tok);
889 if (RemoveBraces()) {
890 Tok->MatchingParen = FormatTok;
891 FormatTok->MatchingParen =
Tok;
894 size_t PPEndHash = computePPHash();
896 if (SeenExplicitAccessModifier)
899 nextToken(-AddLevels);
904 if (Style.RemoveSemicolon && IsFunctionRBrace) {
905 while (FormatTok->is(tok::semi)) {
906 FormatTok->Optional =
true;
911 HandleVerilogBlockLabel();
913 if (MacroBlock && FormatTok->is(tok::l_paren))
916 Line->Level = InitialLevel;
918 if (FormatTok->is(tok::kw_noexcept)) {
923 if (FormatTok->is(tok::arrow)) {
927 parseStructuralElement();
930 if (MunchSemi && FormatTok->is(tok::semi))
933 if (PPStartHash == PPEndHash) {
934 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
937 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
938 CurrentLines->size() - 1;
948 if (
Line.Tokens.size() < 4)
950 auto I =
Line.Tokens.begin();
951 if (I->Tok->TokenText !=
"goog")
954 if (I->Tok->isNot(tok::period))
957 if (I->Tok->TokenText !=
"scope")
960 return I->Tok->is(tok::l_paren);
969 if (
Line.Tokens.size() < 3)
971 auto I =
Line.Tokens.begin();
972 if (I->Tok->isNot(tok::l_paren))
978 return I->Tok->is(tok::l_paren);
984 bool IsJavaRecord =
false) {
986 return Style.BraceWrapping.AfterClass;
989 if (InitialToken.
is(TT_NamespaceMacro))
990 Kind = tok::kw_namespace;
992 const bool WrapRecordAllowed =
995 Style.BraceWrapping.SplitEmptyRecord;
998 case tok::kw_namespace:
999 return Style.BraceWrapping.AfterNamespace;
1001 return Style.BraceWrapping.AfterClass && WrapRecordAllowed;
1003 return Style.BraceWrapping.AfterUnion && WrapRecordAllowed;
1004 case tok::kw_struct:
1005 return Style.BraceWrapping.AfterStruct && WrapRecordAllowed;
1007 return Style.BraceWrapping.AfterEnum;
1013void UnwrappedLineParser::parseChildBlock() {
1014 assert(FormatTok->is(tok::l_brace));
1015 FormatTok->setBlockKind(BK_Block);
1019 bool SkipIndent = (Style.isJavaScript() &&
1020 (isGoogScope(*
Line) || isIIFE(*
Line, Keywords)));
1021 ScopedLineState LineState(*
this);
1022 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
1024 Line->Level += SkipIndent ? 0 : 1;
1025 parseLevel(OpeningBrace);
1026 flushComments(isOnNewLine(*FormatTok));
1027 Line->Level -= SkipIndent ? 0 : 1;
1032void UnwrappedLineParser::parsePPDirective() {
1033 assert(FormatTok->is(tok::hash) &&
"'#' expected");
1034 ScopedMacroState MacroState(*
Line, Tokens, FormatTok);
1038 if (!FormatTok->Tok.getIdentifierInfo()) {
1043 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
1044 case tok::pp_define:
1051 case tok::pp_ifndef:
1055 case tok::pp_elifdef:
1056 case tok::pp_elifndef:
1063 case tok::pp_pragma:
1067 case tok::pp_warning:
1069 if (!
eof() && Style.isCpp())
1070 FormatTok->setFinalizedType(TT_AfterPPDirective);
1078void UnwrappedLineParser::conditionalCompilationCondition(
bool Unreachable) {
1079 size_t Line = CurrentLines->size();
1080 if (CurrentLines == &PreprocessorDirectives)
1081 Line += Lines.size();
1084 (!PP.Stack.empty() && PP.Stack.back().Kind == PP_Unreachable)) {
1085 PP.Stack.push_back({PP_Unreachable,
Line});
1087 PP.Stack.push_back({PP_Conditional,
Line});
1091void UnwrappedLineParser::conditionalCompilationStart(
bool Unreachable) {
1093 assert(PP.BranchLevel >= 0 &&
1094 PP.BranchLevel <= (
int)PP.LevelBranchIndex.size());
1095 if (PP.BranchLevel == (
int)PP.LevelBranchIndex.size()) {
1096 PP.LevelBranchIndex.push_back(0);
1097 PP.LevelBranchCount.push_back(0);
1099 PP.ChainBranchIndex.push(Unreachable ? -1 : 0);
1100 bool Skip = PP.LevelBranchIndex[PP.BranchLevel] > 0;
1101 conditionalCompilationCondition(Unreachable ||
Skip);
1104void UnwrappedLineParser::conditionalCompilationAlternative() {
1105 if (!PP.Stack.empty())
1106 PP.Stack.pop_back();
1107 assert(PP.BranchLevel < (
int)PP.LevelBranchIndex.size());
1108 if (!PP.ChainBranchIndex.empty())
1109 ++PP.ChainBranchIndex.top();
1110 conditionalCompilationCondition(
1111 PP.BranchLevel >= 0 && !PP.ChainBranchIndex.empty() &&
1112 PP.LevelBranchIndex[PP.BranchLevel] != PP.ChainBranchIndex.top());
1115void UnwrappedLineParser::conditionalCompilationEnd() {
1116 assert(PP.BranchLevel < (
int)PP.LevelBranchIndex.size());
1117 if (PP.BranchLevel >= 0 && !PP.ChainBranchIndex.empty()) {
1118 if (PP.ChainBranchIndex.top() + 1 > PP.LevelBranchCount[PP.BranchLevel])
1119 PP.LevelBranchCount[PP.BranchLevel] = PP.ChainBranchIndex.top() + 1;
1122 if (PP.BranchLevel > -1)
1124 if (!PP.ChainBranchIndex.empty())
1125 PP.ChainBranchIndex.pop();
1126 if (!PP.Stack.empty())
1127 PP.Stack.pop_back();
1130void UnwrappedLineParser::parsePPIf(
bool IfDef) {
1131 bool IfNDef = FormatTok->is(tok::pp_ifndef);
1133 bool Unreachable =
false;
1134 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText ==
"0"))
1136 if (IfDef && !IfNDef && FormatTok->TokenText ==
"SWIG")
1138 conditionalCompilationStart(Unreachable);
1142 bool MaybeIncludeGuard = IfNDef;
1143 if (PP.IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1144 for (
auto &
Line : Lines) {
1145 if (
Line.Tokens.front().Tok->isNot(tok::comment)) {
1146 MaybeIncludeGuard =
false;
1147 PP.IncludeGuard = IG_Rejected;
1155 if (PP.IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1156 PP.IncludeGuard = IG_IfNdefed;
1157 PP.IncludeGuardToken = IfCondition;
1161void UnwrappedLineParser::parsePPElse() {
1163 if (PP.IncludeGuard == IG_Defined && PP.BranchLevel == 0)
1164 PP.IncludeGuard = IG_Rejected;
1166 assert(PP.BranchLevel >= -1);
1167 if (PP.BranchLevel == -1)
1168 conditionalCompilationStart(
true);
1169 conditionalCompilationAlternative();
1175void UnwrappedLineParser::parsePPEndIf() {
1176 conditionalCompilationEnd();
1180void UnwrappedLineParser::parsePPDefine() {
1183 if (!FormatTok->Tok.getIdentifierInfo()) {
1184 PP.IncludeGuard = IG_Rejected;
1185 PP.IncludeGuardToken =
nullptr;
1190 bool MaybeIncludeGuard =
false;
1191 if (PP.IncludeGuard == IG_IfNdefed &&
1192 PP.IncludeGuardToken->TokenText == FormatTok->TokenText) {
1193 PP.IncludeGuard = IG_Defined;
1194 PP.IncludeGuardToken =
nullptr;
1195 for (
auto &
Line : Lines) {
1196 if (
Line.Tokens.front().Tok->isNoneOf(tok::comment, tok::hash)) {
1197 PP.IncludeGuard = IG_Rejected;
1201 MaybeIncludeGuard = PP.IncludeGuard == IG_Defined;
1209 FormatTok->Tok.setKind(tok::identifier);
1210 FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);
1214 if (MaybeIncludeGuard && !
eof())
1215 PP.IncludeGuard = IG_Rejected;
1217 if (FormatTok->is(tok::l_paren) && !FormatTok->hasWhitespaceBefore())
1220 Line->Level += PP.BranchLevel + 1;
1224 Line->PPLevel = PP.BranchLevel + (PP.IncludeGuard == IG_Defined ? 0 : 1);
1225 assert((
int)
Line->PPLevel >= 0);
1230 Line->InMacroBody =
true;
1232 if (!Style.SkipMacroDefinitionBody) {
1242 for (
auto *Comment : CommentsBeforeNextToken)
1243 Comment->Finalized =
true;
1246 FormatTok->Finalized =
true;
1247 FormatTok = Tokens->getNextToken();
1253void UnwrappedLineParser::parsePPPragma() {
1254 Line->InPragmaDirective =
true;
1258void UnwrappedLineParser::parsePPUnknown() {
1262 Line->Level += PP.BranchLevel + 1;
1272 return Tok.isNoneOf(tok::semi, tok::l_brace,
1275 tok::period, tok::periodstar, tok::arrow, tok::arrowstar,
1276 tok::less, tok::greater, tok::slash, tok::percent,
1277 tok::lessless, tok::greatergreater, tok::equal,
1278 tok::plusequal, tok::minusequal, tok::starequal,
1279 tok::slashequal, tok::percentequal, tok::ampequal,
1280 tok::pipeequal, tok::caretequal, tok::greatergreaterequal,
1293 return FormatTok->
is(tok::identifier) &&
1308 FormatTok->
isOneOf(tok::kw_true, tok::kw_false) ||
1319 tok::kw_if, tok::kw_else,
1321 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
1323 tok::kw_switch, tok::kw_case,
1325 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.
kw_finally,
1327 tok::kw_const, tok::kw_class, Keywords.
kw_var, Keywords.
kw_let,
1335 return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
1336 tok::kw_unsigned, tok::kw_float, tok::kw_double,
1353 if (FuncName->
isNot(tok::identifier))
1361 Tok->isNoneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
1365 if (
Next->isNot(tok::star) && !
Next->Tok.getIdentifierInfo())
1369 if (!
Tok ||
Tok->isNot(tok::r_paren))
1373 if (!
Tok ||
Tok->isNot(tok::identifier))
1376 return Tok->Previous &&
Tok->Previous->isOneOf(tok::l_paren, tok::comma);
1379bool UnwrappedLineParser::parseModuleDecl() {
1381 assert(FormatTok->is(Keywords.kw_module));
1389 if (FormatTok->isNot(tok::identifier))
1392 for (nextToken(); FormatTok->isNoneOf(tok::semi, tok::eof); nextToken())
1393 if (FormatTok->is(tok::colon))
1394 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1397 Line->IsModuleOrImportDecl =
true;
1402bool UnwrappedLineParser::parseImportDecl() {
1404 assert(FormatTok->is(Keywords.kw_import) &&
"'import' expected");
1412 if (FormatTok->is(tok::colon)) {
1413 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1416 if (FormatTok->isNoneOf(tok::identifier, tok::less, tok::string_literal))
1419 for (; FormatTok->isNoneOf(tok::semi, tok::eof); nextToken()) {
1421 if (FormatTok->is(tok::less)) {
1422 for (nextToken(); FormatTok->isNoneOf(tok::greater, tok::semi, tok::eof);
1426 FormatTok->setFinalizedType(TT_ImplicitStringLiteral);
1432 Line->IsModuleOrImportDecl =
true;
1444void UnwrappedLineParser::readTokenWithJavaScriptASI() {
1450 CommentsBeforeNextToken.empty()
1451 ?
Next->NewlinesBefore == 0
1452 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
1457 bool PreviousStartsTemplateExpr =
1459 if (PreviousMustBeValue ||
Previous->is(tok::r_paren)) {
1462 bool HasAt = llvm::any_of(
Line->Tokens, [](UnwrappedLineNode &LineNode) {
1463 return LineNode.Tok->is(tok::at);
1468 if (
Next->is(tok::exclaim) && PreviousMustBeValue)
1469 return addUnwrappedLine();
1471 bool NextEndsTemplateExpr =
1472 Next->is(TT_TemplateString) &&
Next->TokenText.starts_with(
"}");
1473 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
1474 (PreviousMustBeValue ||
1475 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
1476 tok::minusminus))) {
1477 return addUnwrappedLine();
1479 if ((PreviousMustBeValue ||
Previous->is(tok::r_paren)) &&
1481 return addUnwrappedLine();
1485void UnwrappedLineParser::parseStructuralElement(
1486 const FormatToken *OpeningBrace, IfStmtKind *IfKind,
1487 FormatToken **IfLeftBrace,
bool *HasDoWhile,
bool *HasLabel) {
1488 if (Style.isTableGen() && FormatTok->is(tok::pp_include)) {
1490 if (FormatTok->is(tok::string_literal))
1497 while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
1499 }
else if (Style.isVerilog()) {
1501 while (FormatTok->is(tok::l_paren) &&
1502 Tokens->peekNextToken()->is(tok::star)) {
1505 skipVerilogQualifiers();
1507 if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
1508 Keywords.kw_unique0)) {
1512 if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {
1513 parseForOrWhileLoop(
false);
1516 if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {
1517 parseForOrWhileLoop();
1520 if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
1521 Keywords.kw_assume, Keywords.kw_cover)) {
1522 parseIfThenElse(IfKind,
false,
true);
1528 if (FormatTok->isAccessSpecifierKeyword()) {
1529 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
1532 parseAccessSpecifier();
1535 switch (FormatTok->Tok.getKind()) {
1540 bool DoNotFormat =
false;
1545 FormatTok->isOneOf(tok::kw_volatile, tok::kw_inline, tok::kw_goto)) {
1550 if (FormatTok->is(tok::l_brace)) {
1551 FormatTok->setFinalizedType(TT_InlineASMBrace);
1552 OpenType = tok::l_brace;
1553 CloseType = tok::r_brace;
1555 }
else if (FormatTok->is(tok::l_paren)) {
1556 OpenType = tok::l_paren;
1557 CloseType = tok::r_paren;
1558 FormatTok->setFinalizedType(TT_InlineASMParen);
1566 while (FormatTok && !
eof()) {
1567 if (FormatTok->is(OpenType)) {
1569 }
else if (FormatTok->is(CloseType)) {
1571 if (NestLevel < 1) {
1572 FormatTok->setFinalizedType(OpenTok->getType());
1578 FormatTok->Finalized =
true;
1584 case tok::kw_namespace:
1588 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1599 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1603 parseForOrWhileLoop();
1606 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1614 case tok::kw_switch:
1615 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1621 case tok::kw_default: {
1623 if (Style.isVerilog())
1625 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1631 if (FormatTok->is(tok::colon)) {
1632 FormatTok->setFinalizedType(TT_CaseLabelColon);
1636 if (FormatTok->is(tok::arrow)) {
1637 FormatTok->setFinalizedType(TT_CaseLabelArrow);
1638 Default->setFinalizedType(TT_SwitchExpressionLabel);
1651 if (Style.isVerilog()) {
1656 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1665 if (FormatTok->is(tok::kw_case))
1670 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1676 case tok::kw_extern:
1677 if (Style.isVerilog()) {
1680 parseVerilogExtern();
1684 if (FormatTok->is(tok::string_literal)) {
1686 if (FormatTok->is(tok::l_brace)) {
1687 if (Style.BraceWrapping.AfterExternBlock)
1691 unsigned AddLevels =
1693 (Style.BraceWrapping.AfterExternBlock &&
1694 Style.IndentExternBlock ==
1698 parseBlock(
true, AddLevels);
1704 case tok::kw_export:
1707 if (FormatTok->is(tok::kw_namespace)) {
1711 if (FormatTok->is(tok::l_brace)) {
1712 parseCppExportBlock();
1715 if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
1717 if (FormatTok->is(Keywords.kw_import) && parseImportDecl())
1721 if (Style.isJavaScript()) {
1722 parseJavaScriptEs6ImportExport();
1725 if (Style.isVerilog()) {
1726 parseVerilogExtern();
1730 case tok::kw_inline:
1732 if (FormatTok->is(tok::kw_namespace)) {
1737 case tok::identifier:
1738 if (FormatTok->is(TT_ForEachMacro)) {
1739 parseForOrWhileLoop();
1742 if (FormatTok->is(TT_MacroBlockBegin)) {
1743 parseBlock(
false, 1u,
1747 if (FormatTok->is(Keywords.kw_import)) {
1748 if (IsCpp && parseImportDecl())
1750 if (Style.isJavaScript()) {
1751 parseJavaScriptEs6ImportExport();
1756 if (FormatTok->is(tok::kw_public))
1758 if (FormatTok->isNot(tok::string_literal))
1761 if (FormatTok->is(tok::semi))
1766 if (Style.isVerilog()) {
1767 parseVerilogExtern();
1772 if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
1774 if (FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
1775 Keywords.kw_slots, Keywords.kw_qslots)) {
1777 if (FormatTok->is(tok::colon)) {
1783 if (FormatTok->is(TT_StatementMacro)) {
1784 parseStatementMacro();
1787 if (FormatTok->is(TT_NamespaceMacro)) {
1796 if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&
1797 Tokens->peekNextToken()->is(tok::colon) && !
Line->MustBeDeclaration) {
1799 if (!
Line->InMacroBody || CurrentLines->size() > 1)
1800 Line->Tokens.begin()->Tok->MustBreakBefore =
true;
1801 FormatTok->setFinalizedType(TT_GotoLabelColon);
1807 if (Style.isJava() && FormatTok->is(Keywords.kw_record)) {
1808 parseRecord(
false,
true);
1818 bool SeenEqual =
false;
1819 for (
const bool InRequiresExpression =
1820 OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
1821 TT_CompoundRequirementLBrace);
1824 switch (FormatTok->Tok.getKind()) {
1827 if (FormatTok->is(tok::l_brace)) {
1832 if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) {
1836 switch (
bool IsAutoRelease =
false; FormatTok->Tok.getObjCKeywordID()) {
1837 case tok::objc_public:
1838 case tok::objc_protected:
1839 case tok::objc_package:
1840 case tok::objc_private:
1841 return parseAccessSpecifier();
1842 case tok::objc_interface:
1843 case tok::objc_implementation:
1844 return parseObjCInterfaceOrImplementation();
1845 case tok::objc_protocol:
1846 if (parseObjCProtocol())
1851 case tok::objc_optional:
1852 case tok::objc_required:
1856 case tok::objc_autoreleasepool:
1857 IsAutoRelease =
true;
1859 case tok::objc_synchronized:
1861 if (!IsAutoRelease && FormatTok->is(tok::l_paren)) {
1865 if (FormatTok->is(tok::l_brace)) {
1866 if (Style.BraceWrapping.AfterControlStatement ==
1883 case tok::kw_requires: {
1885 bool ParsedClause = parseRequires(SeenEqual);
1906 if (!IsCpp && !Style.isVerilog()) {
1911 case tok::kw_typedef:
1913 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1914 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
1915 Keywords.kw_CF_CLOSED_ENUM,
1916 Keywords.kw_NS_CLOSED_ENUM)) {
1921 if (Style.isVerilog()) {
1926 if (Style.isTableGen()) {
1933 case tok::kw_struct:
1935 if (parseStructLike())
1938 case tok::kw_decltype:
1940 if (FormatTok->is(tok::l_paren)) {
1942 if (FormatTok->Previous &&
1943 FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
1945 Line->SeenDecltypeAuto =
true;
1952 if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class))
1954 if (Style.isJavaScript() && FormatTok &&
1955 FormatTok->Tok.getIdentifierInfo()) {
1968 case tok::string_literal:
1969 if (Style.isVerilog() && FormatTok->is(TT_VerilogProtected)) {
1970 FormatTok->Finalized =
true;
1977 case tok::l_paren: {
1984 Tokens->peekNextToken(
true),
1991 case tok::kw_operator:
1993 if (FormatTok->isBinaryOperator())
1997 const auto *Prev = FormatTok->getPreviousNonComment();
1999 if (Prev && Prev->is(tok::identifier))
2002 if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {
2005 if (FormatTok->is(tok::less)) {
2007 parseBracedList(
true);
2010 while (FormatTok->is(tok::star))
2014 if (FormatTok->is(tok::l_paren))
2017 if (FormatTok->is(tok::l_brace))
2022 if (InRequiresExpression)
2023 FormatTok->setFinalizedType(TT_BracedListLBrace);
2024 if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
2025 IsDecltypeAutoFunction =
Line->SeenDecltypeAuto;
2030 if (Style.isJava() &&
2031 Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
2034 if (Style.BraceWrapping.AfterControlStatement ==
2038 }
else if (Style.BraceWrapping.AfterFunction) {
2042 FormatTok->setFinalizedType(TT_FunctionLBrace);
2044 IsDecltypeAutoFunction =
false;
2052 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2058 if (Style.BraceWrapping.AfterFunction)
2062 case tok::identifier: {
2063 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&
2064 Line->MustBeDeclaration) {
2066 parseCSharpGenericTypeConstraint();
2069 if (FormatTok->is(TT_MacroBlockEnd)) {
2078 size_t TokenCount =
Line->Tokens.size();
2079 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&
2082 Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {
2083 tryToParseJSFunction();
2086 if ((Style.isJavaScript() || Style.isJava()) &&
2087 FormatTok->is(Keywords.kw_interface)) {
2088 if (Style.isJavaScript()) {
2093 unsigned StoredPosition = Tokens->getPosition();
2095 FormatTok = Tokens->setPosition(StoredPosition);
2106 if (Style.isVerilog()) {
2107 if (FormatTok->is(Keywords.kw_table)) {
2108 parseVerilogTable();
2111 if (Keywords.isVerilogBegin(*FormatTok) ||
2112 Keywords.isVerilogHierarchy(*FormatTok)) {
2119 if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
2120 if (parseStructLike())
2125 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
2126 parseStatementMacro();
2131 StringRef
Text = FormatTok->TokenText;
2138 if (Style.isJavaScript())
2141 auto OneTokenSoFar = [&]() {
2142 auto I =
Line->Tokens.begin(), E =
Line->Tokens.end();
2143 while (I != E && I->Tok->is(tok::comment))
2145 if (Style.isVerilog())
2146 while (I != E && I->Tok->is(tok::hash))
2148 return I != E && (++I == E);
2150 if (OneTokenSoFar()) {
2153 bool FunctionLike = FormatTok->is(tok::l_paren);
2157 bool FollowedByNewline =
2158 CommentsBeforeNextToken.empty()
2159 ? FormatTok->NewlinesBefore > 0
2160 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
2162 if (FollowedByNewline &&
2163 (
Text.size() >= 5 ||
2164 (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
2166 if (PreviousToken->isNot(TT_UntouchableMacroFunc))
2167 PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
2175 if ((Style.isJavaScript() || Style.isCSharp()) &&
2176 FormatTok->is(TT_FatArrow)) {
2177 tryToParseChildBlock();
2183 if (FormatTok->is(tok::l_brace)) {
2187 if (!Style.isJavaScript())
2188 FormatTok->setBlockKind(BK_BracedInit);
2191 if (Style.isTableGen() &&
2192 Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {
2193 FormatTok->setFinalizedType(TT_FunctionLBrace);
2194 parseBlock(
false, 1u,
2202 FormatTok->is(tok::less)) {
2204 parseBracedList(
true);
2211 if ((Style.isCSharp() &&
2212 (Tokens->peekNextToken()->isAccessSpecifierKeyword() ||
2214 FormatTok->endsSequence(tok::kw_new, tok::kw_operator)) {
2220 case tok::kw_switch:
2233 if (Style.isVerilog()) {
2238 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2245 case tok::kw_default:
2247 if (Style.isVerilog()) {
2248 if (FormatTok->is(tok::colon)) {
2252 if (FormatTok->is(Keywords.kw_clocking)) {
2258 parseVerilogCaseLabel();
2264 if (Style.isVerilog()) {
2265 parseVerilogCaseLabel();
2271 if (FormatTok->is(tok::l_brace))
2272 FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
2281bool UnwrappedLineParser::tryToParsePropertyAccessor() {
2282 assert(FormatTok->is(tok::l_brace));
2283 if (!Style.isCSharp())
2286 if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))
2294 unsigned int StoredPosition = Tokens->getPosition();
2300 bool HasSpecialAccessor =
false;
2301 bool IsTrivialPropertyAccessor =
true;
2304 if (
const bool IsAccessorKeyword =
2305 Tok->
isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set);
2306 IsAccessorKeyword ||
Tok->isAccessSpecifierKeyword() ||
2307 Tok->
isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {
2308 if (IsAccessorKeyword)
2309 HasSpecialAccessor =
true;
2310 else if (
Tok->
is(tok::l_square))
2312 Tok = Tokens->getNextToken();
2316 IsTrivialPropertyAccessor =
false;
2321 Tokens->setPosition(StoredPosition);
2327 Tokens->setPosition(StoredPosition);
2328 if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)
2332 switch (FormatTok->Tok.getKind()) {
2335 if (FormatTok->is(tok::equal)) {
2336 while (!
eof() && FormatTok->isNot(tok::semi))
2349 if (FormatTok->is(TT_FatArrow)) {
2353 }
while (!
eof() && FormatTok->isNot(tok::semi));
2362 if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,
2364 !IsTrivialPropertyAccessor) {
2376bool UnwrappedLineParser::tryToParseLambda() {
2377 assert(FormatTok->is(tok::l_square));
2383 if (!tryToParseLambdaIntroducer())
2387 bool InTemplateParameterList =
false;
2389 while (FormatTok->isNot(tok::l_brace)) {
2390 if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {
2394 switch (FormatTok->Tok.getKind()) {
2398 parseParens(TT_PointerOrReference);
2404 assert(FormatTok->Previous);
2405 if (FormatTok->Previous->is(tok::r_square))
2406 InTemplateParameterList =
true;
2411 case tok::kw_struct:
2413 case tok::kw_template:
2414 case tok::kw_typename:
2418 case tok::kw_constexpr:
2419 case tok::kw_consteval:
2422 case tok::identifier:
2423 case tok::numeric_constant:
2424 case tok::coloncolon:
2425 case tok::kw_mutable:
2426 case tok::kw_noexcept:
2427 case tok::kw_static:
2452 case tok::equalequal:
2453 case tok::exclaimequal:
2454 case tok::greaterequal:
2455 case tok::lessequal:
2461 if (Arrow || InTemplateParameterList) {
2470 case tok::kw_requires:
2471 parseRequiresClause();
2474 if (!InTemplateParameterList)
2483 FormatTok->setFinalizedType(TT_LambdaLBrace);
2484 LSquare.setFinalizedType(TT_LambdaLSquare);
2487 Arrow->setFinalizedType(TT_LambdaArrow);
2489 NestedLambdas.push_back(
Line->SeenDecltypeAuto);
2491 assert(!NestedLambdas.empty());
2492 NestedLambdas.pop_back();
2497bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
2502 const auto *PrevPrev =
Previous->getPreviousNonComment();
2503 if (
Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts))
2511 if (!PrevPrev || PrevPrev->isNoneOf(tok::greater, tok::r_paren))
2515 Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
2516 tok::kw_co_return)) {
2520 if (LeftSquare->isCppStructuredBinding(IsCpp))
2522 if (FormatTok->is(tok::l_square) ||
tok::isLiteral(FormatTok->Tok.getKind()))
2524 if (FormatTok->is(tok::r_square)) {
2526 if (
Next->is(tok::greater))
2533void UnwrappedLineParser::tryToParseJSFunction() {
2534 assert(FormatTok->is(Keywords.kw_function));
2535 if (FormatTok->is(Keywords.kw_async))
2541 if (FormatTok->is(tok::star)) {
2542 FormatTok->setFinalizedType(TT_OverloadedOperator);
2547 if (FormatTok->is(tok::identifier))
2550 if (FormatTok->isNot(tok::l_paren))
2556 if (FormatTok->is(tok::colon)) {
2562 if (FormatTok->is(tok::l_brace))
2563 tryToParseBracedList();
2565 while (FormatTok->isNoneOf(tok::l_brace, tok::semi) && !
eof())
2569 if (FormatTok->is(tok::semi))
2575bool UnwrappedLineParser::tryToParseBracedList() {
2576 if (FormatTok->is(BK_Unknown))
2577 calculateBraceTypes();
2578 assert(FormatTok->isNot(BK_Unknown));
2579 if (FormatTok->is(BK_Block))
2586bool UnwrappedLineParser::tryToParseChildBlock() {
2587 assert(Style.isJavaScript() || Style.isCSharp());
2588 assert(FormatTok->is(TT_FatArrow));
2593 if (FormatTok->isNot(tok::l_brace))
2599bool UnwrappedLineParser::parseBracedList(
bool IsAngleBracket,
bool IsEnum) {
2600 assert(!IsAngleBracket || !IsEnum);
2601 bool HasError =
false;
2606 if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
2607 tryToParseChildBlock()) {
2610 if (Style.isJavaScript()) {
2611 if (FormatTok->is(Keywords.kw_function)) {
2612 tryToParseJSFunction();
2615 if (FormatTok->is(tok::l_brace)) {
2617 if (tryToParseBracedList())
2622 if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
2624 FormatTok->setBlockKind(BK_Block);
2625 if (!Style.AllowShortEnumsOnASingleLine)
2631 switch (FormatTok->Tok.getKind()) {
2633 if (Style.isCSharp())
2642 if (Style.isJavaScript()) {
2643 if (FormatTok->is(tok::l_brace))
2651 FormatTok->setBlockKind(BK_BracedInit);
2652 if (!IsAngleBracket) {
2653 auto *Prev = FormatTok->Previous;
2654 if (Prev && Prev->is(tok::greater))
2655 Prev->setFinalizedType(TT_TemplateCloser);
2663 parseBracedList(
true);
2670 if (Style.isJavaScript()) {
2681 if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
2684 case tok::kw_requires:
2685 parseRequiresExpression();
2702bool UnwrappedLineParser::parseParens(TokenType StarAndAmpTokenType,
2704 assert(FormatTok->is(tok::l_paren) &&
"'(' expected.");
2705 auto *LParen = FormatTok;
2706 auto *Prev = FormatTok->Previous;
2707 bool SeenComma =
false;
2708 bool SeenEqual =
false;
2709 bool MightBeFoldExpr =
false;
2710 unsigned ExcessLess = 0;
2712 const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
2713 if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
2716 switch (FormatTok->Tok.getKind()) {
2718 if (parseParens(ExcessLess == 0 ? StarAndAmpTokenType : TT_Unknown,
2722 if (Style.isJava() && FormatTok->is(tok::l_brace))
2725 case tok::r_paren: {
2726 auto *RParen = FormatTok;
2729 auto OptionalParens = [&] {
2731 MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
2732 Line->InMacroBody || RParen->getPreviousNonComment() == LParen) {
2735 const bool DoubleParens =
2736 Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);
2738 const auto *PrevPrev = Prev->getPreviousNonComment();
2739 const bool Excluded =
2741 (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2743 (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2744 PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2748 const bool CommaSeparated =
2749 Prev->isOneOf(tok::l_paren, tok::comma) &&
2750 FormatTok->isOneOf(tok::comma, tok::r_paren);
2751 if (CommaSeparated &&
2753 !Prev->endsSequence(tok::comma, tok::ellipsis) &&
2755 !(FormatTok->is(tok::comma) &&
2756 Tokens->peekNextToken()->is(tok::ellipsis))) {
2759 const bool ReturnParens =
2761 ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2762 (!NestedLambdas.empty() && !NestedLambdas.back())) &&
2763 Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
2764 FormatTok->is(tok::semi);
2770 if (OptionalParens()) {
2771 LParen->Optional =
true;
2772 RParen->Optional =
true;
2773 }
else if (Prev->is(TT_TypenameMacro)) {
2774 LParen->setFinalizedType(TT_TypeDeclarationParen);
2775 RParen->setFinalizedType(TT_TypeDeclarationParen);
2776 }
else if (Prev->is(tok::greater) && RParen->Previous == LParen) {
2777 Prev->setFinalizedType(TT_TemplateCloser);
2778 }
else if (FormatTok->is(tok::l_brace) && Prev->is(tok::amp) &&
2780 FormatTok->setBlockKind(BK_BracedInit);
2792 if (!tryToParseBracedList())
2797 if (FormatTok->is(tok::l_brace)) {
2807 MightBeFoldExpr =
true;
2812 if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
2813 tryToParseChildBlock();
2818 if (Style.isJavaScript())
2823 case tok::identifier:
2824 if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))
2825 tryToParseJSFunction();
2829 case tok::kw_switch:
2835 case tok::kw_requires:
2836 parseRequiresExpression();
2852 if (StarAndAmpTokenType != TT_Unknown && ExcessLess == 0)
2853 FormatTok->setFinalizedType(StarAndAmpTokenType);
2863void UnwrappedLineParser::parseSquare(
bool SkipLambda) {
2865 assert(FormatTok->is(tok::l_square) &&
"'[' expected.");
2866 if (tryToParseLambda())
2870 switch (FormatTok->Tok.getKind()) {
2883 case tok::l_brace: {
2884 if (!tryToParseBracedList())
2891 if (FormatTok->is(tok::l_brace)) {
2903void UnwrappedLineParser::keepAncestorBraces() {
2904 if (!Style.RemoveBracesLLVM)
2907 const int MaxNestingLevels = 2;
2908 const int Size = NestedTooDeep.size();
2909 if (Size >= MaxNestingLevels)
2910 NestedTooDeep[
Size - MaxNestingLevels] =
true;
2911 NestedTooDeep.push_back(
false);
2915 for (
const auto &
Token : llvm::reverse(
Line.Tokens))
2922void UnwrappedLineParser::parseUnbracedBody(
bool CheckEOF) {
2925 if (Style.InsertBraces && !
Line->InPPDirective && !
Line->Tokens.empty() &&
2926 PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
2928 ? getLastNonComment(*
Line)
2931 if (
Tok->BraceCount < 0) {
2932 assert(
Tok->BraceCount == -1);
2935 Tok->BraceCount = -1;
2940 const auto BodyStart = CurrentLines->size();
2942 ++
Line->UnbracedBodyLevel;
2943 parseStructuralElement();
2944 --
Line->UnbracedBodyLevel;
2947 assert(!
Line->InPPDirective);
2950 auto BodyEnd = CurrentLines->size();
2951 while (BodyEnd > 0) {
2952 const auto &L = (*CurrentLines)[--BodyEnd];
2954 Tok = L.Tokens.back().Tok;
2960 bool EnclosesPPDirective =
false;
2961 for (
size_t I = BodyStart; I <= BodyEnd && !EnclosesPPDirective; ++I) {
2962 const auto &BodyLine = (*CurrentLines)[I];
2963 EnclosesPPDirective =
2964 BodyLine.InPPDirective ||
2965 llvm::any_of(BodyLine.Tokens, [](
const UnwrappedLineNode &Node) {
2966 return Node.Tok->FirstAfterPPLine;
2969 if (EnclosesPPDirective)
2970 LBraceTok->BraceCount = 0;
2975 if (CheckEOF &&
eof())
2985 assert(LeftBrace->
is(tok::l_brace));
2993 assert(RightBrace->
is(tok::r_brace));
3001void UnwrappedLineParser::handleAttributes() {
3003 if (FormatTok->isAttribute())
3005 else if (FormatTok->is(tok::l_square))
3006 handleCppAttributes();
3009bool UnwrappedLineParser::handleCppAttributes() {
3011 assert(FormatTok->is(tok::l_square));
3012 if (!tryToParseSimpleAttribute())
3019bool UnwrappedLineParser::isBlockBegin(
const FormatToken &
Tok)
const {
3022 return Style.isVerilog() ? Keywords.isVerilogBegin(
Tok)
3023 :
Tok.
is(tok::l_brace);
3026FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
3028 bool IsVerilogAssert) {
3029 assert((FormatTok->is(tok::kw_if) ||
3030 (Style.isVerilog() &&
3031 FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
3032 Keywords.kw_assume, Keywords.kw_cover))) &&
3036 if (IsVerilogAssert) {
3038 if (FormatTok->is(Keywords.kw_verilogHash)) {
3040 if (FormatTok->is(tok::numeric_constant))
3042 }
else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,
3043 Keywords.kw_sequence)) {
3049 if (Style.isTableGen()) {
3050 while (!
eof() && FormatTok->isNot(Keywords.kw_then)) {
3057 if (FormatTok->is(tok::exclaim))
3060 bool KeepIfBraces =
true;
3061 if (FormatTok->is(tok::kw_consteval)) {
3064 KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;
3065 if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
3067 if (FormatTok->is(tok::l_paren)) {
3068 FormatTok->setFinalizedType(TT_ConditionLParen);
3074 if (IsVerilogAssert && FormatTok->is(tok::semi)) {
3080 bool NeedsUnwrappedLine =
false;
3081 keepAncestorBraces();
3084 IfStmtKind IfBlockKind = IfStmtKind::NotIf;
3086 if (isBlockBegin(*FormatTok)) {
3087 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3088 IfLeftBrace = FormatTok;
3089 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3090 parseBlock(
false, 1u,
3091 true, KeepIfBraces, &IfBlockKind);
3092 setPreviousRBraceType(TT_ControlStatementRBrace);
3093 if (Style.BraceWrapping.BeforeElse)
3096 NeedsUnwrappedLine =
true;
3097 }
else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {
3100 parseUnbracedBody();
3103 if (Style.RemoveBracesLLVM) {
3104 assert(!NestedTooDeep.empty());
3105 KeepIfBraces = KeepIfBraces ||
3106 (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
3107 NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
3108 IfBlockKind == IfStmtKind::IfElseIf;
3111 bool KeepElseBraces = KeepIfBraces;
3113 IfStmtKind
Kind = IfStmtKind::IfOnly;
3115 if (FormatTok->is(tok::kw_else)) {
3116 if (Style.RemoveBracesLLVM) {
3117 NestedTooDeep.back() =
false;
3118 Kind = IfStmtKind::IfElse;
3122 if (isBlockBegin(*FormatTok)) {
3123 const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
3124 FormatTok->setFinalizedType(TT_ElseLBrace);
3125 ElseLeftBrace = FormatTok;
3126 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3127 IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
3129 parseBlock(
false, 1u,
3130 true, KeepElseBraces, &ElseBlockKind);
3131 setPreviousRBraceType(TT_ElseRBrace);
3132 if (FormatTok->is(tok::kw_else)) {
3133 KeepElseBraces = KeepElseBraces ||
3134 ElseBlockKind == IfStmtKind::IfOnly ||
3135 ElseBlockKind == IfStmtKind::IfElseIf;
3136 }
else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
3137 KeepElseBraces =
true;
3138 assert(ElseLeftBrace->MatchingParen);
3142 }
else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {
3145 const bool IsPrecededByComment =
Previous->is(tok::comment);
3146 if (IsPrecededByComment) {
3150 bool TooDeep =
true;
3151 if (Style.RemoveBracesLLVM) {
3152 Kind = IfStmtKind::IfElseIf;
3153 TooDeep = NestedTooDeep.pop_back_val();
3155 ElseLeftBrace = parseIfThenElse(
nullptr, KeepIfBraces);
3156 if (Style.RemoveBracesLLVM)
3157 NestedTooDeep.push_back(TooDeep);
3158 if (IsPrecededByComment)
3161 parseUnbracedBody(
true);
3164 KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
3165 if (NeedsUnwrappedLine)
3169 if (!Style.RemoveBracesLLVM)
3172 assert(!NestedTooDeep.empty());
3173 KeepElseBraces = KeepElseBraces ||
3174 (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
3175 NestedTooDeep.back();
3177 NestedTooDeep.pop_back();
3179 if (!KeepIfBraces && !KeepElseBraces) {
3182 }
else if (IfLeftBrace) {
3183 FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
3185 assert(IfRightBrace->MatchingParen == IfLeftBrace);
3186 assert(!IfLeftBrace->Optional);
3187 assert(!IfRightBrace->Optional);
3188 IfLeftBrace->MatchingParen =
nullptr;
3189 IfRightBrace->MatchingParen =
nullptr;
3199void UnwrappedLineParser::parseTryCatch() {
3200 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) &&
"'try' expected");
3202 bool NeedsUnwrappedLine =
false;
3203 bool HasCtorInitializer =
false;
3204 if (FormatTok->is(tok::colon)) {
3205 auto *Colon = FormatTok;
3208 if (FormatTok->is(tok::identifier)) {
3209 HasCtorInitializer =
true;
3210 Colon->setFinalizedType(TT_CtorInitializerColon);
3215 while (FormatTok->is(tok::comma))
3218 while (FormatTok->is(tok::identifier)) {
3220 if (FormatTok->is(tok::l_paren)) {
3222 }
else if (FormatTok->is(tok::l_brace)) {
3229 while (FormatTok->is(tok::comma))
3234 if (Style.isJava() && FormatTok->is(tok::l_paren))
3237 keepAncestorBraces();
3239 if (FormatTok->is(tok::l_brace)) {
3240 if (HasCtorInitializer)
3241 FormatTok->setFinalizedType(TT_FunctionLBrace);
3242 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3244 if (Style.BraceWrapping.BeforeCatch)
3247 NeedsUnwrappedLine =
true;
3248 }
else if (FormatTok->isNot(tok::kw_catch)) {
3254 parseStructuralElement();
3257 for (
bool SeenCatch =
false;;) {
3258 if (FormatTok->is(tok::at))
3260 if (FormatTok->isNoneOf(tok::kw_catch, Keywords.kw___except,
3261 tok::kw___finally, tok::objc_catch,
3262 tok::objc_finally) &&
3263 !((Style.isJava() || Style.isJavaScript()) &&
3264 FormatTok->is(Keywords.kw_finally))) {
3267 if (FormatTok->is(tok::kw_catch))
3270 while (FormatTok->isNot(tok::l_brace)) {
3271 if (FormatTok->is(tok::l_paren)) {
3275 if (FormatTok->isOneOf(tok::semi, tok::r_brace) ||
eof()) {
3276 if (Style.RemoveBracesLLVM)
3277 NestedTooDeep.pop_back();
3283 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3286 NeedsUnwrappedLine =
false;
3287 Line->MustBeDeclaration =
false;
3288 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3290 if (Style.BraceWrapping.BeforeCatch)
3293 NeedsUnwrappedLine =
true;
3296 if (Style.RemoveBracesLLVM)
3297 NestedTooDeep.pop_back();
3299 if (NeedsUnwrappedLine)
3303void UnwrappedLineParser::parseNamespaceOrExportBlock(
unsigned AddLevels) {
3304 bool ManageWhitesmithsBraces =
3309 if (ManageWhitesmithsBraces)
3314 parseBlock(
true, AddLevels,
true,
3315 true,
nullptr, ManageWhitesmithsBraces);
3317 addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
3319 if (ManageWhitesmithsBraces)
3323void UnwrappedLineParser::parseNamespace() {
3324 assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
3325 "'namespace' expected");
3329 if (InitialToken.is(TT_NamespaceMacro)) {
3332 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
3333 tok::l_square, tok::period, tok::l_paren) ||
3334 (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
3335 if (FormatTok->is(tok::l_square))
3337 else if (FormatTok->is(tok::l_paren))
3343 if (FormatTok->is(tok::l_brace)) {
3344 FormatTok->setFinalizedType(TT_NamespaceLBrace);
3347 Tokens->peekNextToken()->is(tok::r_brace))) {
3351 unsigned AddLevels =
3354 DeclarationScopeStack.size() > 1)
3357 parseNamespaceOrExportBlock(AddLevels);
3362void UnwrappedLineParser::parseCppExportBlock() {
3363 if (FormatTok->is(tok::l_brace)) {
3364 FormatTok->setFinalizedType(TT_ExportLBrace);
3365 if (Style.BraceWrapping.AfterExportBlock)
3368 parseNamespaceOrExportBlock(Style.IndentExportBlock ? 1 : 0);
3371void UnwrappedLineParser::parseNew() {
3372 assert(FormatTok->is(tok::kw_new) &&
"'new' expected");
3375 if (Style.isCSharp()) {
3378 if (FormatTok->is(tok::l_paren))
3382 if (FormatTok->is(tok::l_brace))
3385 if (FormatTok->isOneOf(tok::semi, tok::comma))
3390 }
else if (Style.isJava()) {
3394 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
3398 if (FormatTok->is(tok::l_paren)) {
3403 if (FormatTok->is(tok::l_brace))
3409 }
else if (Style.isCpp()) {
3413 if (FormatTok->is(tok::l_brace))
3415 if (FormatTok->is(tok::l_paren))
3417 if (FormatTok->is(tok::l_paren)) {
3423 if (FormatTok->isOneOf(tok::kw_alignas, tok::kw_decltype)) {
3425 if (FormatTok->is(tok::l_paren))
3427 }
else if (FormatTok->is(tok::l_square)) {
3430 }
else if (FormatTok->is(tok::less)) {
3432 parseBracedList(
true);
3433 }
else if (FormatTok->Tok.getIdentifierInfo() ||
3434 FormatTok->isOneOf(tok::coloncolon, tok::star)) {
3441 if (FormatTok->is(tok::l_brace))
3443 else if (FormatTok->is(tok::l_paren))
3448void UnwrappedLineParser::parseLoopBody(
bool KeepBraces,
bool WrapRightBrace) {
3449 keepAncestorBraces();
3451 if (isBlockBegin(*FormatTok)) {
3452 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3454 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3455 parseBlock(
false, 1u,
3457 setPreviousRBraceType(TT_ControlStatementRBrace);
3459 assert(!NestedTooDeep.empty());
3460 if (!NestedTooDeep.back())
3466 parseUnbracedBody();
3470 NestedTooDeep.pop_back();
3473void UnwrappedLineParser::parseForOrWhileLoop(
bool HasParens) {
3474 assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||
3475 (Style.isVerilog() &&
3476 FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,
3477 Keywords.kw_always_ff, Keywords.kw_always_latch,
3478 Keywords.kw_final, Keywords.kw_initial,
3479 Keywords.kw_foreach, Keywords.kw_forever,
3480 Keywords.kw_repeat))) &&
3481 "'for', 'while' or foreach macro expected");
3482 const bool KeepBraces = !Style.RemoveBracesLLVM ||
3483 FormatTok->isNoneOf(tok::kw_for, tok::kw_while);
3487 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
3489 if (IsCpp && FormatTok->is(tok::kw_co_await))
3491 if (HasParens && FormatTok->is(tok::l_paren)) {
3495 if (Style.isVerilog())
3496 FormatTok->setFinalizedType(TT_ConditionLParen);
3500 if (Style.isVerilog()) {
3502 parseVerilogSensitivityList();
3503 }
else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&
3504 Tokens->getPreviousToken()->is(tok::r_paren)) {
3511 parseLoopBody(KeepBraces,
true);
3514void UnwrappedLineParser::parseDoWhile() {
3515 assert(FormatTok->is(tok::kw_do) &&
"'do' expected");
3518 parseLoopBody(
true, Style.BraceWrapping.BeforeWhile);
3521 if (FormatTok->isNot(tok::kw_while)) {
3526 FormatTok->setFinalizedType(TT_DoWhile);
3534 parseStructuralElement();
3537void UnwrappedLineParser::parseLabel(
bool IsGotoLabel) {
3540 const auto IndentGotoLabel = Style.IndentGotoLabels;
3541 const auto OldLineLevel =
Line->Level;
3548 if (OldLineLevel > 1 || (!
Line->InPPDirective && OldLineLevel > 0))
3552 if (!IsGotoLabel && !Style.IndentCaseBlocks &&
3553 CommentsBeforeNextToken.empty() && FormatTok->is(tok::l_brace)) {
3554 CompoundStatementIndenter Indenter(
this,
Level,
3555 Style.BraceWrapping.AfterCaseLabel,
3556 Style.BraceWrapping.IndentBraces);
3558 if (FormatTok->is(tok::kw_break)) {
3559 if (Style.BraceWrapping.AfterControlStatement ==
3562 if (!Style.IndentCaseBlocks &&
3567 parseStructuralElement();
3571 if (FormatTok->is(tok::semi))
3576 Level = OldLineLevel;
3578 if (FormatTok->isNot(tok::l_brace)) {
3579 parseStructuralElement();
3584void UnwrappedLineParser::parseCaseLabel() {
3585 assert(FormatTok->is(tok::kw_case) &&
"'case' expected");
3586 auto *Case = FormatTok;
3591 if (FormatTok->is(tok::colon)) {
3592 FormatTok->setFinalizedType(TT_CaseLabelColon);
3595 if (Style.isJava() && FormatTok->is(tok::arrow)) {
3596 FormatTok->setFinalizedType(TT_CaseLabelArrow);
3597 Case->setFinalizedType(TT_SwitchExpressionLabel);
3604void UnwrappedLineParser::parseSwitch(
bool IsExpr) {
3605 assert(FormatTok->is(tok::kw_switch) &&
"'switch' expected");
3607 if (FormatTok->is(tok::l_paren))
3610 keepAncestorBraces();
3612 if (FormatTok->is(tok::l_brace)) {
3613 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3614 FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
3615 : TT_ControlStatementLBrace);
3620 setPreviousRBraceType(TT_ControlStatementRBrace);
3626 parseStructuralElement();
3630 if (Style.RemoveBracesLLVM)
3631 NestedTooDeep.pop_back();
3634void UnwrappedLineParser::parseAccessSpecifier() {
3637 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
3640 if (FormatTok->is(tok::colon))
3648bool UnwrappedLineParser::parseRequires(
bool SeenEqual) {
3649 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3653 switch (Tokens->peekNextToken(
true)->Tok.getKind()) {
3656 parseRequiresExpression();
3663 parseRequiresClause();
3674 auto *PreviousNonComment = FormatTok->getPreviousNonComment();
3676 if (!PreviousNonComment ||
3677 PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
3680 parseRequiresClause();
3684 switch (PreviousNonComment->Tok.getKind()) {
3687 case tok::kw_noexcept:
3692 parseRequiresClause();
3701 auto PrevPrev = PreviousNonComment->getPreviousNonComment();
3702 if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {
3703 parseRequiresClause();
3709 if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
3711 parseRequiresClause();
3715 parseRequiresExpression();
3725 unsigned StoredPosition = Tokens->getPosition();
3728 auto PeekNext = [&Lookahead, &NextToken,
this] {
3730 NextToken = Tokens->getNextToken();
3733 bool FoundType =
false;
3734 bool LastWasColonColon =
false;
3737 for (; Lookahead < 50; PeekNext()) {
3738 switch (NextToken->Tok.getKind()) {
3739 case tok::kw_volatile:
3742 if (OpenAngles == 0) {
3743 FormatTok = Tokens->setPosition(StoredPosition);
3744 parseRequiresExpression();
3752 case tok::coloncolon:
3753 LastWasColonColon =
true;
3755 case tok::kw_decltype:
3756 case tok::identifier:
3757 if (FoundType && !LastWasColonColon && OpenAngles == 0) {
3758 FormatTok = Tokens->setPosition(StoredPosition);
3759 parseRequiresExpression();
3763 LastWasColonColon =
false;
3772 if (NextToken->isTypeName(LangOpts)) {
3773 FormatTok = Tokens->setPosition(StoredPosition);
3774 parseRequiresExpression();
3781 FormatTok = Tokens->setPosition(StoredPosition);
3782 parseRequiresClause();
3791void UnwrappedLineParser::parseRequiresClause() {
3792 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3797 bool InRequiresExpression =
3798 !FormatTok->Previous ||
3799 FormatTok->Previous->is(TT_RequiresExpressionLBrace);
3801 FormatTok->setFinalizedType(InRequiresExpression
3802 ? TT_RequiresClauseInARequiresExpression
3803 : TT_RequiresClause);
3808 parseConstraintExpression();
3810 if (!InRequiresExpression && FormatTok->Previous)
3811 FormatTok->Previous->ClosesRequiresClause =
true;
3819void UnwrappedLineParser::parseRequiresExpression() {
3820 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3822 FormatTok->setFinalizedType(TT_RequiresExpression);
3825 if (FormatTok->is(tok::l_paren)) {
3826 FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
3830 if (FormatTok->is(tok::l_brace)) {
3831 FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
3840void UnwrappedLineParser::parseConstraintExpression() {
3847 bool LambdaNextTimeAllowed =
true;
3857 bool TopLevelParensAllowed =
true;
3860 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed,
false);
3862 switch (FormatTok->Tok.getKind()) {
3863 case tok::kw_requires:
3864 parseRequiresExpression();
3868 if (!TopLevelParensAllowed)
3870 parseParens(TT_BinaryOperator);
3871 TopLevelParensAllowed =
false;
3875 if (!LambdaThisTimeAllowed || !tryToParseLambda())
3882 case tok::kw_struct:
3892 FormatTok->setFinalizedType(TT_BinaryOperator);
3894 LambdaNextTimeAllowed =
true;
3895 TopLevelParensAllowed =
true;
3900 LambdaNextTimeAllowed = LambdaThisTimeAllowed;
3904 case tok::kw_sizeof:
3906 case tok::greaterequal:
3907 case tok::greatergreater:
3909 case tok::lessequal:
3911 case tok::equalequal:
3913 case tok::exclaimequal:
3918 LambdaNextTimeAllowed =
true;
3919 TopLevelParensAllowed =
true;
3924 case tok::numeric_constant:
3925 case tok::coloncolon:
3928 TopLevelParensAllowed =
false;
3933 case tok::kw_static_cast:
3934 case tok::kw_const_cast:
3935 case tok::kw_reinterpret_cast:
3936 case tok::kw_dynamic_cast:
3938 if (FormatTok->isNot(tok::less))
3942 parseBracedList(
true);
3946 if (!FormatTok->Tok.getIdentifierInfo()) {
3956 assert(FormatTok->Previous);
3957 switch (FormatTok->Previous->Tok.getKind()) {
3958 case tok::coloncolon:
3962 case tok::kw_requires:
3964 case tok::kw_template:
3972 if (FormatTok->is(tok::less)) {
3974 parseBracedList(
true);
3976 TopLevelParensAllowed =
false;
3982bool UnwrappedLineParser::parseEnum() {
3986 if (FormatTok->is(tok::kw_enum))
3992 if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
4001 if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
4003 while (FormatTok->is(tok::l_square))
4004 if (!handleCppAttributes())
4008 while (FormatTok->Tok.getIdentifierInfo() ||
4009 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
4010 tok::greater, tok::comma, tok::question,
4012 if (FormatTok->is(tok::colon))
4013 FormatTok->setFinalizedType(TT_EnumUnderlyingTypeColon);
4014 if (Style.isVerilog()) {
4015 FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
4018 while (FormatTok->is(tok::l_square))
4024 if (FormatTok->is(tok::l_paren))
4026 if (FormatTok->is(tok::identifier)) {
4030 if (IsCpp && FormatTok->is(tok::identifier))
4036 if (FormatTok->isNot(tok::l_brace))
4038 FormatTok->setFinalizedType(TT_EnumLBrace);
4039 FormatTok->setBlockKind(BK_Block);
4041 if (Style.isJava()) {
4043 parseJavaEnumBody();
4051 const bool ManageWhitesmithsBraces =
4054 if (!Style.AllowShortEnumsOnASingleLine &&
4056 Tokens->peekNextToken()->is(tok::r_brace))) {
4061 if (ManageWhitesmithsBraces)
4066 if (!Style.AllowShortEnumsOnASingleLine) {
4068 if (!ManageWhitesmithsBraces)
4071 const auto OpeningLineIndex = CurrentLines->empty()
4072 ? UnwrappedLine::kInvalidIndex
4073 : CurrentLines->size() - 1;
4074 bool HasError = !parseBracedList(
false,
true);
4075 if (!Style.AllowShortEnumsOnASingleLine && !ManageWhitesmithsBraces)
4078 if (FormatTok->is(tok::semi))
4082 setPreviousRBraceType(TT_EnumRBrace);
4083 if (ManageWhitesmithsBraces)
4084 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
4092bool UnwrappedLineParser::parseStructLike() {
4097 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) {
4098 if (FormatTok->is(tok::semi))
4109class ScopedTokenPosition {
4110 unsigned StoredPosition;
4111 FormatTokenSource *Tokens;
4114 ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
4115 assert(Tokens &&
"Tokens expected to not be null");
4116 StoredPosition = Tokens->getPosition();
4119 ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
4125bool UnwrappedLineParser::tryToParseSimpleAttribute() {
4126 ScopedTokenPosition AutoPosition(Tokens);
4134 if (
Tok->
is(tok::r_square))
4136 Tok = Tokens->getNextToken();
4138 if (
Tok->
is(tok::eof))
4140 Tok = Tokens->getNextToken();
4143 Tok = Tokens->getNextToken();
4144 if (
Tok->
is(tok::semi))
4149void UnwrappedLineParser::parseJavaEnumBody() {
4150 assert(FormatTok->is(tok::l_brace));
4156 unsigned StoredPosition = Tokens->getPosition();
4157 bool IsSimple =
true;
4160 if (
Tok->
is(tok::r_brace))
4168 Tok = Tokens->getNextToken();
4170 FormatTok = Tokens->setPosition(StoredPosition);
4187 if (FormatTok->is(tok::l_brace)) {
4189 parseBlock(
true, 1u,
4191 }
else if (FormatTok->is(tok::l_paren)) {
4193 }
else if (FormatTok->is(tok::comma)) {
4196 }
else if (FormatTok->is(tok::semi)) {
4200 }
else if (FormatTok->is(tok::r_brace)) {
4209 parseLevel(OpeningBrace);
4215void UnwrappedLineParser::parseRecord(
bool ParseAsExpr,
bool IsJavaRecord) {
4216 assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record));
4221 IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok :
nullptr;
4222 bool IsDerived =
false;
4224 return Tok->
is(tok::identifier) &&
Tok->TokenText !=
Tok->TokenText.upper();
4228 bool JSPastExtendsOrImplements =
false;
4232 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
4233 tok::kw_alignas, tok::l_square) ||
4234 FormatTok->isAttribute() ||
4235 ((Style.isJava() || Style.isJavaScript()) &&
4236 FormatTok->isOneOf(tok::period, tok::comma)) ||
4237 (Style.isVerilog() &&
4238 FormatTok->isOneOf(tok::kw_signed, tok::kw_unsigned))) {
4239 if (Style.isJavaScript() &&
4240 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
4241 JSPastExtendsOrImplements =
true;
4246 if (FormatTok->is(tok::l_brace)) {
4247 tryToParseBracedList();
4251 if (FormatTok->is(tok::l_square) && handleCppAttributes())
4255 switch (FormatTok->Tok.getKind()) {
4258 if (IsJavaRecord || !IsNonMacroIdentifier(
Previous) ||
4260 Previous->Previous == &InitialToken) {
4264 case tok::coloncolon:
4268 if (JSPastExtendsOrImplements || ClassName ||
4279 auto IsListInitialization = [&] {
4280 if (!ClassName || IsDerived || JSPastExtendsOrImplements)
4282 assert(FormatTok->is(tok::l_brace));
4283 const auto *Prev = FormatTok->getPreviousNonComment();
4285 return Prev != ClassName && Prev->is(tok::identifier) &&
4286 Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
4289 if (FormatTok->isOneOf(tok::colon, tok::less)) {
4290 int AngleNestingLevel = 0;
4292 if (FormatTok->is(tok::less))
4293 ++AngleNestingLevel;
4294 else if (FormatTok->is(tok::greater))
4295 --AngleNestingLevel;
4297 if (AngleNestingLevel == 0) {
4298 if (FormatTok->is(tok::colon)) {
4300 }
else if (!IsDerived && FormatTok->is(tok::identifier) &&
4301 FormatTok->Previous->is(tok::coloncolon)) {
4302 ClassName = FormatTok;
4303 }
else if (FormatTok->is(tok::l_paren) &&
4304 IsNonMacroIdentifier(FormatTok->Previous)) {
4308 if (FormatTok->is(tok::l_brace)) {
4309 if (AngleNestingLevel == 0 && IsListInitialization())
4311 calculateBraceTypes(
true);
4312 if (!tryToParseBracedList())
4315 if (FormatTok->is(tok::l_square)) {
4318 !
Previous->isTypeOrIdentifier(LangOpts))) {
4321 if (!tryToParseLambda())
4328 if (FormatTok->is(tok::semi))
4330 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {
4333 parseCSharpGenericTypeConstraint();
4340 auto GetBraceTypes =
4341 [](
const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {
4342 switch (RecordTok.Tok.getKind()) {
4344 return {TT_ClassLBrace, TT_ClassRBrace};
4345 case tok::kw_struct:
4346 return {TT_StructLBrace, TT_StructRBrace};
4348 return {TT_UnionLBrace, TT_UnionRBrace};
4351 return {TT_RecordLBrace, TT_RecordRBrace};
4354 if (FormatTok->is(tok::l_brace)) {
4355 if (IsListInitialization())
4358 ClassName->setFinalizedType(TT_ClassHeadName);
4359 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
4360 FormatTok->setFinalizedType(OpenBraceType);
4365 Tokens->peekNextToken()->is(tok::r_brace),
4370 bool IndentAfterExplicitAccessModifier =
false;
4371 unsigned AddLevels = 1u;
4372 switch (Style.IndentAccessModifiers) {
4376 if (Style.isCpp()) {
4377 IndentAfterExplicitAccessModifier =
true;
4386 parseBlock(
true, AddLevels,
false,
4389 IndentAfterExplicitAccessModifier);
4391 setPreviousRBraceType(ClosingBraceType);
4398void UnwrappedLineParser::parseObjCMethod() {
4399 assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
4400 "'(' or identifier expected.");
4402 if (FormatTok->is(tok::semi)) {
4406 }
else if (FormatTok->is(tok::l_brace)) {
4407 if (Style.BraceWrapping.AfterFunction)
4418void UnwrappedLineParser::parseObjCProtocolList() {
4419 assert(FormatTok->is(tok::less) &&
"'<' expected.");
4423 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4425 }
while (!
eof() && FormatTok->isNot(tok::greater));
4429void UnwrappedLineParser::parseObjCUntilAtEnd() {
4431 if (FormatTok->is(tok::objc_end)) {
4436 if (FormatTok->is(tok::l_brace)) {
4440 }
else if (FormatTok->is(tok::r_brace)) {
4444 }
else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
4446 if (FormatTok->isOneOf(tok::l_paren, tok::identifier))
4449 parseStructuralElement();
4454void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
4455 assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation));
4461 if (FormatTok->is(tok::less))
4462 parseObjCLightweightGenerics();
4463 if (FormatTok->is(tok::colon)) {
4467 if (FormatTok->is(tok::less))
4468 parseObjCLightweightGenerics();
4469 }
else if (FormatTok->is(tok::l_paren)) {
4474 if (FormatTok->is(tok::less))
4475 parseObjCProtocolList();
4477 if (FormatTok->is(tok::l_brace)) {
4478 if (Style.BraceWrapping.AfterObjCDeclaration)
4487 parseObjCUntilAtEnd();
4490void UnwrappedLineParser::parseObjCLightweightGenerics() {
4491 assert(FormatTok->is(tok::less));
4499 unsigned NumOpenAngles = 1;
4503 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4505 if (FormatTok->is(tok::less)) {
4507 }
else if (FormatTok->is(tok::greater)) {
4508 assert(NumOpenAngles > 0 &&
"'>' makes NumOpenAngles negative");
4511 }
while (!
eof() && NumOpenAngles != 0);
4517bool UnwrappedLineParser::parseObjCProtocol() {
4518 assert(FormatTok->is(tok::objc_protocol));
4521 if (FormatTok->is(tok::l_paren)) {
4533 if (FormatTok->is(tok::less))
4534 parseObjCProtocolList();
4537 if (FormatTok->is(tok::semi)) {
4544 parseObjCUntilAtEnd();
4548void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
4549 bool IsImport = FormatTok->is(Keywords.kw_import);
4550 assert(IsImport || FormatTok->is(tok::kw_export));
4554 if (FormatTok->is(tok::kw_default))
4560 if (FormatTok->is(Keywords.kw_async))
4562 if (FormatTok->is(Keywords.kw_function)) {
4571 if (!IsImport && FormatTok->isNoneOf(tok::l_brace, tok::star) &&
4572 !FormatTok->isStringLiteral() &&
4573 !(FormatTok->is(Keywords.kw_type) &&
4574 Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {
4579 if (FormatTok->is(tok::semi))
4581 if (
Line->Tokens.empty()) {
4586 if (FormatTok->is(tok::l_brace)) {
4587 FormatTok->setBlockKind(BK_Block);
4596void UnwrappedLineParser::parseStatementMacro() {
4598 if (FormatTok->is(tok::l_paren))
4600 if (FormatTok->is(tok::semi))
4605void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
4608 if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
4609 tok::coloncolon, tok::hash) ||
4610 Keywords.isVerilogIdentifier(*FormatTok)) {
4612 }
else if (FormatTok->is(tok::l_square)) {
4620void UnwrappedLineParser::parseVerilogSensitivityList() {
4621 if (FormatTok->isNot(tok::at))
4625 if (FormatTok->is(tok::at))
4627 switch (FormatTok->Tok.getKind()) {
4635 parseVerilogHierarchyIdentifier();
4640unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
4641 unsigned AddLevels = 0;
4643 if (FormatTok->is(Keywords.kw_clocking)) {
4645 if (Keywords.isVerilogIdentifier(*FormatTok))
4647 parseVerilogSensitivityList();
4648 if (FormatTok->is(tok::semi))
4650 }
else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
4651 Keywords.kw_casez, Keywords.kw_randcase,
4652 Keywords.kw_randsequence)) {
4653 if (Style.IndentCaseLabels)
4656 if (FormatTok->is(tok::l_paren)) {
4657 FormatTok->setFinalizedType(TT_ConditionLParen);
4660 if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
4669 if (FormatTok->is(tok::l_square)) {
4670 auto Prev = FormatTok->getPreviousNonComment();
4671 if (Prev && Keywords.isVerilogIdentifier(*Prev))
4672 Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
4674 }
else if (Keywords.isVerilogIdentifier(*FormatTok) ||
4675 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
4676 Keywords.kw_automatic, tok::kw_static)) {
4683 auto NewLine = [
this]() {
4685 Line->IsContinuation =
true;
4689 while (FormatTok->is(Keywords.kw_import)) {
4692 parseVerilogHierarchyIdentifier();
4693 if (FormatTok->is(tok::semi))
4698 if (FormatTok->is(Keywords.kw_verilogHash)) {
4701 if (FormatTok->is(tok::l_paren)) {
4702 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4706 if (FormatTok->is(tok::l_paren)) {
4708 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4713 if (FormatTok->is(Keywords.kw_extends)) {
4716 parseVerilogHierarchyIdentifier();
4717 if (FormatTok->is(tok::l_paren))
4720 if (FormatTok->is(Keywords.kw_implements)) {
4724 parseVerilogHierarchyIdentifier();
4725 }
while (FormatTok->is(tok::comma));
4729 if (FormatTok->is(tok::at)) {
4731 parseVerilogSensitivityList();
4734 if (FormatTok->is(tok::semi))
4742void UnwrappedLineParser::parseVerilogTable() {
4743 assert(FormatTok->is(Keywords.kw_table));
4747 auto InitialLevel =
Line->Level++;
4748 while (!
eof() && !Keywords.isVerilogEnd(*FormatTok)) {
4751 if (
Tok->
is(tok::semi))
4753 else if (
Tok->
isOneOf(tok::star, tok::colon, tok::question, tok::minus))
4754 Tok->setFinalizedType(TT_VerilogTableItem);
4756 Line->Level = InitialLevel;
4761void UnwrappedLineParser::parseVerilogCaseLabel() {
4767 auto OrigLevel =
Line->Level;
4768 auto FirstLine = CurrentLines->size();
4769 if (
Line->Level == 0 || (
Line->InPPDirective &&
Line->Level <= 1))
4771 else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
4773 parseStructuralElement();
4776 if (CurrentLines->size() > FirstLine)
4777 (*CurrentLines)[FirstLine].Level = OrigLevel;
4778 Line->Level = OrigLevel;
4781void UnwrappedLineParser::parseVerilogExtern() {
4783 FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
4786 if (FormatTok->is(tok::string_literal))
4788 skipVerilogQualifiers();
4789 if (Keywords.isVerilogIdentifier(*FormatTok))
4791 if (FormatTok->is(tok::equal))
4793 if (Keywords.isVerilogHierarchy(*FormatTok))
4794 parseVerilogHierarchyHeader();
4797void UnwrappedLineParser::skipVerilogQualifiers() {
4798 while (FormatTok->isOneOf(tok::kw_protected, tok::kw_virtual, tok::kw_static,
4799 Keywords.kw_rand, Keywords.kw_context,
4800 Keywords.kw_pure, Keywords.kw_randc,
4801 Keywords.kw_local)) {
4806bool UnwrappedLineParser::containsExpansion(
const UnwrappedLine &
Line)
const {
4807 for (
const auto &N :
Line.Tokens) {
4808 if (N.Tok->MacroCtx)
4810 for (
const UnwrappedLine &Child : N.Children)
4811 if (containsExpansion(Child))
4817void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
4818 if (
Line->Tokens.empty())
4821 if (!parsingPPDirective()) {
4822 llvm::dbgs() <<
"Adding unwrapped line:\n";
4823 printDebugInfo(*
Line);
4831 bool ClosesWhitesmithsBlock =
4832 Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
4838 if (!parsingPPDirective() && !InExpansion && containsExpansion(*
Line)) {
4840 Reconstruct.emplace(
Line->Level, Unexpanded);
4841 Reconstruct->addLine(*
Line);
4846 CurrentExpandedLines.push_back(std::move(*
Line));
4848 if (Reconstruct->finished()) {
4849 UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();
4850 assert(!Reconstructed.Tokens.empty() &&
4851 "Reconstructed must at least contain the macro identifier.");
4852 assert(!parsingPPDirective());
4854 llvm::dbgs() <<
"Adding unexpanded line:\n";
4855 printDebugInfo(Reconstructed);
4857 ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;
4858 Lines.push_back(std::move(Reconstructed));
4859 CurrentExpandedLines.clear();
4860 Reconstruct.reset();
4865 assert(!Reconstruct || (CurrentLines != &Lines) || !PP.Stack.empty());
4866 CurrentLines->push_back(std::move(*
Line));
4868 Line->Tokens.clear();
4869 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
4870 Line->FirstStartColumn = 0;
4871 Line->IsContinuation =
false;
4872 Line->SeenDecltypeAuto =
false;
4873 Line->IsModuleOrImportDecl =
false;
4875 if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
4877 if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {
4878 CurrentLines->append(
4879 std::make_move_iterator(PreprocessorDirectives.begin()),
4880 std::make_move_iterator(PreprocessorDirectives.end()));
4881 PreprocessorDirectives.clear();
4884 FormatTok->Previous =
nullptr;
4887bool UnwrappedLineParser::eof()
const {
return FormatTok->is(tok::eof); }
4889bool UnwrappedLineParser::isOnNewLine(
const FormatToken &FormatTok) {
4890 return (
Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
4891 FormatTok.NewlinesBefore > 0;
4899 const llvm::Regex &CommentPragmasRegex) {
4903 StringRef IndentContent = FormatTok.
TokenText;
4904 if (FormatTok.
TokenText.starts_with(
"//") ||
4905 FormatTok.
TokenText.starts_with(
"/*")) {
4906 IndentContent = FormatTok.
TokenText.substr(2);
4908 if (CommentPragmasRegex.match(IndentContent))
4983 if (PreviousToken && PreviousToken->
is(tok::l_brace) &&
4985 MinColumnToken = PreviousToken;
4988 PreviousToken = Node.
Tok;
4992 MinColumnToken = Node.
Tok;
4994 if (PreviousToken && PreviousToken->
is(tok::l_brace))
4995 MinColumnToken = PreviousToken;
5001void UnwrappedLineParser::flushComments(
bool NewlineBeforeNext) {
5002 bool JustComments =
Line->Tokens.empty();
5012 Tok->ContinuesLineCommentSection =
5013 continuesLineCommentSection(*
Tok, *
Line, Style, CommentPragmasRegex);
5014 if (isOnNewLine(*
Tok) && JustComments && !
Tok->ContinuesLineCommentSection)
5018 if (NewlineBeforeNext && JustComments)
5020 CommentsBeforeNextToken.clear();
5023void UnwrappedLineParser::nextToken(
int LevelDifference) {
5026 flushComments(isOnNewLine(*FormatTok));
5027 pushToken(FormatTok);
5029 if (!Style.isJavaScript())
5030 readToken(LevelDifference);
5032 readTokenWithJavaScriptASI();
5034 if (Style.isVerilog()) {
5041 if (Keywords.isVerilogEnd(*FormatTok))
5042 FormatTok->Tok.setKind(tok::r_brace);
5046void UnwrappedLineParser::distributeComments(
5066 if (Comments.empty())
5068 bool ShouldPushCommentsInCurrentLine =
true;
5069 bool HasTrailAlignedWithNextToken =
false;
5070 unsigned StartOfTrailAlignedWithNextToken = 0;
5073 for (
unsigned i = Comments.size() - 1; i > 0; --i) {
5075 HasTrailAlignedWithNextToken =
true;
5076 StartOfTrailAlignedWithNextToken = i;
5080 for (
unsigned i = 0, e = Comments.size(); i < e; ++i) {
5082 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
5083 FormatTok->ContinuesLineCommentSection =
false;
5086 *FormatTok, *
Line, Style, CommentPragmasRegex);
5088 if (!FormatTok->ContinuesLineCommentSection &&
5089 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
5090 ShouldPushCommentsInCurrentLine =
false;
5092 if (ShouldPushCommentsInCurrentLine)
5093 pushToken(FormatTok);
5095 CommentsBeforeNextToken.push_back(FormatTok);
5099void UnwrappedLineParser::readToken(
int LevelDifference) {
5101 bool PreviousWasComment =
false;
5102 bool FirstNonCommentOnLine =
false;
5104 FormatTok = Tokens->getNextToken();
5106 while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
5107 TT_ConflictAlternative)) {
5108 if (FormatTok->is(TT_ConflictStart))
5109 conditionalCompilationStart(
false);
5110 else if (FormatTok->is(TT_ConflictAlternative))
5111 conditionalCompilationAlternative();
5112 else if (FormatTok->is(TT_ConflictEnd))
5113 conditionalCompilationEnd();
5114 FormatTok = Tokens->getNextToken();
5115 FormatTok->MustBreakBefore =
true;
5116 FormatTok->MustBreakBeforeFinalized =
true;
5119 auto IsFirstNonCommentOnLine = [](
bool FirstNonCommentOnLine,
5121 bool PreviousWasComment) {
5123 return Tok.HasUnescapedNewline ||
Tok.IsFirst;
5128 if (PreviousWasComment)
5129 return FirstNonCommentOnLine || IsFirstOnLine(
Tok);
5130 return IsFirstOnLine(
Tok);
5133 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
5134 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
5135 PreviousWasComment = FormatTok->is(tok::comment);
5137 while (!
Line->InPPDirective && FormatTok->is(tok::hash) &&
5138 FirstNonCommentOnLine) {
5141 const auto *
Next = Tokens->peekNextToken();
5142 if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*
Next)) ||
5143 (Style.isTableGen() &&
5144 Next->isNoneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef,
5145 tok::pp_ifndef, tok::pp_endif))) {
5148 distributeComments(Comments, FormatTok);
5153 const bool ParsedBefore = !ParsedPPDirectives.insert(FormatTok).second;
5156 bool SwitchToPreprocessorLines = !
Line->Tokens.empty();
5157 ScopedLineState BlockState(*
this, SwitchToPreprocessorLines,
5159 assert((LevelDifference >= 0 ||
5160 static_cast<unsigned>(-LevelDifference) <=
Line->Level) &&
5161 "LevelDifference makes Line->Level negative");
5162 Line->Level += LevelDifference;
5167 PP.BranchLevel > 0) {
5168 Line->Level += PP.BranchLevel;
5170 assert(
Line->Level >=
Line->UnbracedBodyLevel);
5171 Line->Level -=
Line->UnbracedBodyLevel;
5172 flushComments(isOnNewLine(*FormatTok));
5173 const bool IsEndIf = Tokens->peekNextToken()->is(tok::pp_endif);
5175 PreviousWasComment = FormatTok->is(tok::comment);
5176 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
5177 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
5180 if (IsEndIf && PP.IncludeGuard == IG_Defined && PP.BranchLevel == -1 &&
5181 getIncludeGuardState(Style.IndentPPDirectives) == IG_Inited &&
5183 (PreviousWasComment &&
5184 Tokens->peekNextToken(
true)->is(tok::eof)))) {
5185 PP.IncludeGuard = IG_Found;
5189 if (!PP.Stack.empty() && (PP.Stack.back().Kind == PP_Unreachable) &&
5190 !
Line->InPPDirective) {
5194 if (FormatTok->is(tok::identifier) &&
5195 Macros.defined(FormatTok->TokenText) &&
5197 !
Line->InPPDirective) {
5199 unsigned Position = Tokens->getPosition();
5204 const auto SavedPPState = PP;
5208 auto PreCall = std::move(
Line);
5209 Line.reset(
new UnwrappedLine);
5210 bool OldInExpansion = InExpansion;
5213 auto Args = parseMacroCall(SavedPPState);
5214 InExpansion = OldInExpansion;
5215 assert(
Line->Tokens.front().Tok == ID);
5217 auto UnexpandedLine = std::move(
Line);
5219 Line = std::move(PreCall);
5222 llvm::dbgs() <<
"Macro call: " <<
ID->TokenText <<
"(";
5224 llvm::dbgs() <<
"(";
5225 for (
const auto &Arg : Args.value())
5226 for (
const auto &
T : Arg)
5227 llvm::dbgs() <<
T->TokenText <<
" ";
5228 llvm::dbgs() <<
")";
5230 llvm::dbgs() <<
"\n";
5232 if (
Macros.objectLike(
ID->TokenText) && Args &&
5233 !
Macros.hasArity(
ID->TokenText, Args->size())) {
5239 LLVM_DEBUG(llvm::dbgs()
5240 <<
"Macro \"" <<
ID->TokenText
5241 <<
"\" not overloaded for arity " << Args->size()
5242 <<
"or not function-like, using object-like overload.");
5244 UnexpandedLine->Tokens.resize(1);
5245 Tokens->setPosition(Position);
5247 FormatTok = Tokens->getNextToken();
5249 assert(!Args &&
Macros.objectLike(
ID->TokenText));
5251 if ((!Args &&
Macros.objectLike(
ID->TokenText)) ||
5252 (Args &&
Macros.hasArity(
ID->TokenText, Args->size()))) {
5255 Unexpanded[
ID] = std::move(UnexpandedLine);
5257 Macros.expand(ID, std::move(Args));
5258 if (!Expansion.empty())
5259 FormatTok = Tokens->insertTokens(Expansion);
5262 llvm::dbgs() <<
"Expanded: ";
5263 for (
const auto &
T : Expansion)
5264 llvm::dbgs() <<
T->TokenText <<
" ";
5265 llvm::dbgs() <<
"\n";
5269 llvm::dbgs() <<
"Did not expand macro \"" <<
ID->TokenText
5270 <<
"\", because it was used ";
5272 llvm::dbgs() <<
"with " << Args->size();
5274 llvm::dbgs() <<
"without";
5275 llvm::dbgs() <<
" arguments, which doesn't match any definition.\n";
5277 Tokens->setPosition(Position);
5283 if (FormatTok->isNot(tok::comment)) {
5284 distributeComments(Comments, FormatTok);
5289 Comments.push_back(FormatTok);
5292 distributeComments(Comments,
nullptr);
5297template <
typename Iterator>
5298void pushTokens(Iterator Begin, Iterator End,
5300 for (
auto I = Begin; I != End; ++I) {
5301 Into.push_back(I->Tok);
5302 for (
const auto &Child : I->Children)
5303 pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);
5308std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
5309UnwrappedLineParser::parseMacroCall(
const PPState &SavedPPState) {
5310 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;
5311 assert(
Line->Tokens.empty());
5314 auto ConsumeLastTokenOfCall = [
this] {
5315 flushComments(isOnNewLine(*FormatTok));
5316 pushToken(FormatTok);
5317 FormatTok = Tokens->getNextToken();
5319 if (Tokens->peekNextToken(
true)->isNot(tok::l_paren)) {
5320 ConsumeLastTokenOfCall();
5324 assert(FormatTok->is(tok::l_paren));
5325 unsigned Position = Tokens->getPosition();
5329 auto ArgStart = std::prev(
Line->Tokens.end());
5333 switch (FormatTok->Tok.getKind()) {
5338 case tok::r_paren: {
5344 Args->push_back({});
5345 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5346 ConsumeLastTokenOfCall();
5354 Args->push_back({});
5355 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5357 ArgStart = std::prev(
Line->Tokens.end());
5365 Line->Tokens.resize(1);
5366 Tokens->setPosition(Position);
5373 Line->Tokens.push_back(UnwrappedLineNode(
Tok));
5374 if (PP.AtEndOfPPLine) {
5375 auto &
Tok = *
Line->Tokens.back().Tok;
5376 Tok.MustBreakBefore =
true;
5377 Tok.MustBreakBeforeFinalized =
true;
5378 Tok.FirstAfterPPLine =
true;
5379 PP.AtEndOfPPLine =
false;
This file contains the main building blocks of macro support in clang-format.
static bool HasAttribute(const QualType &T)
This file implements a token annotator, i.e.
Defines the clang::TokenKind enum and support functions.
This file contains the declaration of the UnwrappedLineParser, which turns a stream of tokens into Un...
Implements an efficient mapping from strings to IdentifierInfo nodes.
Parser - This implements a parser for the C family of languages.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isOneOf(Ts... Ks) const
bool isNot(tok::TokenKind K) const
@ Macros
Canonicalize -D and -U options.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
bool isLiteral(TokenKind K)
Return true if this is a "literal" kind, like a numeric constant, string, etc.
Top level wrappers for InstallAPI frontend operations.
bool isLineComment(const FormatToken &FormatTok)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Default
Set to the current date and time.
const FunctionProtoType * T
bool continuesLineComment(const FormatToken &FormatTok, const FormatToken *Previous, const FormatToken *MinColumnToken)
@ Parens
New-expression has a C++98 paren-delimited initializer.
Encapsulates keywords that are context sensitive or for languages not properly supported by Clang's l...
IdentifierInfo * kw_instanceof
IdentifierInfo * kw_implements
IdentifierInfo * kw_override
IdentifierInfo * kw_await
IdentifierInfo * kw_extends
IdentifierInfo * kw_async
IdentifierInfo * kw_abstract
IdentifierInfo * kw_interface
IdentifierInfo * kw_function
IdentifierInfo * kw_yield
IdentifierInfo * kw_where
IdentifierInfo * kw_throws
IdentifierInfo * kw_import
IdentifierInfo * kw_finally