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 (
auto &Line : Lines) {
234 if (!Line.Tokens.empty()) {
235 auto it = ExpandedLines.find(Line.Tokens.begin()->Tok);
236 if (it != ExpandedLines.end()) {
237 for (
auto &Expanded : it->second) {
238 Expanded.InMacroExpansion =
true;
239 LLVM_DEBUG(printDebugInfo(Expanded));
240 Callback.consumeUnwrappedLine(Expanded);
245 Line.InMacroExpansion =
true;
246 LLVM_DEBUG(printDebugInfo(Line));
247 Callback.consumeUnwrappedLine(Line);
248 Line.InMacroExpansion =
false;
250 Callback.finishRun();
253 LLVM_DEBUG(llvm::dbgs() <<
"Unwrapped lines:\n");
255 LLVM_DEBUG(printDebugInfo(Line));
256 Callback.consumeUnwrappedLine(Line);
258 Callback.finishRun();
260 while (!PP.LevelBranchIndex.empty() &&
261 PP.LevelBranchIndex.back() + 1 >= PP.LevelBranchCount.back()) {
262 PP.LevelBranchIndex.resize(PP.LevelBranchIndex.size() - 1);
263 PP.LevelBranchCount.resize(PP.LevelBranchCount.size() - 1);
265 if (!PP.LevelBranchIndex.empty()) {
266 ++PP.LevelBranchIndex.back();
267 assert(PP.LevelBranchIndex.size() == PP.LevelBranchCount.size());
268 assert(PP.LevelBranchIndex.back() <= PP.LevelBranchCount.back());
270 }
while (!PP.LevelBranchIndex.empty());
273void UnwrappedLineParser::parseFile() {
276 bool MustBeDeclaration = !
Line->InPPDirective && !Style.isJavaScript();
277 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
279 if (Style.isTextProto() || (Style.isJson() && FormatTok->
IsFirst))
293 if (Style.isTextProto() && !CommentsBeforeNextToken.empty())
299void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {
309 parseCSharpGenericTypeConstraint();
318void UnwrappedLineParser::parseCSharpAttribute() {
319 int UnpairedSquareBrackets = 1;
321 switch (FormatTok->Tok.getKind()) {
324 --UnpairedSquareBrackets;
325 if (UnpairedSquareBrackets == 0) {
331 ++UnpairedSquareBrackets;
341bool UnwrappedLineParser::precededByCommentOrPPDirective()
const {
342 if (!Lines.empty() && Lines.back().InPPDirective)
356bool UnwrappedLineParser::parseLevel(
const FormatToken *OpeningBrace,
359 bool *SeenExplicitAccessModifier) {
360 const bool InRequiresExpression =
361 OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
362 const bool IsPrecededByCommentOrPPDirective =
363 !Style.RemoveBracesLLVM || precededByCommentOrPPDirective();
365 bool HasDoWhile =
false;
366 bool HasLabel =
false;
367 unsigned StatementCount = 0;
368 bool SwitchLabelEncountered =
false;
371 if (FormatTok->isAttribute()) {
373 if (FormatTok->is(tok::l_paren))
378 if (FormatTok->is(TT_MacroBlockBegin))
380 else if (FormatTok->is(TT_MacroBlockEnd))
383 auto ParseDefault = [
this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
384 &HasLabel, &StatementCount,
385 SeenExplicitAccessModifier] {
386 if (SeenExplicitAccessModifier && !*SeenExplicitAccessModifier) {
387 const bool IsQtAccessLabel =
388 FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
389 Keywords.kw_slots, Keywords.kw_qslots) &&
390 Tokens->peekNextToken(
true)->is(tok::colon);
391 if (FormatTok->isAccessSpecifierKeyword() || IsQtAccessLabel) {
393 *SeenExplicitAccessModifier =
true;
396 parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,
397 HasDoWhile ?
nullptr : &HasDoWhile,
398 HasLabel ?
nullptr : &HasLabel);
400 assert(StatementCount > 0 &&
"StatementCount overflow!");
409 if (InRequiresExpression) {
410 FormatTok->setFinalizedType(TT_CompoundRequirementLBrace);
411 }
else if (FormatTok->Previous &&
412 FormatTok->Previous->ClosesRequiresClause) {
418 if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {
419 if (tryToParseBracedList())
421 FormatTok->setFinalizedType(TT_BlockLBrace);
425 assert(StatementCount > 0 &&
"StatementCount overflow!");
430 if (!Style.RemoveBracesLLVM || Line->InPPDirective ||
431 OpeningBrace->isNoneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
434 if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||
435 HasDoWhile || IsPrecededByCommentOrPPDirective ||
436 precededByCommentOrPPDirective()) {
440 if (
Next->is(tok::comment) &&
Next->NewlinesBefore == 0)
443 *IfLeftBrace = IfLBrace;
449 case tok::kw_default: {
450 unsigned StoredPosition = Tokens->getPosition();
451 auto *
Next = Tokens->getNextNonComment();
452 FormatTok = Tokens->setPosition(StoredPosition);
453 if (
Next->isNoneOf(tok::colon, tok::arrow)) {
456 parseStructuralElement();
464 (Style.isJavaScript() && Line->MustBeDeclaration)) {
472 if (!SwitchLabelEncountered &&
473 (Style.IndentCaseLabels ||
474 (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||
475 (Line->InPPDirective && Line->Level == 1))) {
478 SwitchLabelEncountered =
true;
479 parseStructuralElement();
482 if (Style.isCSharp()) {
484 parseCSharpAttribute();
487 if (handleCppAttributes())
499void UnwrappedLineParser::calculateBraceTypes(
bool ExpectClassBody) {
504 unsigned StoredPosition = Tokens->getPosition();
514 SmallVector<StackEntry, 8> LBraceStack;
515 assert(
Tok->is(tok::l_brace));
518 auto *NextTok = Tokens->getNextNonComment();
520 if (!Line->InMacroBody && !Style.isTableGen()) {
522 while (NextTok->is(tok::hash)) {
523 NextTok = Tokens->getNextToken();
524 if (NextTok->isOneOf(tok::pp_not_keyword, tok::pp_define))
527 NextTok = Tokens->getNextToken();
528 }
while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));
530 while (NextTok->is(tok::comment))
531 NextTok = Tokens->getNextToken();
535 switch (
Tok->Tok.getKind()) {
537 if (Style.isJavaScript() && PrevTok) {
538 if (PrevTok->isOneOf(tok::colon, tok::less)) {
549 }
else if (PrevTok->is(tok::r_paren)) {
553 }
else if (Style.isJava() && PrevTok && PrevTok->is(tok::arrow)) {
558 LBraceStack.push_back({
Tok, PrevTok});
561 if (LBraceStack.empty())
563 if (
auto *LBrace = LBraceStack.back().Tok; LBrace->is(
BK_Unknown)) {
564 bool ProbablyBracedList =
false;
566 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
567 }
else if (LBrace->isNot(TT_EnumLBrace)) {
570 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
571 NextTok->OriginalColumn == 0;
581 ProbablyBracedList = LBrace->is(TT_BracedListLBrace);
583 ProbablyBracedList = ProbablyBracedList ||
584 (Style.isJavaScript() &&
585 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
588 ProbablyBracedList ||
589 (IsCpp && (PrevTok->Tok.isLiteral() ||
590 NextTok->isOneOf(tok::l_paren, tok::arrow)));
597 ProbablyBracedList ||
598 NextTok->isOneOf(tok::comma, tok::period, tok::colon,
599 tok::r_paren, tok::r_square, tok::ellipsis);
604 ProbablyBracedList ||
605 (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&
606 LBraceStack.back().PrevTok->isOneOf(tok::identifier,
610 ProbablyBracedList ||
611 (NextTok->is(tok::identifier) &&
612 PrevTok->isNoneOf(tok::semi, tok::r_brace, tok::l_brace));
614 ProbablyBracedList = ProbablyBracedList ||
615 (NextTok->is(tok::semi) &&
616 (!ExpectClassBody || LBraceStack.size() != 1));
619 ProbablyBracedList ||
620 (NextTok->isBinaryOperator() && !NextIsObjCMethod);
622 if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
625 NextTok = Tokens->getNextToken();
626 ProbablyBracedList = NextTok->isNot(tok::l_square);
630 if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
631 !FormatTok->Previous && NextTok->is(tok::eof) &&
635 PrevTok->isNoneOf(tok::semi,
BK_Block, tok::colon)) {
636 ProbablyBracedList =
true;
640 Tok->setBlockKind(BlockKind);
641 LBrace->setBlockKind(BlockKind);
643 LBraceStack.pop_back();
645 case tok::identifier:
646 if (
Tok->isNot(TT_StatementMacro))
657 if (!LBraceStack.empty() && LBraceStack.back().Tok->is(
BK_Unknown))
658 LBraceStack.back().Tok->setBlockKind(
BK_Block);
666 }
while (
Tok->isNot(tok::eof) && !LBraceStack.empty());
669 for (
const auto &Entry : LBraceStack)
673 FormatTok = Tokens->setPosition(StoredPosition);
677void UnwrappedLineParser::setPreviousRBraceType(
TokenType Type) {
678 if (
auto Prev = FormatTok->getPreviousNonComment();
679 Prev && Prev->is(tok::r_brace)) {
680 Prev->setFinalizedType(
Type);
687 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
690size_t UnwrappedLineParser::computePPHash()
const {
692 for (
const auto &i : PP.Stack) {
703bool UnwrappedLineParser::mightFitOnOneLine(
705 const auto ColumnLimit = Style.ColumnLimit;
706 if (ColumnLimit == 0)
709 auto &Tokens = ParsedLine.Tokens;
710 assert(!Tokens.empty());
712 const auto *LastToken = Tokens.back().Tok;
715 SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());
718 for (
const auto &Token : Tokens) {
720 auto &SavedToken = SavedTokens[Index++];
722 SavedToken.Tok->copyFrom(*Token.Tok);
723 SavedToken.Children = std::move(Token.Children);
726 AnnotatedLine
Line(ParsedLine);
727 assert(Line.Last == LastToken);
729 TokenAnnotator Annotator(Style, Keywords);
730 Annotator.annotate(Line);
731 Annotator.calculateFormattingInformation(Line);
733 auto Length = LastToken->TotalLength;
735 assert(OpeningBrace != Tokens.front().Tok);
736 if (
auto Prev = OpeningBrace->Previous;
737 Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
738 Length -= ColumnLimit;
740 Length -= OpeningBrace->TokenText.size() + 1;
743 if (
const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
744 assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
745 Length -= FirstToken->TokenText.size() + 1;
749 for (
auto &Token : Tokens) {
750 const auto &SavedToken = SavedTokens[Index++];
751 Token.Tok->copyFrom(*SavedToken.Tok);
752 Token.Children = std::move(SavedToken.Children);
753 delete SavedToken.Tok;
757 assert(!Line.InMacroBody);
758 assert(!Line.InPPDirective);
759 return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
763 bool MustBeDeclaration,
unsigned AddLevels,
bool MunchSemi,
bool KeepBraces,
764 IfStmtKind *IfKind,
bool UnindentWhitesmithsBraces,
765 bool IndentAfterExplicitAccessModifier) {
766 auto HandleVerilogBlockLabel = [
this]() {
768 if (Style.isVerilog() && FormatTok->is(tok::colon)) {
770 if (Keywords.isVerilogIdentifier(*FormatTok))
777 const bool VerilogHierarchy =
778 Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);
779 assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
780 (Style.isVerilog() &&
781 (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
782 "'{' or macro block token expected");
784 const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
785 auto Index = CurrentLines->size();
786 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
789 const bool IsWhitesmiths =
794 if (!VerilogHierarchy && AddLevels > 0 && IsWhitesmiths)
797 size_t PPStartHash = computePPHash();
799 const unsigned InitialLevel = Line->Level;
800 if (VerilogHierarchy) {
801 AddLevels += parseVerilogHierarchyHeader();
803 nextToken(AddLevels);
804 HandleVerilogBlockLabel();
808 if (Line->Level > 300)
811 if (MacroBlock && FormatTok->is(tok::l_paren))
814 size_t NbPreprocessorDirectives =
815 !parsingPPDirective() ? PreprocessorDirectives.size() : 0;
817 size_t OpeningLineIndex =
818 CurrentLines->empty() || !CurrentExpandedLines.empty()
820 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
825 if (UnindentWhitesmithsBraces)
828 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
834 Line->Level += AddLevels - (IsWhitesmiths ? 1 : 0);
837 bool SeenExplicitAccessModifier =
false;
838 const bool SimpleBlock =
839 parseLevel(
Tok, IfKind, &IfLBrace,
840 IndentAfterExplicitAccessModifier ? &SeenExplicitAccessModifier
846 if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)
847 : FormatTok->isNot(tok::r_brace)) {
848 Line->Level = InitialLevel;
849 FormatTok->setBlockKind(BK_Block);
853 if (FormatTok->is(tok::r_brace)) {
854 FormatTok->setBlockKind(BK_Block);
855 if (Tok->is(TT_NamespaceLBrace))
856 FormatTok->setFinalizedType(TT_NamespaceRBrace);
859 const bool IsFunctionRBrace =
860 FormatTok->is(tok::r_brace) &&
Tok->is(TT_FunctionLBrace);
862 auto RemoveBraces = [=]()
mutable {
865 assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
866 assert(FormatTok->is(tok::r_brace));
867 const bool WrappedOpeningBrace = !Tok->Previous;
868 if (WrappedOpeningBrace && FollowedByComment)
870 const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
871 if (KeepBraces && !HasRequiredIfBraces)
873 if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
874 const FormatToken *Previous = Tokens->getPreviousToken();
876 if (Previous->is(tok::r_brace) && !Previous->Optional)
881 assert(!CurrentLines->empty());
882 auto &LastLine = CurrentLines->back();
883 if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
885 if (
Tok->is(TT_ElseLBrace))
887 if (WrappedOpeningBrace) {
892 return mightFitOnOneLine((*CurrentLines)[Index],
Tok);
894 if (RemoveBraces()) {
895 Tok->MatchingParen = FormatTok;
896 FormatTok->MatchingParen =
Tok;
899 size_t PPEndHash = computePPHash();
901 if (SeenExplicitAccessModifier)
904 nextToken(-AddLevels);
909 if (Style.RemoveSemicolon && IsFunctionRBrace) {
910 while (FormatTok->is(tok::semi)) {
911 FormatTok->Optional =
true;
916 HandleVerilogBlockLabel();
918 if (MacroBlock && FormatTok->is(tok::l_paren))
921 Line->Level = InitialLevel;
923 if (FormatTok->is(tok::kw_noexcept)) {
928 if (FormatTok->is(tok::arrow)) {
932 parseStructuralElement();
935 if (MunchSemi && FormatTok->is(tok::semi))
938 if (PPStartHash == PPEndHash && CurrentExpandedLines.empty() &&
939 !containsExpansion(*
Line)) {
940 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
943 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
944 CurrentLines->size() - 1;
954 if (
Line.Tokens.size() < 4)
956 auto I =
Line.Tokens.begin();
957 if (I->Tok->TokenText !=
"goog")
960 if (I->Tok->isNot(tok::period))
963 if (I->Tok->TokenText !=
"scope")
966 return I->Tok->is(tok::l_paren);
975 if (
Line.Tokens.size() < 3)
977 auto I =
Line.Tokens.begin();
978 if (I->Tok->isNot(tok::l_paren))
984 return I->Tok->is(tok::l_paren);
990 bool IsJavaRecord =
false) {
992 return Style.BraceWrapping.AfterClass;
995 if (InitialToken.
is(TT_NamespaceMacro))
996 Kind = tok::kw_namespace;
998 const bool WrapRecordAllowed =
1001 Style.BraceWrapping.SplitEmptyRecord;
1004 case tok::kw_namespace:
1005 return Style.BraceWrapping.AfterNamespace;
1007 return Style.BraceWrapping.AfterClass && WrapRecordAllowed;
1009 return Style.BraceWrapping.AfterUnion && WrapRecordAllowed;
1010 case tok::kw_struct:
1011 return Style.BraceWrapping.AfterStruct && WrapRecordAllowed;
1013 return Style.BraceWrapping.AfterEnum;
1019void UnwrappedLineParser::parseChildBlock() {
1020 assert(FormatTok->is(tok::l_brace));
1021 FormatTok->setBlockKind(BK_Block);
1025 bool SkipIndent = (Style.isJavaScript() &&
1026 (isGoogScope(*
Line) || isIIFE(*
Line, Keywords)));
1027 ScopedLineState LineState(*
this);
1028 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
1030 Line->Level += SkipIndent ? 0 : 1;
1031 parseLevel(OpeningBrace);
1032 flushComments(isOnNewLine(*FormatTok));
1033 Line->Level -= SkipIndent ? 0 : 1;
1038void UnwrappedLineParser::parsePPDirective() {
1039 assert(FormatTok->is(tok::hash) &&
"'#' expected");
1040 ScopedMacroState MacroState(*
Line, Tokens, FormatTok);
1044 if (!FormatTok->Tok.getIdentifierInfo()) {
1049 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
1050 case tok::pp_define:
1057 case tok::pp_ifndef:
1061 case tok::pp_elifdef:
1062 case tok::pp_elifndef:
1069 case tok::pp_pragma:
1073 case tok::pp_warning:
1075 if (!
eof() && Style.isCpp())
1076 FormatTok->setFinalizedType(TT_AfterPPDirective);
1084void UnwrappedLineParser::conditionalCompilationCondition(
bool Unreachable) {
1085 size_t Line = CurrentLines->size();
1086 if (CurrentLines == &PreprocessorDirectives)
1087 Line += Lines.size();
1090 (!PP.Stack.empty() && PP.Stack.back().Kind == PP_Unreachable)) {
1091 PP.Stack.push_back({PP_Unreachable,
Line});
1093 PP.Stack.push_back({PP_Conditional,
Line});
1097void UnwrappedLineParser::conditionalCompilationStart(
bool Unreachable) {
1099 assert(PP.BranchLevel >= 0 &&
1100 PP.BranchLevel <= (
int)PP.LevelBranchIndex.size());
1101 if (PP.BranchLevel == (
int)PP.LevelBranchIndex.size()) {
1102 PP.LevelBranchIndex.push_back(0);
1103 PP.LevelBranchCount.push_back(0);
1105 PP.ChainBranchIndex.push(Unreachable ? -1 : 0);
1106 bool Skip = PP.LevelBranchIndex[PP.BranchLevel] > 0;
1107 conditionalCompilationCondition(Unreachable ||
Skip);
1110void UnwrappedLineParser::conditionalCompilationAlternative() {
1111 if (!PP.Stack.empty())
1112 PP.Stack.pop_back();
1113 assert(PP.BranchLevel < (
int)PP.LevelBranchIndex.size());
1114 if (!PP.ChainBranchIndex.empty())
1115 ++PP.ChainBranchIndex.top();
1116 conditionalCompilationCondition(
1117 PP.BranchLevel >= 0 && !PP.ChainBranchIndex.empty() &&
1118 PP.LevelBranchIndex[PP.BranchLevel] != PP.ChainBranchIndex.top());
1121void UnwrappedLineParser::conditionalCompilationEnd() {
1122 assert(PP.BranchLevel < (
int)PP.LevelBranchIndex.size());
1123 if (PP.BranchLevel >= 0 && !PP.ChainBranchIndex.empty()) {
1124 if (PP.ChainBranchIndex.top() + 1 > PP.LevelBranchCount[PP.BranchLevel])
1125 PP.LevelBranchCount[PP.BranchLevel] = PP.ChainBranchIndex.top() + 1;
1128 if (PP.BranchLevel > -1)
1130 if (!PP.ChainBranchIndex.empty())
1131 PP.ChainBranchIndex.pop();
1132 if (!PP.Stack.empty())
1133 PP.Stack.pop_back();
1136void UnwrappedLineParser::parsePPIf(
bool IfDef) {
1137 bool IfNDef = FormatTok->is(tok::pp_ifndef);
1139 bool Unreachable =
false;
1140 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText ==
"0"))
1142 if (IfDef && !IfNDef && FormatTok->TokenText ==
"SWIG")
1144 conditionalCompilationStart(Unreachable);
1148 bool MaybeIncludeGuard = IfNDef;
1149 if (PP.IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1150 for (
auto &
Line : Lines) {
1151 if (
Line.Tokens.front().Tok->isNot(tok::comment)) {
1152 MaybeIncludeGuard =
false;
1153 PP.IncludeGuard = IG_Rejected;
1161 if (PP.IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1162 PP.IncludeGuard = IG_IfNdefed;
1163 PP.IncludeGuardToken = IfCondition;
1167void UnwrappedLineParser::parsePPElse() {
1169 if (PP.IncludeGuard == IG_Defined && PP.BranchLevel == 0)
1170 PP.IncludeGuard = IG_Rejected;
1172 assert(PP.BranchLevel >= -1);
1173 if (PP.BranchLevel == -1)
1174 conditionalCompilationStart(
true);
1175 conditionalCompilationAlternative();
1181void UnwrappedLineParser::parsePPEndIf() {
1182 conditionalCompilationEnd();
1186void UnwrappedLineParser::parsePPDefine() {
1189 if (!FormatTok->Tok.getIdentifierInfo()) {
1190 PP.IncludeGuard = IG_Rejected;
1191 PP.IncludeGuardToken =
nullptr;
1196 bool MaybeIncludeGuard =
false;
1197 if (PP.IncludeGuard == IG_IfNdefed &&
1198 PP.IncludeGuardToken->TokenText == FormatTok->TokenText) {
1199 PP.IncludeGuard = IG_Defined;
1200 PP.IncludeGuardToken =
nullptr;
1201 for (
auto &
Line : Lines) {
1202 if (
Line.Tokens.front().Tok->isNoneOf(tok::comment, tok::hash)) {
1203 PP.IncludeGuard = IG_Rejected;
1207 MaybeIncludeGuard = PP.IncludeGuard == IG_Defined;
1215 FormatTok->Tok.setKind(tok::identifier);
1216 FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);
1220 if (MaybeIncludeGuard && !
eof())
1221 PP.IncludeGuard = IG_Rejected;
1223 if (FormatTok->is(tok::l_paren) && !FormatTok->hasWhitespaceBefore())
1226 Line->Level += PP.BranchLevel + 1;
1230 Line->PPLevel = PP.BranchLevel + (PP.IncludeGuard == IG_Defined ? 0 : 1);
1231 assert((
int)
Line->PPLevel >= 0);
1236 Line->InMacroBody =
true;
1238 if (!Style.SkipMacroDefinitionBody) {
1248 for (
auto *Comment : CommentsBeforeNextToken)
1249 Comment->Finalized =
true;
1252 FormatTok->Finalized =
true;
1253 FormatTok = Tokens->getNextToken();
1259void UnwrappedLineParser::parsePPPragma() {
1260 Line->InPragmaDirective =
true;
1264void UnwrappedLineParser::parsePPUnknown() {
1268 Line->Level += PP.BranchLevel + 1;
1278 return Tok.isNoneOf(tok::semi, tok::l_brace,
1281 tok::period, tok::periodstar, tok::arrow, tok::arrowstar,
1282 tok::less, tok::greater, tok::slash, tok::percent,
1283 tok::lessless, tok::greatergreater, tok::equal,
1284 tok::plusequal, tok::minusequal, tok::starequal,
1285 tok::slashequal, tok::percentequal, tok::ampequal,
1286 tok::pipeequal, tok::caretequal, tok::greatergreaterequal,
1299 return FormatTok->
is(tok::identifier) &&
1314 FormatTok->
isOneOf(tok::kw_true, tok::kw_false) ||
1325 tok::kw_if, tok::kw_else,
1327 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
1329 tok::kw_switch, tok::kw_case,
1331 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.
kw_finally,
1333 tok::kw_const, tok::kw_class, Keywords.
kw_var, Keywords.
kw_let,
1341 return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
1342 tok::kw_unsigned, tok::kw_float, tok::kw_double,
1359 if (FuncName->
isNot(tok::identifier))
1367 Tok->isNoneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
1371 if (
Next->isNot(tok::star) && !
Next->Tok.getIdentifierInfo())
1375 if (!
Tok ||
Tok->isNot(tok::r_paren))
1379 if (!
Tok ||
Tok->isNot(tok::identifier))
1382 return Tok->Previous &&
Tok->Previous->isOneOf(tok::l_paren, tok::comma);
1385bool UnwrappedLineParser::parseModuleDecl() {
1387 assert(FormatTok->is(Keywords.kw_module));
1395 if (FormatTok->isNot(tok::identifier))
1398 for (nextToken(); FormatTok->isNoneOf(tok::semi, tok::eof); nextToken())
1399 if (FormatTok->is(tok::colon))
1400 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1403 Line->IsModuleOrImportDecl =
true;
1408bool UnwrappedLineParser::parseImportDecl() {
1410 assert(FormatTok->is(Keywords.kw_import) &&
"'import' expected");
1418 if (FormatTok->is(tok::colon)) {
1419 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1422 if (FormatTok->isNoneOf(tok::identifier, tok::less, tok::string_literal))
1425 for (; FormatTok->isNoneOf(tok::semi, tok::eof); nextToken()) {
1427 if (FormatTok->is(tok::less)) {
1428 for (nextToken(); FormatTok->isNoneOf(tok::greater, tok::semi, tok::eof);
1432 FormatTok->setFinalizedType(TT_ImplicitStringLiteral);
1438 Line->IsModuleOrImportDecl =
true;
1450void UnwrappedLineParser::readTokenWithJavaScriptASI() {
1456 CommentsBeforeNextToken.empty()
1457 ?
Next->NewlinesBefore == 0
1458 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
1463 bool PreviousStartsTemplateExpr =
1465 if (PreviousMustBeValue ||
Previous->is(tok::r_paren)) {
1468 bool HasAt = llvm::any_of(
Line->Tokens, [](UnwrappedLineNode &LineNode) {
1469 return LineNode.Tok->is(tok::at);
1474 if (
Next->is(tok::exclaim) && PreviousMustBeValue)
1475 return addUnwrappedLine();
1477 bool NextEndsTemplateExpr =
1478 Next->is(TT_TemplateString) &&
Next->TokenText.starts_with(
"}");
1479 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
1480 (PreviousMustBeValue ||
1481 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
1482 tok::minusminus))) {
1483 return addUnwrappedLine();
1485 if ((PreviousMustBeValue ||
Previous->is(tok::r_paren)) &&
1487 return addUnwrappedLine();
1491void UnwrappedLineParser::parseStructuralElement(
1492 const FormatToken *OpeningBrace, IfStmtKind *IfKind,
1493 FormatToken **IfLeftBrace,
bool *HasDoWhile,
bool *HasLabel) {
1494 if (Style.isTableGen() && FormatTok->is(tok::pp_include)) {
1496 if (FormatTok->is(tok::string_literal))
1503 while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
1505 }
else if (Style.isVerilog()) {
1507 while (FormatTok->is(tok::l_paren) &&
1508 Tokens->peekNextToken()->is(tok::star)) {
1511 skipVerilogQualifiers();
1513 if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
1514 Keywords.kw_unique0)) {
1518 if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {
1519 parseForOrWhileLoop(
false);
1522 if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {
1523 parseForOrWhileLoop();
1526 if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
1527 Keywords.kw_assume, Keywords.kw_cover)) {
1528 parseIfThenElse(IfKind,
false,
true);
1534 if (FormatTok->isAccessSpecifierKeyword()) {
1535 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
1538 parseAccessSpecifier();
1541 switch (FormatTok->Tok.getKind()) {
1546 bool DoNotFormat =
false;
1551 FormatTok->isOneOf(tok::kw_volatile, tok::kw_inline, tok::kw_goto)) {
1556 if (FormatTok->is(tok::l_brace)) {
1557 FormatTok->setFinalizedType(TT_InlineASMBrace);
1558 OpenType = tok::l_brace;
1559 CloseType = tok::r_brace;
1561 }
else if (FormatTok->is(tok::l_paren)) {
1562 OpenType = tok::l_paren;
1563 CloseType = tok::r_paren;
1564 FormatTok->setFinalizedType(TT_InlineASMParen);
1572 while (FormatTok && !
eof()) {
1573 if (FormatTok->is(OpenType)) {
1575 }
else if (FormatTok->is(CloseType)) {
1577 if (NestLevel < 1) {
1578 FormatTok->setFinalizedType(OpenTok->getType());
1584 FormatTok->Finalized =
true;
1590 case tok::kw_namespace:
1594 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1605 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1609 parseForOrWhileLoop();
1612 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1620 case tok::kw_switch:
1621 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1627 case tok::kw_default: {
1629 if (Style.isVerilog())
1631 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1637 if (FormatTok->is(tok::colon)) {
1638 FormatTok->setFinalizedType(TT_CaseLabelColon);
1642 if (FormatTok->is(tok::arrow)) {
1643 FormatTok->setFinalizedType(TT_CaseLabelArrow);
1644 Default->setFinalizedType(TT_SwitchExpressionLabel);
1657 if (Style.isVerilog()) {
1662 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1671 if (FormatTok->is(tok::kw_case))
1676 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1682 case tok::kw_extern:
1683 if (Style.isVerilog()) {
1686 parseVerilogExtern();
1690 if (FormatTok->is(tok::string_literal)) {
1692 if (FormatTok->is(tok::l_brace)) {
1693 if (Style.BraceWrapping.AfterExternBlock)
1697 unsigned AddLevels =
1699 (Style.BraceWrapping.AfterExternBlock &&
1700 Style.IndentExternBlock ==
1704 parseBlock(
true, AddLevels);
1710 case tok::kw_export:
1713 if (FormatTok->is(tok::kw_namespace)) {
1717 if (FormatTok->is(tok::l_brace)) {
1718 parseCppExportBlock();
1721 if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
1723 if (FormatTok->is(Keywords.kw_import) && parseImportDecl())
1727 if (Style.isJavaScript()) {
1728 parseJavaScriptEs6ImportExport();
1731 if (Style.isVerilog()) {
1732 parseVerilogExtern();
1736 case tok::kw_inline:
1738 if (FormatTok->is(tok::kw_namespace)) {
1743 case tok::identifier:
1744 if (FormatTok->is(TT_ForEachMacro)) {
1745 parseForOrWhileLoop();
1748 if (FormatTok->is(TT_MacroBlockBegin)) {
1749 parseBlock(
false, 1u,
1753 if (FormatTok->is(Keywords.kw_import)) {
1754 if (IsCpp && parseImportDecl())
1756 if (Style.isJavaScript()) {
1757 parseJavaScriptEs6ImportExport();
1762 if (FormatTok->is(tok::kw_public))
1764 if (FormatTok->isNot(tok::string_literal))
1767 if (FormatTok->is(tok::semi))
1772 if (Style.isVerilog()) {
1773 parseVerilogExtern();
1778 if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
1780 if (FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
1781 Keywords.kw_slots, Keywords.kw_qslots)) {
1783 if (FormatTok->is(tok::colon)) {
1789 if (FormatTok->is(TT_StatementMacro)) {
1790 parseStatementMacro();
1793 if (FormatTok->is(TT_NamespaceMacro)) {
1802 if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&
1803 Tokens->peekNextToken()->is(tok::colon) && !
Line->MustBeDeclaration) {
1805 if (!
Line->InMacroBody || CurrentLines->size() > 1)
1806 Line->Tokens.begin()->Tok->MustBreakBefore =
true;
1807 FormatTok->setFinalizedType(TT_GotoLabelColon);
1813 if (Style.isJava() && FormatTok->is(Keywords.kw_record)) {
1814 parseRecord(
false,
true);
1824 bool SeenEqual =
false;
1825 for (
const bool InRequiresExpression =
1826 OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
1827 TT_CompoundRequirementLBrace);
1830 switch (FormatTok->Tok.getKind()) {
1833 if (FormatTok->is(tok::l_brace)) {
1838 if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) {
1842 switch (
bool IsAutoRelease =
false; FormatTok->Tok.getObjCKeywordID()) {
1843 case tok::objc_public:
1844 case tok::objc_protected:
1845 case tok::objc_package:
1846 case tok::objc_private:
1847 return parseAccessSpecifier();
1848 case tok::objc_interface:
1849 case tok::objc_implementation:
1850 return parseObjCInterfaceOrImplementation();
1851 case tok::objc_protocol:
1852 if (parseObjCProtocol())
1857 case tok::objc_optional:
1858 case tok::objc_required:
1862 case tok::objc_autoreleasepool:
1863 IsAutoRelease =
true;
1865 case tok::objc_synchronized:
1867 if (!IsAutoRelease && FormatTok->is(tok::l_paren)) {
1871 if (FormatTok->is(tok::l_brace)) {
1872 if (Style.BraceWrapping.AfterControlStatement ==
1889 case tok::kw_requires: {
1891 bool ParsedClause = parseRequires(SeenEqual);
1912 if (!IsCpp && !Style.isVerilog()) {
1917 case tok::kw_typedef:
1919 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1920 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
1921 Keywords.kw_CF_CLOSED_ENUM,
1922 Keywords.kw_NS_CLOSED_ENUM)) {
1927 if (Style.isVerilog()) {
1932 if (Style.isTableGen()) {
1939 case tok::kw_struct:
1941 if (parseStructLike())
1944 case tok::kw_decltype:
1946 if (FormatTok->is(tok::l_paren)) {
1948 if (FormatTok->Previous &&
1949 FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
1951 Line->SeenDecltypeAuto =
true;
1958 if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class))
1960 if (Style.isJavaScript() && FormatTok &&
1961 FormatTok->Tok.getIdentifierInfo()) {
1974 case tok::string_literal:
1975 if (Style.isVerilog() && FormatTok->is(TT_VerilogProtected)) {
1976 FormatTok->Finalized =
true;
1983 case tok::l_paren: {
1990 Tokens->peekNextToken(
true),
1997 case tok::kw_operator:
1999 if (FormatTok->isBinaryOperator())
2003 const auto *Prev = FormatTok->getPreviousNonComment();
2005 if (Prev && Prev->is(tok::identifier))
2008 if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {
2011 if (FormatTok->is(tok::less)) {
2013 parseBracedList(
true);
2016 while (FormatTok->is(tok::star))
2020 if (FormatTok->is(tok::l_paren))
2023 if (FormatTok->is(tok::l_brace))
2028 if (InRequiresExpression)
2029 FormatTok->setFinalizedType(TT_BracedListLBrace);
2030 if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
2031 IsDecltypeAutoFunction =
Line->SeenDecltypeAuto;
2036 if (Style.isJava() &&
2037 Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
2040 if (Style.BraceWrapping.AfterControlStatement ==
2044 }
else if (Style.BraceWrapping.AfterFunction) {
2048 FormatTok->setFinalizedType(TT_FunctionLBrace);
2050 IsDecltypeAutoFunction =
false;
2058 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2064 if (Style.BraceWrapping.AfterFunction)
2068 case tok::identifier: {
2069 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&
2070 Line->MustBeDeclaration) {
2072 parseCSharpGenericTypeConstraint();
2075 if (FormatTok->is(TT_MacroBlockEnd)) {
2084 size_t TokenCount =
Line->Tokens.size();
2085 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&
2088 Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {
2089 tryToParseJSFunction();
2092 if ((Style.isJavaScript() || Style.isJava()) &&
2093 FormatTok->is(Keywords.kw_interface)) {
2094 if (Style.isJavaScript()) {
2099 unsigned StoredPosition = Tokens->getPosition();
2101 FormatTok = Tokens->setPosition(StoredPosition);
2112 if (Style.isVerilog()) {
2113 if (FormatTok->is(Keywords.kw_table)) {
2114 parseVerilogTable();
2117 if (Keywords.isVerilogBegin(*FormatTok) ||
2118 Keywords.isVerilogHierarchy(*FormatTok)) {
2125 if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
2126 if (parseStructLike())
2131 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
2132 parseStatementMacro();
2137 StringRef
Text = FormatTok->TokenText;
2144 if (Style.isJavaScript())
2147 auto OneTokenSoFar = [&]() {
2148 auto I =
Line->Tokens.begin(), E =
Line->Tokens.end();
2149 while (I != E && I->Tok->is(tok::comment))
2151 if (Style.isVerilog())
2152 while (I != E && I->Tok->is(tok::hash))
2154 return I != E && (++I == E);
2156 if (OneTokenSoFar()) {
2159 bool FunctionLike = FormatTok->is(tok::l_paren);
2163 bool FollowedByNewline =
2164 CommentsBeforeNextToken.empty()
2165 ? FormatTok->NewlinesBefore > 0
2166 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
2168 if (FollowedByNewline &&
2169 (
Text.size() >= 5 ||
2170 (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
2172 if (PreviousToken->isNot(TT_UntouchableMacroFunc))
2173 PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
2181 if ((Style.isJavaScript() || Style.isCSharp()) &&
2182 FormatTok->is(TT_FatArrow)) {
2183 tryToParseChildBlock();
2189 if (FormatTok->is(tok::l_brace)) {
2193 if (!Style.isJavaScript())
2194 FormatTok->setBlockKind(BK_BracedInit);
2197 if (Style.isTableGen() &&
2198 Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {
2199 FormatTok->setFinalizedType(TT_FunctionLBrace);
2200 parseBlock(
false, 1u,
2208 FormatTok->is(tok::less)) {
2210 parseBracedList(
true);
2217 if ((Style.isCSharp() &&
2218 (Tokens->peekNextToken()->isAccessSpecifierKeyword() ||
2220 FormatTok->endsSequence(tok::kw_new, tok::kw_operator)) {
2226 case tok::kw_switch:
2239 if (Style.isVerilog()) {
2244 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2251 case tok::kw_default:
2253 if (Style.isVerilog()) {
2254 if (FormatTok->is(tok::colon)) {
2258 if (FormatTok->is(Keywords.kw_clocking)) {
2264 parseVerilogCaseLabel();
2270 if (Style.isVerilog()) {
2271 parseVerilogCaseLabel();
2277 if (FormatTok->is(tok::l_brace))
2278 FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
2287bool UnwrappedLineParser::tryToParsePropertyAccessor() {
2288 assert(FormatTok->is(tok::l_brace));
2289 if (!Style.isCSharp())
2292 if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))
2300 unsigned int StoredPosition = Tokens->getPosition();
2306 bool HasSpecialAccessor =
false;
2307 bool IsTrivialPropertyAccessor =
true;
2310 if (
const bool IsAccessorKeyword =
2311 Tok->
isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set);
2312 IsAccessorKeyword ||
Tok->isAccessSpecifierKeyword() ||
2313 Tok->
isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {
2314 if (IsAccessorKeyword)
2315 HasSpecialAccessor =
true;
2316 else if (
Tok->
is(tok::l_square))
2318 Tok = Tokens->getNextToken();
2322 IsTrivialPropertyAccessor =
false;
2327 Tokens->setPosition(StoredPosition);
2333 Tokens->setPosition(StoredPosition);
2334 if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)
2338 switch (FormatTok->Tok.getKind()) {
2341 if (FormatTok->is(tok::equal)) {
2342 while (!
eof() && FormatTok->isNot(tok::semi))
2355 if (FormatTok->is(TT_FatArrow)) {
2359 }
while (!
eof() && FormatTok->isNot(tok::semi));
2368 if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,
2370 !IsTrivialPropertyAccessor) {
2382bool UnwrappedLineParser::tryToParseLambda() {
2383 assert(FormatTok->is(tok::l_square));
2389 if (!tryToParseLambdaIntroducer())
2393 bool InTemplateParameterList =
false;
2395 while (FormatTok->isNot(tok::l_brace)) {
2396 if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {
2400 switch (FormatTok->Tok.getKind()) {
2404 parseParens(TT_PointerOrReference);
2410 assert(FormatTok->Previous);
2411 if (FormatTok->Previous->is(tok::r_square))
2412 InTemplateParameterList =
true;
2417 case tok::kw_struct:
2419 case tok::kw_template:
2420 case tok::kw_typename:
2424 case tok::kw_constexpr:
2425 case tok::kw_consteval:
2428 case tok::identifier:
2429 case tok::numeric_constant:
2430 case tok::coloncolon:
2431 case tok::kw_mutable:
2432 case tok::kw_noexcept:
2433 case tok::kw_static:
2458 case tok::equalequal:
2459 case tok::exclaimequal:
2460 case tok::greaterequal:
2461 case tok::lessequal:
2467 if (Arrow || InTemplateParameterList) {
2476 case tok::kw_requires:
2477 parseRequiresClause();
2480 if (!InTemplateParameterList)
2489 FormatTok->setFinalizedType(TT_LambdaLBrace);
2490 LSquare.setFinalizedType(TT_LambdaLSquare);
2493 Arrow->setFinalizedType(TT_LambdaArrow);
2495 NestedLambdas.push_back(
Line->SeenDecltypeAuto);
2497 assert(!NestedLambdas.empty());
2498 NestedLambdas.pop_back();
2503bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
2508 const auto *PrevPrev =
Previous->getPreviousNonComment();
2509 if (
Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts))
2517 if (!PrevPrev || PrevPrev->isNoneOf(tok::greater, tok::r_paren))
2521 Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
2522 tok::kw_co_return)) {
2526 if (LeftSquare->isCppStructuredBinding(IsCpp))
2528 if (FormatTok->is(tok::l_square) ||
tok::isLiteral(FormatTok->Tok.getKind()))
2530 if (FormatTok->is(tok::r_square)) {
2532 if (
Next->is(tok::greater))
2539void UnwrappedLineParser::tryToParseJSFunction() {
2540 assert(FormatTok->is(Keywords.kw_function));
2541 if (FormatTok->is(Keywords.kw_async))
2547 if (FormatTok->is(tok::star)) {
2548 FormatTok->setFinalizedType(TT_OverloadedOperator);
2553 if (FormatTok->is(tok::identifier))
2556 if (FormatTok->isNot(tok::l_paren))
2562 if (FormatTok->is(tok::colon)) {
2568 if (FormatTok->is(tok::l_brace))
2569 tryToParseBracedList();
2571 while (FormatTok->isNoneOf(tok::l_brace, tok::semi) && !
eof())
2575 if (FormatTok->is(tok::semi))
2581bool UnwrappedLineParser::tryToParseBracedList() {
2582 if (FormatTok->is(BK_Unknown))
2583 calculateBraceTypes();
2584 assert(FormatTok->isNot(BK_Unknown));
2585 if (FormatTok->is(BK_Block))
2592bool UnwrappedLineParser::tryToParseChildBlock() {
2593 assert(Style.isJavaScript() || Style.isCSharp());
2594 assert(FormatTok->is(TT_FatArrow));
2599 if (FormatTok->isNot(tok::l_brace))
2605bool UnwrappedLineParser::parseBracedList(
bool IsAngleBracket,
bool IsEnum) {
2606 assert(!IsAngleBracket || !IsEnum);
2607 bool HasError =
false;
2612 if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
2613 tryToParseChildBlock()) {
2616 if (Style.isJavaScript()) {
2617 if (FormatTok->is(Keywords.kw_function)) {
2618 tryToParseJSFunction();
2621 if (FormatTok->is(tok::l_brace)) {
2623 if (tryToParseBracedList())
2628 if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
2630 FormatTok->setBlockKind(BK_Block);
2631 if (!Style.AllowShortEnumsOnASingleLine)
2637 switch (FormatTok->Tok.getKind()) {
2639 if (Style.isCSharp())
2648 if (Style.isJavaScript()) {
2649 if (FormatTok->is(tok::l_brace))
2657 FormatTok->setBlockKind(BK_BracedInit);
2658 if (!IsAngleBracket) {
2659 auto *Prev = FormatTok->Previous;
2660 if (Prev && Prev->is(tok::greater))
2661 Prev->setFinalizedType(TT_TemplateCloser);
2669 parseBracedList(
true);
2676 if (Style.isJavaScript()) {
2687 if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
2690 case tok::kw_requires:
2691 parseRequiresExpression();
2708bool UnwrappedLineParser::parseParens(TokenType StarAndAmpTokenType,
2710 assert(FormatTok->is(tok::l_paren) &&
"'(' expected.");
2711 auto *LParen = FormatTok;
2712 auto *Prev = FormatTok->Previous;
2713 bool SeenComma =
false;
2714 bool SeenEqual =
false;
2715 bool MightBeFoldExpr =
false;
2716 unsigned ExcessLess = 0;
2718 const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
2719 if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
2722 switch (FormatTok->Tok.getKind()) {
2724 if (parseParens(ExcessLess == 0 ? StarAndAmpTokenType : TT_Unknown,
2728 if (Style.isJava() && FormatTok->is(tok::l_brace))
2731 case tok::r_paren: {
2732 auto *RParen = FormatTok;
2735 auto OptionalParens = [&] {
2737 MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
2738 Line->InMacroBody || RParen->getPreviousNonComment() == LParen) {
2741 const bool DoubleParens =
2742 Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);
2744 const auto *PrevPrev = Prev->getPreviousNonComment();
2745 const bool Excluded =
2747 (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2749 (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2750 PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2754 const bool CommaSeparated =
2755 Prev->isOneOf(tok::l_paren, tok::comma) &&
2756 FormatTok->isOneOf(tok::comma, tok::r_paren);
2757 if (CommaSeparated &&
2759 !Prev->endsSequence(tok::comma, tok::ellipsis) &&
2761 !(FormatTok->is(tok::comma) &&
2762 Tokens->peekNextToken()->is(tok::ellipsis))) {
2765 const bool ReturnParens =
2767 ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2768 (!NestedLambdas.empty() && !NestedLambdas.back())) &&
2769 Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
2770 FormatTok->is(tok::semi);
2776 if (OptionalParens()) {
2777 LParen->Optional =
true;
2778 RParen->Optional =
true;
2779 }
else if (Prev->is(TT_TypenameMacro)) {
2780 LParen->setFinalizedType(TT_TypeDeclarationParen);
2781 RParen->setFinalizedType(TT_TypeDeclarationParen);
2782 }
else if (Prev->is(tok::greater) && RParen->Previous == LParen) {
2783 Prev->setFinalizedType(TT_TemplateCloser);
2784 }
else if (FormatTok->is(tok::l_brace) && Prev->is(tok::amp) &&
2786 FormatTok->setBlockKind(BK_BracedInit);
2798 if (!tryToParseBracedList())
2803 if (FormatTok->is(tok::l_brace)) {
2813 MightBeFoldExpr =
true;
2818 if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
2819 tryToParseChildBlock();
2824 if (Style.isJavaScript())
2829 case tok::identifier:
2830 if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))
2831 tryToParseJSFunction();
2835 case tok::kw_switch:
2841 case tok::kw_requires:
2842 parseRequiresExpression();
2858 if (StarAndAmpTokenType != TT_Unknown && ExcessLess == 0)
2859 FormatTok->setFinalizedType(StarAndAmpTokenType);
2869void UnwrappedLineParser::parseSquare(
bool SkipLambda) {
2871 assert(FormatTok->is(tok::l_square) &&
"'[' expected.");
2872 if (tryToParseLambda())
2876 switch (FormatTok->Tok.getKind()) {
2889 case tok::l_brace: {
2890 if (!tryToParseBracedList())
2897 if (FormatTok->is(tok::l_brace)) {
2909void UnwrappedLineParser::keepAncestorBraces() {
2910 if (!Style.RemoveBracesLLVM)
2913 const int MaxNestingLevels = 2;
2914 const int Size = NestedTooDeep.size();
2915 if (Size >= MaxNestingLevels)
2916 NestedTooDeep[
Size - MaxNestingLevels] =
true;
2917 NestedTooDeep.push_back(
false);
2921 for (
const auto &
Token : llvm::reverse(
Line.Tokens))
2928void UnwrappedLineParser::parseUnbracedBody(
bool CheckEOF) {
2931 if (Style.InsertBraces && !
Line->InPPDirective && !
Line->Tokens.empty() &&
2932 PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
2934 ? getLastNonComment(*
Line)
2937 if (
Tok->BraceCount < 0) {
2938 assert(
Tok->BraceCount == -1);
2941 Tok->BraceCount = -1;
2946 const auto BodyStart = CurrentLines->size();
2948 ++
Line->UnbracedBodyLevel;
2949 parseStructuralElement();
2950 --
Line->UnbracedBodyLevel;
2953 assert(!
Line->InPPDirective);
2956 auto BodyEnd = CurrentLines->size();
2957 while (BodyEnd > 0) {
2958 const auto &L = (*CurrentLines)[--BodyEnd];
2960 Tok = L.Tokens.back().Tok;
2966 bool EnclosesPPDirective =
false;
2967 for (
size_t I = BodyStart; I <= BodyEnd && !EnclosesPPDirective; ++I) {
2968 const auto &BodyLine = (*CurrentLines)[I];
2969 EnclosesPPDirective =
2970 BodyLine.InPPDirective ||
2971 llvm::any_of(BodyLine.Tokens, [](
const UnwrappedLineNode &Node) {
2972 return Node.Tok->FirstAfterPPLine;
2975 if (EnclosesPPDirective)
2976 LBraceTok->BraceCount = 0;
2981 if (CheckEOF &&
eof())
2991 assert(LeftBrace->
is(tok::l_brace));
2999 assert(RightBrace->
is(tok::r_brace));
3007void UnwrappedLineParser::handleAttributes() {
3009 if (FormatTok->isAttribute())
3011 else if (FormatTok->is(tok::l_square))
3012 handleCppAttributes();
3015bool UnwrappedLineParser::handleCppAttributes() {
3017 assert(FormatTok->is(tok::l_square));
3018 if (!tryToParseSimpleAttribute())
3025bool UnwrappedLineParser::isBlockBegin(
const FormatToken &
Tok)
const {
3028 return Style.isVerilog() ? Keywords.isVerilogBegin(
Tok)
3029 :
Tok.
is(tok::l_brace);
3032FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
3034 bool IsVerilogAssert) {
3035 assert((FormatTok->is(tok::kw_if) ||
3036 (Style.isVerilog() &&
3037 FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
3038 Keywords.kw_assume, Keywords.kw_cover))) &&
3042 if (IsVerilogAssert) {
3044 if (FormatTok->is(Keywords.kw_verilogHash)) {
3046 if (FormatTok->is(tok::numeric_constant))
3048 }
else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,
3049 Keywords.kw_sequence)) {
3055 if (Style.isTableGen()) {
3056 while (!
eof() && FormatTok->isNot(Keywords.kw_then)) {
3063 if (FormatTok->is(tok::exclaim))
3066 bool KeepIfBraces =
true;
3067 if (FormatTok->is(tok::kw_consteval)) {
3070 KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;
3071 if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
3073 if (FormatTok->is(tok::l_paren)) {
3074 FormatTok->setFinalizedType(TT_ConditionLParen);
3080 if (IsVerilogAssert && FormatTok->is(tok::semi)) {
3086 bool NeedsUnwrappedLine =
false;
3087 keepAncestorBraces();
3090 IfStmtKind IfBlockKind = IfStmtKind::NotIf;
3092 if (isBlockBegin(*FormatTok)) {
3093 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3094 IfLeftBrace = FormatTok;
3095 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3096 parseBlock(
false, 1u,
3097 true, KeepIfBraces, &IfBlockKind);
3098 setPreviousRBraceType(TT_ControlStatementRBrace);
3099 if (Style.BraceWrapping.BeforeElse)
3102 NeedsUnwrappedLine =
true;
3103 }
else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {
3106 parseUnbracedBody();
3109 if (Style.RemoveBracesLLVM) {
3110 assert(!NestedTooDeep.empty());
3111 KeepIfBraces = KeepIfBraces ||
3112 (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
3113 NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
3114 IfBlockKind == IfStmtKind::IfElseIf;
3117 bool KeepElseBraces = KeepIfBraces;
3119 IfStmtKind
Kind = IfStmtKind::IfOnly;
3121 if (FormatTok->is(tok::kw_else)) {
3122 if (Style.RemoveBracesLLVM) {
3123 NestedTooDeep.back() =
false;
3124 Kind = IfStmtKind::IfElse;
3128 if (isBlockBegin(*FormatTok)) {
3129 const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
3130 FormatTok->setFinalizedType(TT_ElseLBrace);
3131 ElseLeftBrace = FormatTok;
3132 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3133 IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
3135 parseBlock(
false, 1u,
3136 true, KeepElseBraces, &ElseBlockKind);
3137 setPreviousRBraceType(TT_ElseRBrace);
3138 if (FormatTok->is(tok::kw_else)) {
3139 KeepElseBraces = KeepElseBraces ||
3140 ElseBlockKind == IfStmtKind::IfOnly ||
3141 ElseBlockKind == IfStmtKind::IfElseIf;
3142 }
else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
3143 KeepElseBraces =
true;
3144 assert(ElseLeftBrace->MatchingParen);
3148 }
else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {
3151 const bool IsPrecededByComment =
Previous->is(tok::comment);
3152 if (IsPrecededByComment) {
3156 bool TooDeep =
true;
3157 if (Style.RemoveBracesLLVM) {
3158 Kind = IfStmtKind::IfElseIf;
3159 TooDeep = NestedTooDeep.pop_back_val();
3161 ElseLeftBrace = parseIfThenElse(
nullptr, KeepIfBraces);
3162 if (Style.RemoveBracesLLVM)
3163 NestedTooDeep.push_back(TooDeep);
3164 if (IsPrecededByComment)
3167 parseUnbracedBody(
true);
3170 KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
3171 if (NeedsUnwrappedLine)
3175 if (!Style.RemoveBracesLLVM)
3178 assert(!NestedTooDeep.empty());
3179 KeepElseBraces = KeepElseBraces ||
3180 (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
3181 NestedTooDeep.back();
3183 NestedTooDeep.pop_back();
3185 if (!KeepIfBraces && !KeepElseBraces) {
3188 }
else if (IfLeftBrace) {
3189 FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
3191 assert(IfRightBrace->MatchingParen == IfLeftBrace);
3192 assert(!IfLeftBrace->Optional);
3193 assert(!IfRightBrace->Optional);
3194 IfLeftBrace->MatchingParen =
nullptr;
3195 IfRightBrace->MatchingParen =
nullptr;
3205void UnwrappedLineParser::parseTryCatch() {
3206 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) &&
"'try' expected");
3208 bool NeedsUnwrappedLine =
false;
3209 bool HasCtorInitializer =
false;
3210 if (FormatTok->is(tok::colon)) {
3211 auto *Colon = FormatTok;
3214 if (FormatTok->is(tok::identifier)) {
3215 HasCtorInitializer =
true;
3216 Colon->setFinalizedType(TT_CtorInitializerColon);
3221 while (FormatTok->is(tok::comma))
3224 while (FormatTok->is(tok::identifier)) {
3226 if (FormatTok->is(tok::l_paren)) {
3228 }
else if (FormatTok->is(tok::l_brace)) {
3235 while (FormatTok->is(tok::comma))
3240 if (Style.isJava() && FormatTok->is(tok::l_paren))
3243 keepAncestorBraces();
3245 if (FormatTok->is(tok::l_brace)) {
3246 if (HasCtorInitializer)
3247 FormatTok->setFinalizedType(TT_FunctionLBrace);
3248 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3250 if (Style.BraceWrapping.BeforeCatch)
3253 NeedsUnwrappedLine =
true;
3254 }
else if (FormatTok->isNot(tok::kw_catch)) {
3260 parseStructuralElement();
3263 for (
bool SeenCatch =
false;;) {
3264 if (FormatTok->is(tok::at))
3266 if (FormatTok->isNoneOf(tok::kw_catch, Keywords.kw___except,
3267 tok::kw___finally, tok::objc_catch,
3268 tok::objc_finally) &&
3269 !((Style.isJava() || Style.isJavaScript()) &&
3270 FormatTok->is(Keywords.kw_finally))) {
3273 if (FormatTok->is(tok::kw_catch))
3276 while (FormatTok->isNot(tok::l_brace)) {
3277 if (FormatTok->is(tok::l_paren)) {
3281 if (FormatTok->isOneOf(tok::semi, tok::r_brace) ||
eof()) {
3282 if (Style.RemoveBracesLLVM)
3283 NestedTooDeep.pop_back();
3289 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3292 NeedsUnwrappedLine =
false;
3293 Line->MustBeDeclaration =
false;
3294 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3296 if (Style.BraceWrapping.BeforeCatch)
3299 NeedsUnwrappedLine =
true;
3302 if (Style.RemoveBracesLLVM)
3303 NestedTooDeep.pop_back();
3305 if (NeedsUnwrappedLine)
3309void UnwrappedLineParser::parseNamespaceOrExportBlock(
unsigned AddLevels) {
3310 bool ManageWhitesmithsBraces =
3315 if (ManageWhitesmithsBraces)
3320 parseBlock(
true, AddLevels,
true,
3321 true,
nullptr, ManageWhitesmithsBraces);
3323 addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
3325 if (ManageWhitesmithsBraces)
3329void UnwrappedLineParser::parseNamespace() {
3330 assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
3331 "'namespace' expected");
3335 if (InitialToken.is(TT_NamespaceMacro)) {
3338 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
3339 tok::l_square, tok::period, tok::l_paren) ||
3340 (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
3341 if (FormatTok->is(tok::l_square))
3343 else if (FormatTok->is(tok::l_paren))
3349 if (FormatTok->is(tok::l_brace)) {
3350 FormatTok->setFinalizedType(TT_NamespaceLBrace);
3353 Tokens->peekNextToken()->is(tok::r_brace))) {
3357 unsigned AddLevels =
3360 DeclarationScopeStack.size() > 1)
3363 parseNamespaceOrExportBlock(AddLevels);
3368void UnwrappedLineParser::parseCppExportBlock() {
3369 if (FormatTok->is(tok::l_brace)) {
3370 FormatTok->setFinalizedType(TT_ExportLBrace);
3371 if (Style.BraceWrapping.AfterExportBlock)
3374 parseNamespaceOrExportBlock(Style.IndentExportBlock ? 1 : 0);
3377void UnwrappedLineParser::parseNew() {
3378 assert(FormatTok->is(tok::kw_new) &&
"'new' expected");
3381 if (Style.isCSharp()) {
3384 if (FormatTok->is(tok::l_paren))
3388 if (FormatTok->is(tok::l_brace))
3391 if (FormatTok->isOneOf(tok::semi, tok::comma))
3396 }
else if (Style.isJava()) {
3400 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
3404 if (FormatTok->is(tok::l_paren)) {
3409 if (FormatTok->is(tok::l_brace))
3415 }
else if (Style.isCpp()) {
3419 if (FormatTok->is(tok::l_brace))
3421 if (FormatTok->is(tok::l_paren))
3423 if (FormatTok->is(tok::l_paren)) {
3429 if (FormatTok->isOneOf(tok::kw_alignas, tok::kw_decltype)) {
3431 if (FormatTok->is(tok::l_paren))
3433 }
else if (FormatTok->is(tok::l_square)) {
3436 }
else if (FormatTok->is(tok::less)) {
3438 parseBracedList(
true);
3439 }
else if (FormatTok->Tok.getIdentifierInfo() ||
3440 FormatTok->isOneOf(tok::coloncolon, tok::star)) {
3447 if (FormatTok->is(tok::l_brace))
3449 else if (FormatTok->is(tok::l_paren))
3454void UnwrappedLineParser::parseLoopBody(
bool KeepBraces,
bool WrapRightBrace) {
3455 keepAncestorBraces();
3457 if (isBlockBegin(*FormatTok)) {
3458 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3460 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3461 parseBlock(
false, 1u,
3463 setPreviousRBraceType(TT_ControlStatementRBrace);
3465 assert(!NestedTooDeep.empty());
3466 if (!NestedTooDeep.back())
3472 parseUnbracedBody();
3476 NestedTooDeep.pop_back();
3479void UnwrappedLineParser::parseForOrWhileLoop(
bool HasParens) {
3480 assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||
3481 (Style.isVerilog() &&
3482 FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,
3483 Keywords.kw_always_ff, Keywords.kw_always_latch,
3484 Keywords.kw_final, Keywords.kw_initial,
3485 Keywords.kw_foreach, Keywords.kw_forever,
3486 Keywords.kw_repeat))) &&
3487 "'for', 'while' or foreach macro expected");
3488 const bool KeepBraces = !Style.RemoveBracesLLVM ||
3489 FormatTok->isNoneOf(tok::kw_for, tok::kw_while);
3493 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
3495 if (IsCpp && FormatTok->is(tok::kw_co_await))
3497 if (HasParens && FormatTok->is(tok::l_paren)) {
3501 if (Style.isVerilog())
3502 FormatTok->setFinalizedType(TT_ConditionLParen);
3506 if (Style.isVerilog()) {
3508 parseVerilogSensitivityList();
3509 }
else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&
3510 Tokens->getPreviousToken()->is(tok::r_paren)) {
3517 parseLoopBody(KeepBraces,
true);
3520void UnwrappedLineParser::parseDoWhile() {
3521 assert(FormatTok->is(tok::kw_do) &&
"'do' expected");
3524 parseLoopBody(
true, Style.BraceWrapping.BeforeWhile);
3527 if (FormatTok->isNot(tok::kw_while)) {
3532 FormatTok->setFinalizedType(TT_DoWhile);
3540 parseStructuralElement();
3543void UnwrappedLineParser::parseLabel(
bool IsGotoLabel) {
3546 const auto IndentGotoLabel = Style.IndentGotoLabels;
3547 const auto OldLineLevel =
Line->Level;
3554 if (OldLineLevel > 1 || (!
Line->InPPDirective && OldLineLevel > 0))
3558 if (!IsGotoLabel && !Style.IndentCaseBlocks &&
3559 CommentsBeforeNextToken.empty() && FormatTok->is(tok::l_brace)) {
3560 CompoundStatementIndenter Indenter(
this,
Level,
3561 Style.BraceWrapping.AfterCaseLabel,
3562 Style.BraceWrapping.IndentBraces);
3564 if (FormatTok->is(tok::kw_break)) {
3565 if (Style.BraceWrapping.AfterControlStatement ==
3568 if (!Style.IndentCaseBlocks &&
3573 parseStructuralElement();
3577 if (FormatTok->is(tok::semi))
3582 Level = OldLineLevel;
3584 if (FormatTok->isNot(tok::l_brace)) {
3585 parseStructuralElement();
3590void UnwrappedLineParser::parseCaseLabel() {
3591 assert(FormatTok->is(tok::kw_case) &&
"'case' expected");
3592 auto *Case = FormatTok;
3597 if (FormatTok->is(tok::colon)) {
3598 FormatTok->setFinalizedType(TT_CaseLabelColon);
3601 if (Style.isJava() && FormatTok->is(tok::arrow)) {
3602 FormatTok->setFinalizedType(TT_CaseLabelArrow);
3603 Case->setFinalizedType(TT_SwitchExpressionLabel);
3610void UnwrappedLineParser::parseSwitch(
bool IsExpr) {
3611 assert(FormatTok->is(tok::kw_switch) &&
"'switch' expected");
3613 if (FormatTok->is(tok::l_paren))
3616 keepAncestorBraces();
3618 if (FormatTok->is(tok::l_brace)) {
3619 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3620 FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
3621 : TT_ControlStatementLBrace);
3626 setPreviousRBraceType(TT_ControlStatementRBrace);
3632 parseStructuralElement();
3636 if (Style.RemoveBracesLLVM)
3637 NestedTooDeep.pop_back();
3640void UnwrappedLineParser::parseAccessSpecifier() {
3643 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
3646 if (FormatTok->is(tok::colon))
3654bool UnwrappedLineParser::parseRequires(
bool SeenEqual) {
3655 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3659 switch (Tokens->peekNextToken(
true)->Tok.getKind()) {
3662 parseRequiresExpression();
3669 parseRequiresClause();
3680 auto *PreviousNonComment = FormatTok->getPreviousNonComment();
3682 if (!PreviousNonComment ||
3683 PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
3686 parseRequiresClause();
3690 switch (PreviousNonComment->Tok.getKind()) {
3693 case tok::kw_noexcept:
3698 parseRequiresClause();
3707 auto PrevPrev = PreviousNonComment->getPreviousNonComment();
3708 if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {
3709 parseRequiresClause();
3715 if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
3717 parseRequiresClause();
3721 parseRequiresExpression();
3731 unsigned StoredPosition = Tokens->getPosition();
3734 auto PeekNext = [&Lookahead, &NextToken,
this] {
3736 NextToken = Tokens->getNextToken();
3739 bool FoundType =
false;
3740 bool LastWasColonColon =
false;
3743 for (; Lookahead < 50; PeekNext()) {
3744 switch (NextToken->Tok.getKind()) {
3745 case tok::kw_volatile:
3748 if (OpenAngles == 0) {
3749 FormatTok = Tokens->setPosition(StoredPosition);
3750 parseRequiresExpression();
3758 case tok::coloncolon:
3759 LastWasColonColon =
true;
3761 case tok::kw_decltype:
3762 case tok::identifier:
3763 if (FoundType && !LastWasColonColon && OpenAngles == 0) {
3764 FormatTok = Tokens->setPosition(StoredPosition);
3765 parseRequiresExpression();
3769 LastWasColonColon =
false;
3778 if (NextToken->isTypeName(LangOpts)) {
3779 FormatTok = Tokens->setPosition(StoredPosition);
3780 parseRequiresExpression();
3787 FormatTok = Tokens->setPosition(StoredPosition);
3788 parseRequiresClause();
3797void UnwrappedLineParser::parseRequiresClause() {
3798 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3803 bool InRequiresExpression =
3804 !FormatTok->Previous ||
3805 FormatTok->Previous->is(TT_RequiresExpressionLBrace);
3807 FormatTok->setFinalizedType(InRequiresExpression
3808 ? TT_RequiresClauseInARequiresExpression
3809 : TT_RequiresClause);
3814 parseConstraintExpression();
3816 if (!InRequiresExpression && FormatTok->Previous)
3817 FormatTok->Previous->ClosesRequiresClause =
true;
3825void UnwrappedLineParser::parseRequiresExpression() {
3826 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3828 FormatTok->setFinalizedType(TT_RequiresExpression);
3831 if (FormatTok->is(tok::l_paren)) {
3832 FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
3836 if (FormatTok->is(tok::l_brace)) {
3837 FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
3846void UnwrappedLineParser::parseConstraintExpression() {
3853 bool LambdaNextTimeAllowed =
true;
3863 bool TopLevelParensAllowed =
true;
3866 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed,
false);
3868 switch (FormatTok->Tok.getKind()) {
3869 case tok::kw_requires:
3870 parseRequiresExpression();
3874 if (!TopLevelParensAllowed)
3876 parseParens(TT_BinaryOperator);
3877 TopLevelParensAllowed =
false;
3881 if (!LambdaThisTimeAllowed || !tryToParseLambda())
3888 case tok::kw_struct:
3898 FormatTok->setFinalizedType(TT_BinaryOperator);
3900 LambdaNextTimeAllowed =
true;
3901 TopLevelParensAllowed =
true;
3906 LambdaNextTimeAllowed = LambdaThisTimeAllowed;
3910 case tok::kw_sizeof:
3912 case tok::greaterequal:
3913 case tok::greatergreater:
3915 case tok::lessequal:
3917 case tok::equalequal:
3919 case tok::exclaimequal:
3924 LambdaNextTimeAllowed =
true;
3925 TopLevelParensAllowed =
true;
3930 case tok::numeric_constant:
3931 case tok::coloncolon:
3934 TopLevelParensAllowed =
false;
3939 case tok::kw_static_cast:
3940 case tok::kw_const_cast:
3941 case tok::kw_reinterpret_cast:
3942 case tok::kw_dynamic_cast:
3944 if (FormatTok->isNot(tok::less))
3948 parseBracedList(
true);
3952 if (!FormatTok->Tok.getIdentifierInfo()) {
3962 assert(FormatTok->Previous);
3963 switch (FormatTok->Previous->Tok.getKind()) {
3964 case tok::coloncolon:
3968 case tok::kw_requires:
3970 case tok::kw_template:
3978 if (FormatTok->is(tok::less)) {
3980 parseBracedList(
true);
3982 TopLevelParensAllowed =
false;
3988bool UnwrappedLineParser::parseEnum() {
3992 if (FormatTok->is(tok::kw_enum))
3998 if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
4007 if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
4009 while (FormatTok->is(tok::l_square))
4010 if (!handleCppAttributes())
4014 while (FormatTok->Tok.getIdentifierInfo() ||
4015 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
4016 tok::greater, tok::comma, tok::question,
4018 if (FormatTok->is(tok::colon))
4019 FormatTok->setFinalizedType(TT_EnumUnderlyingTypeColon);
4020 if (Style.isVerilog()) {
4021 FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
4024 while (FormatTok->is(tok::l_square))
4030 if (FormatTok->is(tok::l_paren))
4032 if (FormatTok->is(tok::identifier)) {
4036 if (IsCpp && FormatTok->is(tok::identifier))
4042 if (FormatTok->isNot(tok::l_brace))
4044 FormatTok->setFinalizedType(TT_EnumLBrace);
4045 FormatTok->setBlockKind(BK_Block);
4047 if (Style.isJava()) {
4049 parseJavaEnumBody();
4057 const bool ManageWhitesmithsBraces =
4060 if (!Style.AllowShortEnumsOnASingleLine &&
4062 Tokens->peekNextToken()->is(tok::r_brace))) {
4067 if (ManageWhitesmithsBraces)
4072 if (!Style.AllowShortEnumsOnASingleLine) {
4074 if (!ManageWhitesmithsBraces)
4077 const auto OpeningLineIndex =
4078 CurrentLines->empty() || !CurrentExpandedLines.empty()
4079 ? UnwrappedLine::kInvalidIndex
4080 : CurrentLines->size() - 1;
4081 bool HasError = !parseBracedList(
false,
true);
4082 if (!Style.AllowShortEnumsOnASingleLine && !ManageWhitesmithsBraces)
4085 if (FormatTok->is(tok::semi))
4089 setPreviousRBraceType(TT_EnumRBrace);
4090 if (ManageWhitesmithsBraces && CurrentExpandedLines.empty() &&
4091 !containsExpansion(*
Line)) {
4092 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
4101bool UnwrappedLineParser::parseStructLike() {
4106 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) {
4107 if (FormatTok->is(tok::semi))
4118class ScopedTokenPosition {
4119 unsigned StoredPosition;
4120 FormatTokenSource *Tokens;
4123 ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
4124 assert(Tokens &&
"Tokens expected to not be null");
4125 StoredPosition = Tokens->getPosition();
4128 ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
4134bool UnwrappedLineParser::tryToParseSimpleAttribute() {
4135 ScopedTokenPosition AutoPosition(Tokens);
4143 if (
Tok->
is(tok::r_square))
4145 Tok = Tokens->getNextToken();
4147 if (
Tok->
is(tok::eof))
4149 Tok = Tokens->getNextToken();
4152 Tok = Tokens->getNextToken();
4153 if (
Tok->
is(tok::semi))
4158void UnwrappedLineParser::parseJavaEnumBody() {
4159 assert(FormatTok->is(tok::l_brace));
4165 unsigned StoredPosition = Tokens->getPosition();
4166 bool IsSimple =
true;
4169 if (
Tok->
is(tok::r_brace))
4177 Tok = Tokens->getNextToken();
4179 FormatTok = Tokens->setPosition(StoredPosition);
4196 if (FormatTok->is(tok::l_brace)) {
4198 parseBlock(
true, 1u,
4200 }
else if (FormatTok->is(tok::l_paren)) {
4202 }
else if (FormatTok->is(tok::comma)) {
4205 }
else if (FormatTok->is(tok::semi)) {
4209 }
else if (FormatTok->is(tok::r_brace)) {
4218 parseLevel(OpeningBrace);
4224void UnwrappedLineParser::parseRecord(
bool ParseAsExpr,
bool IsJavaRecord) {
4225 assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record));
4230 IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok :
nullptr;
4231 bool IsDerived =
false;
4233 return Tok->
is(tok::identifier) &&
Tok->TokenText !=
Tok->TokenText.upper();
4237 bool JSPastExtendsOrImplements =
false;
4241 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
4242 tok::kw_alignas, tok::l_square) ||
4243 FormatTok->isAttribute() ||
4244 ((Style.isJava() || Style.isJavaScript()) &&
4245 FormatTok->isOneOf(tok::period, tok::comma)) ||
4246 (Style.isVerilog() &&
4247 FormatTok->isOneOf(tok::kw_signed, tok::kw_unsigned))) {
4248 if (Style.isJavaScript() &&
4249 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
4250 JSPastExtendsOrImplements =
true;
4255 if (FormatTok->is(tok::l_brace)) {
4256 tryToParseBracedList();
4260 if (FormatTok->is(tok::l_square) && handleCppAttributes())
4264 switch (FormatTok->Tok.getKind()) {
4267 if (IsJavaRecord || !IsNonMacroIdentifier(
Previous) ||
4269 Previous->Previous == &InitialToken) {
4273 case tok::coloncolon:
4277 if (JSPastExtendsOrImplements || ClassName ||
4288 auto IsListInitialization = [&] {
4289 if (!ClassName || IsDerived || JSPastExtendsOrImplements)
4291 assert(FormatTok->is(tok::l_brace));
4292 const auto *Prev = FormatTok->getPreviousNonComment();
4294 return Prev != ClassName && Prev->is(tok::identifier) &&
4295 Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
4298 if (FormatTok->isOneOf(tok::colon, tok::less)) {
4299 int AngleNestingLevel = 0;
4301 if (FormatTok->is(tok::less))
4302 ++AngleNestingLevel;
4303 else if (FormatTok->is(tok::greater))
4304 --AngleNestingLevel;
4306 if (AngleNestingLevel == 0) {
4307 if (FormatTok->is(tok::colon)) {
4309 }
else if (!IsDerived && FormatTok->is(tok::identifier) &&
4310 FormatTok->Previous->is(tok::coloncolon)) {
4311 ClassName = FormatTok;
4312 }
else if (FormatTok->is(tok::l_paren) &&
4313 IsNonMacroIdentifier(FormatTok->Previous)) {
4317 if (FormatTok->is(tok::l_brace)) {
4318 if (AngleNestingLevel == 0 && IsListInitialization())
4320 calculateBraceTypes(
true);
4321 if (!tryToParseBracedList())
4324 if (FormatTok->is(tok::l_square)) {
4327 !
Previous->isTypeOrIdentifier(LangOpts))) {
4330 if (!tryToParseLambda())
4337 if (FormatTok->is(tok::semi))
4339 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {
4342 parseCSharpGenericTypeConstraint();
4349 auto GetBraceTypes =
4350 [](
const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {
4351 switch (RecordTok.Tok.getKind()) {
4353 return {TT_ClassLBrace, TT_ClassRBrace};
4354 case tok::kw_struct:
4355 return {TT_StructLBrace, TT_StructRBrace};
4357 return {TT_UnionLBrace, TT_UnionRBrace};
4360 return {TT_RecordLBrace, TT_RecordRBrace};
4363 if (FormatTok->is(tok::l_brace)) {
4364 if (IsListInitialization())
4367 ClassName->setFinalizedType(TT_ClassHeadName);
4368 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
4369 FormatTok->setFinalizedType(OpenBraceType);
4374 Tokens->peekNextToken()->is(tok::r_brace),
4379 bool IndentAfterExplicitAccessModifier =
false;
4380 unsigned AddLevels = 1u;
4381 switch (Style.IndentAccessModifiers) {
4385 if (Style.isCpp()) {
4386 IndentAfterExplicitAccessModifier =
true;
4395 parseBlock(
true, AddLevels,
false,
4398 IndentAfterExplicitAccessModifier);
4400 setPreviousRBraceType(ClosingBraceType);
4407void UnwrappedLineParser::parseObjCMethod() {
4408 assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
4409 "'(' or identifier expected.");
4411 if (FormatTok->is(tok::semi)) {
4415 }
else if (FormatTok->is(tok::l_brace)) {
4416 if (Style.BraceWrapping.AfterFunction)
4427void UnwrappedLineParser::parseObjCProtocolList() {
4428 assert(FormatTok->is(tok::less) &&
"'<' expected.");
4432 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4434 }
while (!
eof() && FormatTok->isNot(tok::greater));
4438void UnwrappedLineParser::parseObjCUntilAtEnd() {
4440 if (FormatTok->is(tok::objc_end)) {
4445 if (FormatTok->is(tok::l_brace)) {
4449 }
else if (FormatTok->is(tok::r_brace)) {
4453 }
else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
4455 if (FormatTok->isOneOf(tok::l_paren, tok::identifier))
4458 parseStructuralElement();
4463void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
4464 assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation));
4470 if (FormatTok->is(tok::less))
4471 parseObjCLightweightGenerics();
4472 if (FormatTok->is(tok::colon)) {
4476 if (FormatTok->is(tok::less))
4477 parseObjCLightweightGenerics();
4478 }
else if (FormatTok->is(tok::l_paren)) {
4483 if (FormatTok->is(tok::less))
4484 parseObjCProtocolList();
4486 if (FormatTok->is(tok::l_brace)) {
4487 if (Style.BraceWrapping.AfterObjCDeclaration)
4496 parseObjCUntilAtEnd();
4499void UnwrappedLineParser::parseObjCLightweightGenerics() {
4500 assert(FormatTok->is(tok::less));
4508 unsigned NumOpenAngles = 1;
4512 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4514 if (FormatTok->is(tok::less)) {
4516 }
else if (FormatTok->is(tok::greater)) {
4517 assert(NumOpenAngles > 0 &&
"'>' makes NumOpenAngles negative");
4520 }
while (!
eof() && NumOpenAngles != 0);
4526bool UnwrappedLineParser::parseObjCProtocol() {
4527 assert(FormatTok->is(tok::objc_protocol));
4530 if (FormatTok->is(tok::l_paren)) {
4542 if (FormatTok->is(tok::less))
4543 parseObjCProtocolList();
4546 if (FormatTok->is(tok::semi)) {
4553 parseObjCUntilAtEnd();
4557void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
4558 bool IsImport = FormatTok->is(Keywords.kw_import);
4559 assert(IsImport || FormatTok->is(tok::kw_export));
4563 if (FormatTok->is(tok::kw_default))
4569 if (FormatTok->is(Keywords.kw_async))
4571 if (FormatTok->is(Keywords.kw_function)) {
4580 if (!IsImport && FormatTok->isNoneOf(tok::l_brace, tok::star) &&
4581 !FormatTok->isStringLiteral() &&
4582 !(FormatTok->is(Keywords.kw_type) &&
4583 Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {
4588 if (FormatTok->is(tok::semi))
4590 if (
Line->Tokens.empty()) {
4595 if (FormatTok->is(tok::l_brace)) {
4596 FormatTok->setBlockKind(BK_Block);
4605void UnwrappedLineParser::parseStatementMacro() {
4607 if (FormatTok->is(tok::l_paren))
4609 if (FormatTok->is(tok::semi))
4614void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
4617 if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
4618 tok::coloncolon, tok::hash) ||
4619 Keywords.isVerilogIdentifier(*FormatTok)) {
4621 }
else if (FormatTok->is(tok::l_square)) {
4629void UnwrappedLineParser::parseVerilogSensitivityList() {
4630 if (FormatTok->isNot(tok::at))
4634 if (FormatTok->is(tok::at))
4636 switch (FormatTok->Tok.getKind()) {
4644 parseVerilogHierarchyIdentifier();
4649unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
4650 unsigned AddLevels = 0;
4652 if (FormatTok->is(Keywords.kw_clocking)) {
4654 if (Keywords.isVerilogIdentifier(*FormatTok))
4656 parseVerilogSensitivityList();
4657 if (FormatTok->is(tok::semi))
4659 }
else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
4660 Keywords.kw_casez, Keywords.kw_randcase,
4661 Keywords.kw_randsequence)) {
4662 if (Style.IndentCaseLabels)
4665 if (FormatTok->is(tok::l_paren)) {
4666 FormatTok->setFinalizedType(TT_ConditionLParen);
4669 if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
4678 if (FormatTok->is(tok::l_square)) {
4679 auto Prev = FormatTok->getPreviousNonComment();
4680 if (Prev && Keywords.isVerilogIdentifier(*Prev))
4681 Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
4683 }
else if (Keywords.isVerilogIdentifier(*FormatTok) ||
4684 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
4685 Keywords.kw_automatic, tok::kw_static)) {
4692 auto NewLine = [
this]() {
4694 Line->IsContinuation =
true;
4698 while (FormatTok->is(Keywords.kw_import)) {
4701 parseVerilogHierarchyIdentifier();
4702 if (FormatTok->is(tok::semi))
4707 if (FormatTok->is(Keywords.kw_verilogHash)) {
4710 if (FormatTok->is(tok::l_paren)) {
4711 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4715 if (FormatTok->is(tok::l_paren)) {
4717 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4722 if (FormatTok->is(Keywords.kw_extends)) {
4725 parseVerilogHierarchyIdentifier();
4726 if (FormatTok->is(tok::l_paren))
4729 if (FormatTok->is(Keywords.kw_implements)) {
4733 parseVerilogHierarchyIdentifier();
4734 }
while (FormatTok->is(tok::comma));
4738 if (FormatTok->is(tok::at)) {
4740 parseVerilogSensitivityList();
4743 if (FormatTok->is(tok::semi))
4751void UnwrappedLineParser::parseVerilogTable() {
4752 assert(FormatTok->is(Keywords.kw_table));
4756 auto InitialLevel =
Line->Level++;
4757 while (!
eof() && !Keywords.isVerilogEnd(*FormatTok)) {
4760 if (
Tok->
is(tok::semi))
4762 else if (
Tok->
isOneOf(tok::star, tok::colon, tok::question, tok::minus))
4763 Tok->setFinalizedType(TT_VerilogTableItem);
4765 Line->Level = InitialLevel;
4770void UnwrappedLineParser::parseVerilogCaseLabel() {
4776 auto OrigLevel =
Line->Level;
4777 auto FirstLine = CurrentLines->size();
4778 if (
Line->Level == 0 || (
Line->InPPDirective &&
Line->Level <= 1))
4780 else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
4782 parseStructuralElement();
4785 if (CurrentLines->size() > FirstLine)
4786 (*CurrentLines)[FirstLine].Level = OrigLevel;
4787 Line->Level = OrigLevel;
4790void UnwrappedLineParser::parseVerilogExtern() {
4792 FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
4795 if (FormatTok->is(tok::string_literal))
4797 skipVerilogQualifiers();
4798 if (Keywords.isVerilogIdentifier(*FormatTok))
4800 if (FormatTok->is(tok::equal))
4802 if (Keywords.isVerilogHierarchy(*FormatTok))
4803 parseVerilogHierarchyHeader();
4806void UnwrappedLineParser::skipVerilogQualifiers() {
4807 while (FormatTok->isOneOf(tok::kw_protected, tok::kw_virtual, tok::kw_static,
4808 Keywords.kw_rand, Keywords.kw_context,
4809 Keywords.kw_pure, Keywords.kw_randc,
4810 Keywords.kw_local)) {
4815bool UnwrappedLineParser::containsExpansion(
const UnwrappedLine &
Line)
const {
4816 for (
const auto &N :
Line.Tokens) {
4817 if (N.Tok->MacroCtx)
4819 for (
const UnwrappedLine &Child : N.Children)
4820 if (containsExpansion(Child))
4826void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
4827 if (
Line->Tokens.empty())
4830 if (!parsingPPDirective()) {
4831 llvm::dbgs() <<
"Adding unwrapped line:\n";
4832 printDebugInfo(*
Line);
4840 bool ClosesWhitesmithsBlock =
4841 Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
4847 if (!parsingPPDirective() && !InExpansion && containsExpansion(*
Line)) {
4849 Reconstruct.emplace(
Line->Level, Unexpanded);
4850 Reconstruct->addLine(*
Line);
4855 CurrentExpandedLines.push_back(std::move(*
Line));
4857 if (Reconstruct->finished()) {
4858 UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();
4859 assert(!Reconstructed.Tokens.empty() &&
4860 "Reconstructed must at least contain the macro identifier.");
4861 assert(!parsingPPDirective());
4863 llvm::dbgs() <<
"Adding unexpanded line:\n";
4864 printDebugInfo(Reconstructed);
4866 if (CurrentExpandedLines.size() > 1)
4867 Reconstructed.Tokens.back().Tok->MacroParent =
true;
4868 ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;
4869 Lines.push_back(std::move(Reconstructed));
4870 CurrentExpandedLines.clear();
4871 Reconstruct.reset();
4876 assert(!Reconstruct || (CurrentLines != &Lines) || !PP.Stack.empty());
4877 CurrentLines->push_back(std::move(*
Line));
4879 Line->Tokens.clear();
4880 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
4881 Line->FirstStartColumn = 0;
4882 Line->IsContinuation =
false;
4883 Line->SeenDecltypeAuto =
false;
4884 Line->IsModuleOrImportDecl =
false;
4886 if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
4888 if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {
4889 CurrentLines->append(
4890 std::make_move_iterator(PreprocessorDirectives.begin()),
4891 std::make_move_iterator(PreprocessorDirectives.end()));
4892 PreprocessorDirectives.clear();
4895 FormatTok->Previous =
nullptr;
4898bool UnwrappedLineParser::eof()
const {
return FormatTok->is(tok::eof); }
4900bool UnwrappedLineParser::isOnNewLine(
const FormatToken &FormatTok) {
4901 return (
Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
4902 FormatTok.NewlinesBefore > 0;
4910 const llvm::Regex &CommentPragmasRegex) {
4914 StringRef IndentContent = FormatTok.
TokenText;
4915 if (FormatTok.
TokenText.starts_with(
"//") ||
4916 FormatTok.
TokenText.starts_with(
"/*")) {
4917 IndentContent = FormatTok.
TokenText.substr(2);
4919 if (CommentPragmasRegex.match(IndentContent))
4994 if (PreviousToken && PreviousToken->
is(tok::l_brace) &&
4996 MinColumnToken = PreviousToken;
4999 PreviousToken = Node.
Tok;
5003 MinColumnToken = Node.
Tok;
5005 if (PreviousToken && PreviousToken->
is(tok::l_brace))
5006 MinColumnToken = PreviousToken;
5012void UnwrappedLineParser::flushComments(
bool NewlineBeforeNext) {
5013 bool JustComments =
Line->Tokens.empty();
5023 Tok->ContinuesLineCommentSection =
5024 continuesLineCommentSection(*
Tok, *
Line, Style, CommentPragmasRegex);
5025 if (isOnNewLine(*
Tok) && JustComments && !
Tok->ContinuesLineCommentSection)
5029 if (NewlineBeforeNext && JustComments)
5031 CommentsBeforeNextToken.clear();
5034void UnwrappedLineParser::nextToken(
int LevelDifference) {
5037 flushComments(isOnNewLine(*FormatTok));
5038 pushToken(FormatTok);
5040 if (!Style.isJavaScript())
5041 readToken(LevelDifference);
5043 readTokenWithJavaScriptASI();
5045 if (Style.isVerilog()) {
5052 if (Keywords.isVerilogEnd(*FormatTok))
5053 FormatTok->Tok.setKind(tok::r_brace);
5057void UnwrappedLineParser::distributeComments(
5077 if (Comments.empty())
5079 bool ShouldPushCommentsInCurrentLine =
true;
5080 bool HasTrailAlignedWithNextToken =
false;
5081 unsigned StartOfTrailAlignedWithNextToken = 0;
5084 for (
unsigned i = Comments.size() - 1; i > 0; --i) {
5086 HasTrailAlignedWithNextToken =
true;
5087 StartOfTrailAlignedWithNextToken = i;
5091 for (
unsigned i = 0, e = Comments.size(); i < e; ++i) {
5093 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
5094 FormatTok->ContinuesLineCommentSection =
false;
5097 *FormatTok, *
Line, Style, CommentPragmasRegex);
5099 if (!FormatTok->ContinuesLineCommentSection &&
5100 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
5101 ShouldPushCommentsInCurrentLine =
false;
5103 if (ShouldPushCommentsInCurrentLine)
5104 pushToken(FormatTok);
5106 CommentsBeforeNextToken.push_back(FormatTok);
5110void UnwrappedLineParser::readToken(
int LevelDifference) {
5112 bool PreviousWasComment =
false;
5113 bool FirstNonCommentOnLine =
false;
5115 FormatTok = Tokens->getNextToken();
5117 while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
5118 TT_ConflictAlternative)) {
5119 if (FormatTok->is(TT_ConflictStart))
5120 conditionalCompilationStart(
false);
5121 else if (FormatTok->is(TT_ConflictAlternative))
5122 conditionalCompilationAlternative();
5123 else if (FormatTok->is(TT_ConflictEnd))
5124 conditionalCompilationEnd();
5125 FormatTok = Tokens->getNextToken();
5126 FormatTok->MustBreakBefore =
true;
5127 FormatTok->MustBreakBeforeFinalized =
true;
5130 auto IsFirstNonCommentOnLine = [](
bool FirstNonCommentOnLine,
5132 bool PreviousWasComment) {
5134 return Tok.HasUnescapedNewline ||
Tok.IsFirst;
5139 if (PreviousWasComment)
5140 return FirstNonCommentOnLine || IsFirstOnLine(
Tok);
5141 return IsFirstOnLine(
Tok);
5144 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
5145 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
5146 PreviousWasComment = FormatTok->is(tok::comment);
5148 while (!
Line->InPPDirective && FormatTok->is(tok::hash) &&
5149 FirstNonCommentOnLine) {
5152 const auto *
Next = Tokens->peekNextToken();
5153 if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*
Next)) ||
5154 (Style.isTableGen() &&
5155 Next->isNoneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef,
5156 tok::pp_ifndef, tok::pp_endif))) {
5159 distributeComments(Comments, FormatTok);
5164 const bool ParsedBefore = !ParsedPPDirectives.insert(FormatTok).second;
5167 bool SwitchToPreprocessorLines = !
Line->Tokens.empty();
5168 ScopedLineState BlockState(*
this, SwitchToPreprocessorLines,
5170 assert((LevelDifference >= 0 ||
5171 static_cast<unsigned>(-LevelDifference) <=
Line->Level) &&
5172 "LevelDifference makes Line->Level negative");
5173 Line->Level += LevelDifference;
5178 PP.BranchLevel > 0) {
5179 Line->Level += PP.BranchLevel;
5181 assert(
Line->Level >=
Line->UnbracedBodyLevel);
5182 Line->Level -=
Line->UnbracedBodyLevel;
5183 flushComments(isOnNewLine(*FormatTok));
5184 const bool IsEndIf = Tokens->peekNextToken()->is(tok::pp_endif);
5186 PreviousWasComment = FormatTok->is(tok::comment);
5187 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
5188 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
5191 if (IsEndIf && PP.IncludeGuard == IG_Defined && PP.BranchLevel == -1 &&
5192 getIncludeGuardState(Style.IndentPPDirectives) == IG_Inited &&
5194 (PreviousWasComment &&
5195 Tokens->peekNextToken(
true)->is(tok::eof)))) {
5196 PP.IncludeGuard = IG_Found;
5200 if (!PP.Stack.empty() && (PP.Stack.back().Kind == PP_Unreachable) &&
5201 !
Line->InPPDirective) {
5205 if (FormatTok->is(tok::identifier) &&
5206 Macros.defined(FormatTok->TokenText) &&
5208 !
Line->InPPDirective) {
5210 unsigned Position = Tokens->getPosition();
5215 const auto SavedPPState = PP;
5219 auto PreCall = std::move(
Line);
5220 Line.reset(
new UnwrappedLine);
5221 bool OldInExpansion = InExpansion;
5224 auto Args = parseMacroCall(SavedPPState);
5225 InExpansion = OldInExpansion;
5226 assert(
Line->Tokens.front().Tok == ID);
5228 auto UnexpandedLine = std::move(
Line);
5230 Line = std::move(PreCall);
5233 llvm::dbgs() <<
"Macro call: " <<
ID->TokenText <<
"(";
5235 llvm::dbgs() <<
"(";
5236 for (
const auto &Arg : Args.value())
5237 for (
const auto &
T : Arg)
5238 llvm::dbgs() <<
T->TokenText <<
" ";
5239 llvm::dbgs() <<
")";
5241 llvm::dbgs() <<
"\n";
5243 if (
Macros.objectLike(
ID->TokenText) && Args &&
5244 !
Macros.hasArity(
ID->TokenText, Args->size())) {
5250 LLVM_DEBUG(llvm::dbgs()
5251 <<
"Macro \"" <<
ID->TokenText
5252 <<
"\" not overloaded for arity " << Args->size()
5253 <<
"or not function-like, using object-like overload.");
5255 UnexpandedLine->Tokens.resize(1);
5256 Tokens->setPosition(Position);
5258 FormatTok = Tokens->getNextToken();
5260 assert(!Args &&
Macros.objectLike(
ID->TokenText));
5262 if ((!Args &&
Macros.objectLike(
ID->TokenText)) ||
5263 (Args &&
Macros.hasArity(
ID->TokenText, Args->size()))) {
5266 Unexpanded[
ID] = std::move(UnexpandedLine);
5268 Macros.expand(ID, std::move(Args));
5269 if (!Expansion.empty())
5270 FormatTok = Tokens->insertTokens(Expansion);
5273 llvm::dbgs() <<
"Expanded: ";
5274 for (
const auto &
T : Expansion)
5275 llvm::dbgs() <<
T->TokenText <<
" ";
5276 llvm::dbgs() <<
"\n";
5280 llvm::dbgs() <<
"Did not expand macro \"" <<
ID->TokenText
5281 <<
"\", because it was used ";
5283 llvm::dbgs() <<
"with " << Args->size();
5285 llvm::dbgs() <<
"without";
5286 llvm::dbgs() <<
" arguments, which doesn't match any definition.\n";
5288 Tokens->setPosition(Position);
5294 if (FormatTok->isNot(tok::comment)) {
5295 distributeComments(Comments, FormatTok);
5300 Comments.push_back(FormatTok);
5303 distributeComments(Comments,
nullptr);
5308template <
typename Iterator>
5309void pushTokens(Iterator Begin, Iterator End,
5311 for (
auto I = Begin; I != End; ++I) {
5312 Into.push_back(I->Tok);
5313 for (
const auto &Child : I->Children)
5314 pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);
5319std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
5320UnwrappedLineParser::parseMacroCall(
const PPState &SavedPPState) {
5321 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;
5322 assert(
Line->Tokens.empty());
5325 auto ConsumeLastTokenOfCall = [
this] {
5326 flushComments(isOnNewLine(*FormatTok));
5327 pushToken(FormatTok);
5328 FormatTok = Tokens->getNextToken();
5330 if (Tokens->peekNextToken(
true)->isNot(tok::l_paren)) {
5331 ConsumeLastTokenOfCall();
5335 assert(FormatTok->is(tok::l_paren));
5336 unsigned Position = Tokens->getPosition();
5340 auto ArgStart = std::prev(
Line->Tokens.end());
5344 switch (FormatTok->Tok.getKind()) {
5349 case tok::r_paren: {
5355 Args->push_back({});
5356 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5357 ConsumeLastTokenOfCall();
5365 Args->push_back({});
5366 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5368 ArgStart = std::prev(
Line->Tokens.end());
5376 Line->Tokens.resize(1);
5377 Tokens->setPosition(Position);
5384 Line->Tokens.push_back(UnwrappedLineNode(
Tok));
5385 if (PP.AtEndOfPPLine) {
5386 auto &
Tok = *
Line->Tokens.back().Tok;
5387 Tok.MustBreakBefore =
true;
5388 Tok.MustBreakBeforeFinalized =
true;
5389 Tok.FirstAfterPPLine =
true;
5390 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