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))
294 if (Style.isTextProto() && !CommentsBeforeNextToken.empty())
300void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {
310 parseCSharpGenericTypeConstraint();
319void UnwrappedLineParser::parseCSharpAttribute() {
320 int UnpairedSquareBrackets = 1;
322 switch (FormatTok->Tok.getKind()) {
325 --UnpairedSquareBrackets;
326 if (UnpairedSquareBrackets == 0) {
332 ++UnpairedSquareBrackets;
342bool UnwrappedLineParser::precededByCommentOrPPDirective()
const {
343 if (!Lines.empty() && Lines.back().InPPDirective)
357bool UnwrappedLineParser::parseLevel(
const FormatToken *OpeningBrace,
360 bool *SeenExplicitAccessModifier) {
361 const bool InRequiresExpression =
362 OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
363 const bool IsPrecededByCommentOrPPDirective =
364 !Style.RemoveBracesLLVM || precededByCommentOrPPDirective();
366 bool HasDoWhile =
false;
367 bool HasLabel =
false;
368 unsigned StatementCount = 0;
369 bool SwitchLabelEncountered =
false;
372 if (FormatTok->isAttribute()) {
374 if (FormatTok->is(tok::l_paren))
379 if (FormatTok->is(TT_MacroBlockBegin))
381 else if (FormatTok->is(TT_MacroBlockEnd))
384 auto ParseDefault = [
this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
385 &HasLabel, &StatementCount,
386 SeenExplicitAccessModifier] {
387 if (SeenExplicitAccessModifier && !*SeenExplicitAccessModifier) {
388 const bool IsQtAccessLabel =
389 FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
390 Keywords.kw_slots, Keywords.kw_qslots) &&
391 Tokens->peekNextToken(
true)->is(tok::colon);
392 if (FormatTok->isAccessSpecifierKeyword() || IsQtAccessLabel) {
394 *SeenExplicitAccessModifier =
true;
397 parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,
398 HasDoWhile ?
nullptr : &HasDoWhile,
399 HasLabel ?
nullptr : &HasLabel);
401 assert(StatementCount > 0 &&
"StatementCount overflow!");
410 if (InRequiresExpression) {
411 FormatTok->setFinalizedType(TT_CompoundRequirementLBrace);
412 }
else if (FormatTok->Previous &&
413 FormatTok->Previous->ClosesRequiresClause) {
419 if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {
420 if (tryToParseBracedList())
422 FormatTok->setFinalizedType(TT_BlockLBrace);
426 assert(StatementCount > 0 &&
"StatementCount overflow!");
431 if (!Style.RemoveBracesLLVM || Line->InPPDirective ||
432 OpeningBrace->isNoneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
435 if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||
436 HasDoWhile || IsPrecededByCommentOrPPDirective ||
437 precededByCommentOrPPDirective()) {
441 if (
Next->is(tok::comment) &&
Next->NewlinesBefore == 0)
444 *IfLeftBrace = IfLBrace;
450 case tok::kw_default: {
451 unsigned StoredPosition = Tokens->getPosition();
452 auto *
Next = Tokens->getNextNonComment();
453 FormatTok = Tokens->setPosition(StoredPosition);
454 if (
Next->isNoneOf(tok::colon, tok::arrow)) {
457 parseStructuralElement();
465 (Style.isJavaScript() && Line->MustBeDeclaration)) {
473 if (!SwitchLabelEncountered &&
474 (Style.IndentCaseLabels ||
475 (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||
476 (Line->InPPDirective && Line->Level == 1))) {
479 SwitchLabelEncountered =
true;
480 parseStructuralElement();
483 if (Style.isCSharp()) {
485 parseCSharpAttribute();
488 if (handleCppAttributes())
500void UnwrappedLineParser::calculateBraceTypes(
bool ExpectClassBody) {
505 unsigned StoredPosition = Tokens->getPosition();
515 SmallVector<StackEntry, 8> LBraceStack;
516 assert(
Tok->is(tok::l_brace));
519 auto *NextTok = Tokens->getNextNonComment();
521 if (!Line->InMacroBody && !Style.isTableGen()) {
523 while (NextTok->is(tok::hash)) {
524 NextTok = Tokens->getNextToken();
525 if (NextTok->isOneOf(tok::pp_not_keyword, tok::pp_define))
528 NextTok = Tokens->getNextToken();
529 }
while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));
531 while (NextTok->is(tok::comment))
532 NextTok = Tokens->getNextToken();
536 switch (
Tok->Tok.getKind()) {
538 if (Style.isJavaScript() && PrevTok) {
539 if (PrevTok->isOneOf(tok::colon, tok::less)) {
550 }
else if (PrevTok->is(tok::r_paren)) {
554 }
else if (Style.isJava() && PrevTok && PrevTok->is(tok::arrow)) {
559 LBraceStack.push_back({
Tok, PrevTok});
562 if (LBraceStack.empty())
564 if (
auto *LBrace = LBraceStack.back().Tok; LBrace->is(
BK_Unknown)) {
565 bool ProbablyBracedList =
false;
567 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
568 }
else if (LBrace->isNot(TT_EnumLBrace)) {
571 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
572 NextTok->OriginalColumn == 0;
582 ProbablyBracedList = LBrace->is(TT_BracedListLBrace);
584 ProbablyBracedList = ProbablyBracedList ||
585 (Style.isJavaScript() &&
586 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
589 ProbablyBracedList ||
590 (IsCpp && (PrevTok->Tok.isLiteral() ||
591 NextTok->isOneOf(tok::l_paren, tok::arrow)));
598 ProbablyBracedList ||
599 NextTok->isOneOf(tok::comma, tok::period, tok::colon,
600 tok::r_paren, tok::r_square, tok::ellipsis);
605 ProbablyBracedList ||
606 (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&
607 LBraceStack.back().PrevTok->isOneOf(tok::identifier,
611 ProbablyBracedList ||
612 (NextTok->is(tok::identifier) &&
613 PrevTok->isNoneOf(tok::semi, tok::r_brace, tok::l_brace));
615 ProbablyBracedList = ProbablyBracedList ||
616 (NextTok->is(tok::semi) &&
617 (!ExpectClassBody || LBraceStack.size() != 1));
620 ProbablyBracedList ||
621 (NextTok->isBinaryOperator() && !NextIsObjCMethod);
623 if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
626 NextTok = Tokens->getNextToken();
627 ProbablyBracedList = NextTok->isNot(tok::l_square);
631 if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
632 !FormatTok->Previous && NextTok->is(tok::eof) &&
636 PrevTok->isNoneOf(tok::semi,
BK_Block, tok::colon)) {
637 ProbablyBracedList =
true;
641 Tok->setBlockKind(BlockKind);
642 LBrace->setBlockKind(BlockKind);
644 LBraceStack.pop_back();
646 case tok::identifier:
647 if (
Tok->isNot(TT_StatementMacro))
658 if (!LBraceStack.empty() && LBraceStack.back().Tok->is(
BK_Unknown))
659 LBraceStack.back().Tok->setBlockKind(
BK_Block);
667 }
while (
Tok->isNot(tok::eof) && !LBraceStack.empty());
670 for (
const auto &Entry : LBraceStack)
674 FormatTok = Tokens->setPosition(StoredPosition);
678void UnwrappedLineParser::setPreviousRBraceType(
TokenType Type) {
679 if (
auto Prev = FormatTok->getPreviousNonComment();
680 Prev && Prev->is(tok::r_brace)) {
681 Prev->setFinalizedType(
Type);
688 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
691size_t UnwrappedLineParser::computePPHash()
const {
693 for (
const auto &i : PP.Stack) {
704bool UnwrappedLineParser::mightFitOnOneLine(
706 const auto ColumnLimit = Style.ColumnLimit;
707 if (ColumnLimit == 0)
710 auto &Tokens = ParsedLine.Tokens;
711 assert(!Tokens.empty());
713 const auto *LastToken = Tokens.back().Tok;
716 SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());
719 for (
const auto &Token : Tokens) {
721 auto &SavedToken = SavedTokens[Index++];
723 SavedToken.Tok->copyFrom(*Token.Tok);
724 SavedToken.Children = std::move(Token.Children);
727 AnnotatedLine
Line(ParsedLine);
728 assert(Line.Last == LastToken);
730 TokenAnnotator Annotator(Style, Keywords);
731 Annotator.annotate(Line);
732 Annotator.calculateFormattingInformation(Line);
734 auto Length = LastToken->TotalLength;
736 assert(OpeningBrace != Tokens.front().Tok);
737 if (
auto Prev = OpeningBrace->Previous;
738 Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
739 Length -= ColumnLimit;
741 Length -= OpeningBrace->TokenText.size() + 1;
744 if (
const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
745 assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
746 Length -= FirstToken->TokenText.size() + 1;
750 for (
auto &Token : Tokens) {
751 const auto &SavedToken = SavedTokens[Index++];
752 Token.Tok->copyFrom(*SavedToken.Tok);
753 Token.Children = std::move(SavedToken.Children);
754 delete SavedToken.Tok;
758 assert(!Line.InMacroBody);
759 assert(!Line.InPPDirective);
760 return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
764 bool MustBeDeclaration,
unsigned AddLevels,
bool MunchSemi,
bool KeepBraces,
765 IfStmtKind *IfKind,
bool UnindentWhitesmithsBraces,
766 bool IndentAfterExplicitAccessModifier) {
767 auto HandleVerilogBlockLabel = [
this]() {
769 if (Style.isVerilog() && FormatTok->is(tok::colon)) {
771 if (Keywords.isVerilogIdentifier(*FormatTok))
778 const bool VerilogHierarchy =
779 Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);
780 assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
781 (Style.isVerilog() &&
782 (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
783 "'{' or macro block token expected");
785 const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
786 auto Index = CurrentLines->size();
787 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
790 const bool IsWhitesmiths =
795 if (!VerilogHierarchy && AddLevels > 0 && IsWhitesmiths)
798 size_t PPStartHash = computePPHash();
800 const unsigned InitialLevel = Line->Level;
801 if (VerilogHierarchy) {
802 AddLevels += parseVerilogHierarchyHeader();
804 nextToken(AddLevels);
805 HandleVerilogBlockLabel();
809 if (Line->Level > 300)
812 if (MacroBlock && FormatTok->is(tok::l_paren))
815 size_t NbPreprocessorDirectives =
816 !parsingPPDirective() ? PreprocessorDirectives.size() : 0;
818 size_t OpeningLineIndex =
819 CurrentLines->empty() || !CurrentExpandedLines.empty()
821 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
826 if (UnindentWhitesmithsBraces)
829 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
835 Line->Level += AddLevels - (IsWhitesmiths ? 1 : 0);
838 bool SeenExplicitAccessModifier =
false;
839 const bool SimpleBlock =
840 parseLevel(
Tok, IfKind, &IfLBrace,
841 IndentAfterExplicitAccessModifier ? &SeenExplicitAccessModifier
847 if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)
848 : FormatTok->isNot(tok::r_brace)) {
849 Line->Level = InitialLevel;
850 FormatTok->setBlockKind(BK_Block);
854 if (FormatTok->is(tok::r_brace)) {
855 FormatTok->setBlockKind(BK_Block);
856 if (Tok->is(TT_NamespaceLBrace))
857 FormatTok->setFinalizedType(TT_NamespaceRBrace);
860 const bool IsFunctionRBrace =
861 FormatTok->is(tok::r_brace) &&
Tok->is(TT_FunctionLBrace);
863 auto RemoveBraces = [=]()
mutable {
866 assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
867 assert(FormatTok->is(tok::r_brace));
868 const bool WrappedOpeningBrace = !Tok->Previous;
869 if (WrappedOpeningBrace && FollowedByComment)
871 const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
872 if (KeepBraces && !HasRequiredIfBraces)
874 if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
875 const FormatToken *Previous = Tokens->getPreviousToken();
877 if (Previous->is(tok::r_brace) && !Previous->Optional)
882 assert(!CurrentLines->empty());
883 auto &LastLine = CurrentLines->back();
884 if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
886 if (
Tok->is(TT_ElseLBrace))
888 if (WrappedOpeningBrace) {
893 return mightFitOnOneLine((*CurrentLines)[Index],
Tok);
895 if (RemoveBraces()) {
896 Tok->MatchingParen = FormatTok;
897 FormatTok->MatchingParen =
Tok;
900 size_t PPEndHash = computePPHash();
902 if (SeenExplicitAccessModifier)
905 nextToken(-AddLevels);
910 if (Style.RemoveSemicolon && IsFunctionRBrace) {
911 while (FormatTok->is(tok::semi)) {
912 FormatTok->Optional =
true;
917 HandleVerilogBlockLabel();
919 if (MacroBlock && FormatTok->is(tok::l_paren))
922 Line->Level = InitialLevel;
924 if (FormatTok->is(tok::kw_noexcept)) {
929 if (FormatTok->is(tok::arrow)) {
933 parseStructuralElement();
936 if (MunchSemi && FormatTok->is(tok::semi))
939 if (PPStartHash == PPEndHash && CurrentExpandedLines.empty() &&
940 !containsExpansion(*
Line)) {
941 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
944 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
945 CurrentLines->size() - 1;
955 if (
Line.Tokens.size() < 4)
957 auto I =
Line.Tokens.begin();
958 if (I->Tok->TokenText !=
"goog")
961 if (I->Tok->isNot(tok::period))
964 if (I->Tok->TokenText !=
"scope")
967 return I->Tok->is(tok::l_paren);
976 if (
Line.Tokens.size() < 3)
978 auto I =
Line.Tokens.begin();
979 if (I->Tok->isNot(tok::l_paren))
985 return I->Tok->is(tok::l_paren);
991 bool IsJavaRecord =
false) {
993 return Style.BraceWrapping.AfterClass;
996 if (InitialToken.
is(TT_NamespaceMacro))
997 Kind = tok::kw_namespace;
999 const bool WrapRecordAllowed =
1002 Style.BraceWrapping.SplitEmptyRecord;
1005 case tok::kw_namespace:
1006 return Style.BraceWrapping.AfterNamespace;
1008 return Style.BraceWrapping.AfterClass && WrapRecordAllowed;
1010 return Style.BraceWrapping.AfterUnion && WrapRecordAllowed;
1011 case tok::kw_struct:
1012 return Style.BraceWrapping.AfterStruct && WrapRecordAllowed;
1014 return Style.BraceWrapping.AfterEnum;
1020void UnwrappedLineParser::parseChildBlock() {
1021 assert(FormatTok->is(tok::l_brace));
1022 FormatTok->setBlockKind(BK_Block);
1026 bool SkipIndent = (Style.isJavaScript() &&
1027 (isGoogScope(*
Line) || isIIFE(*
Line, Keywords)));
1028 ScopedLineState LineState(*
this);
1029 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
1031 Line->Level += SkipIndent ? 0 : 1;
1032 parseLevel(OpeningBrace);
1033 flushComments(isOnNewLine(*FormatTok));
1034 Line->Level -= SkipIndent ? 0 : 1;
1039void UnwrappedLineParser::parsePPDirective() {
1040 assert(FormatTok->is(tok::hash) &&
"'#' expected");
1041 ScopedMacroState MacroState(*
Line, Tokens, FormatTok);
1045 if (!FormatTok->Tok.getIdentifierInfo()) {
1050 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
1051 case tok::pp_define:
1058 case tok::pp_ifndef:
1062 case tok::pp_elifdef:
1063 case tok::pp_elifndef:
1070 case tok::pp_pragma:
1074 case tok::pp_warning:
1076 if (!
eof() && Style.isCpp())
1077 FormatTok->setFinalizedType(TT_AfterPPDirective);
1085void UnwrappedLineParser::conditionalCompilationCondition(
bool Unreachable) {
1086 size_t Line = CurrentLines->size();
1087 if (CurrentLines == &PreprocessorDirectives)
1088 Line += Lines.size();
1091 (!PP.Stack.empty() && PP.Stack.back().Kind == PP_Unreachable)) {
1092 PP.Stack.push_back({PP_Unreachable,
Line});
1094 PP.Stack.push_back({PP_Conditional,
Line});
1098void UnwrappedLineParser::conditionalCompilationStart(
bool Unreachable) {
1100 assert(PP.BranchLevel >= 0 &&
1101 PP.BranchLevel <= (
int)PP.LevelBranchIndex.size());
1102 if (PP.BranchLevel == (
int)PP.LevelBranchIndex.size()) {
1103 PP.LevelBranchIndex.push_back(0);
1104 PP.LevelBranchCount.push_back(0);
1106 PP.ChainBranchIndex.push(Unreachable ? -1 : 0);
1107 bool Skip = PP.LevelBranchIndex[PP.BranchLevel] > 0;
1108 conditionalCompilationCondition(Unreachable ||
Skip);
1111void UnwrappedLineParser::conditionalCompilationAlternative() {
1112 if (!PP.Stack.empty())
1113 PP.Stack.pop_back();
1114 assert(PP.BranchLevel < (
int)PP.LevelBranchIndex.size());
1115 if (!PP.ChainBranchIndex.empty())
1116 ++PP.ChainBranchIndex.top();
1117 conditionalCompilationCondition(
1118 PP.BranchLevel >= 0 && !PP.ChainBranchIndex.empty() &&
1119 PP.LevelBranchIndex[PP.BranchLevel] != PP.ChainBranchIndex.top());
1122void UnwrappedLineParser::conditionalCompilationEnd() {
1123 assert(PP.BranchLevel < (
int)PP.LevelBranchIndex.size());
1124 if (PP.BranchLevel >= 0 && !PP.ChainBranchIndex.empty()) {
1125 if (PP.ChainBranchIndex.top() + 1 > PP.LevelBranchCount[PP.BranchLevel])
1126 PP.LevelBranchCount[PP.BranchLevel] = PP.ChainBranchIndex.top() + 1;
1129 if (PP.BranchLevel > -1)
1131 if (!PP.ChainBranchIndex.empty())
1132 PP.ChainBranchIndex.pop();
1133 if (!PP.Stack.empty())
1134 PP.Stack.pop_back();
1137void UnwrappedLineParser::parsePPIf(
bool IfDef) {
1138 bool IfNDef = FormatTok->is(tok::pp_ifndef);
1140 bool Unreachable =
false;
1141 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText ==
"0"))
1143 if (IfDef && !IfNDef && FormatTok->TokenText ==
"SWIG")
1145 conditionalCompilationStart(Unreachable);
1149 bool MaybeIncludeGuard = IfNDef;
1150 if (PP.IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1151 for (
auto &
Line : Lines) {
1152 if (
Line.Tokens.front().Tok->isNot(tok::comment)) {
1153 MaybeIncludeGuard =
false;
1154 PP.IncludeGuard = IG_Rejected;
1162 if (PP.IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1163 PP.IncludeGuard = IG_IfNdefed;
1164 PP.IncludeGuardToken = IfCondition;
1168void UnwrappedLineParser::parsePPElse() {
1170 if (PP.IncludeGuard == IG_Defined && PP.BranchLevel == 0)
1171 PP.IncludeGuard = IG_Rejected;
1173 assert(PP.BranchLevel >= -1);
1174 if (PP.BranchLevel == -1)
1175 conditionalCompilationStart(
true);
1176 conditionalCompilationAlternative();
1182void UnwrappedLineParser::parsePPEndIf() {
1183 conditionalCompilationEnd();
1187void UnwrappedLineParser::parsePPDefine() {
1190 if (!FormatTok->Tok.getIdentifierInfo()) {
1191 PP.IncludeGuard = IG_Rejected;
1192 PP.IncludeGuardToken =
nullptr;
1197 bool MaybeIncludeGuard =
false;
1198 if (PP.IncludeGuard == IG_IfNdefed &&
1199 PP.IncludeGuardToken->TokenText == FormatTok->TokenText) {
1200 PP.IncludeGuard = IG_Defined;
1201 PP.IncludeGuardToken =
nullptr;
1202 for (
auto &
Line : Lines) {
1203 if (
Line.Tokens.front().Tok->isNoneOf(tok::comment, tok::hash)) {
1204 PP.IncludeGuard = IG_Rejected;
1208 MaybeIncludeGuard = PP.IncludeGuard == IG_Defined;
1216 FormatTok->Tok.setKind(tok::identifier);
1217 FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);
1221 if (MaybeIncludeGuard && !
eof())
1222 PP.IncludeGuard = IG_Rejected;
1224 if (FormatTok->is(tok::l_paren) && !FormatTok->hasWhitespaceBefore())
1227 Line->Level += PP.BranchLevel + 1;
1231 Line->PPLevel = PP.BranchLevel + (PP.IncludeGuard == IG_Defined ? 0 : 1);
1232 assert((
int)
Line->PPLevel >= 0);
1237 Line->InMacroBody =
true;
1239 if (!Style.SkipMacroDefinitionBody) {
1249 for (
auto *Comment : CommentsBeforeNextToken)
1250 Comment->Finalized =
true;
1253 FormatTok->Finalized =
true;
1254 FormatTok = Tokens->getNextToken();
1260void UnwrappedLineParser::parsePPPragma() {
1261 Line->InPragmaDirective =
true;
1265void UnwrappedLineParser::parsePPUnknown() {
1269 Line->Level += PP.BranchLevel + 1;
1279 return Tok.isNoneOf(tok::semi, tok::l_brace,
1282 tok::period, tok::periodstar, tok::arrow, tok::arrowstar,
1283 tok::less, tok::greater, tok::slash, tok::percent,
1284 tok::lessless, tok::greatergreater, tok::equal,
1285 tok::plusequal, tok::minusequal, tok::starequal,
1286 tok::slashequal, tok::percentequal, tok::ampequal,
1287 tok::pipeequal, tok::caretequal, tok::greatergreaterequal,
1300 return FormatTok->
is(tok::identifier) &&
1315 FormatTok->
isOneOf(tok::kw_true, tok::kw_false) ||
1326 tok::kw_if, tok::kw_else,
1328 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
1330 tok::kw_switch, tok::kw_case,
1332 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.
kw_finally,
1334 tok::kw_const, tok::kw_class, Keywords.
kw_var, Keywords.
kw_let,
1342 return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
1343 tok::kw_unsigned, tok::kw_float, tok::kw_double,
1360 if (FuncName->
isNot(tok::identifier))
1368 Tok->isNoneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
1372 if (
Next->isNot(tok::star) && !
Next->Tok.getIdentifierInfo())
1376 if (!
Tok ||
Tok->isNot(tok::r_paren))
1380 if (!
Tok ||
Tok->isNot(tok::identifier))
1383 return Tok->Previous &&
Tok->Previous->isOneOf(tok::l_paren, tok::comma);
1386bool UnwrappedLineParser::parseModuleDecl() {
1388 assert(FormatTok->is(Keywords.kw_module));
1396 if (FormatTok->isNot(tok::identifier))
1399 for (nextToken(); FormatTok->isNoneOf(tok::semi, tok::eof); nextToken())
1400 if (FormatTok->is(tok::colon))
1401 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1404 Line->IsModuleOrImportDecl =
true;
1409bool UnwrappedLineParser::parseImportDecl() {
1411 assert(FormatTok->is(Keywords.kw_import) &&
"'import' expected");
1419 if (FormatTok->is(tok::colon)) {
1420 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1423 if (FormatTok->isNoneOf(tok::identifier, tok::less, tok::string_literal))
1426 for (; FormatTok->isNoneOf(tok::semi, tok::eof); nextToken()) {
1428 if (FormatTok->is(tok::less)) {
1429 for (nextToken(); FormatTok->isNoneOf(tok::greater, tok::semi, tok::eof);
1433 FormatTok->setFinalizedType(TT_ImplicitStringLiteral);
1439 Line->IsModuleOrImportDecl =
true;
1451void UnwrappedLineParser::readTokenWithJavaScriptASI() {
1457 CommentsBeforeNextToken.empty()
1458 ?
Next->NewlinesBefore == 0
1459 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
1464 bool PreviousStartsTemplateExpr =
1466 if (PreviousMustBeValue ||
Previous->is(tok::r_paren)) {
1469 bool HasAt = llvm::any_of(
Line->Tokens, [](UnwrappedLineNode &LineNode) {
1470 return LineNode.Tok->is(tok::at);
1475 if (
Next->is(tok::exclaim) && PreviousMustBeValue)
1476 return addUnwrappedLine();
1478 bool NextEndsTemplateExpr =
1479 Next->is(TT_TemplateString) &&
Next->TokenText.starts_with(
"}");
1480 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
1481 (PreviousMustBeValue ||
1482 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
1483 tok::minusminus))) {
1484 return addUnwrappedLine();
1486 if ((PreviousMustBeValue ||
Previous->is(tok::r_paren)) &&
1488 return addUnwrappedLine();
1492void UnwrappedLineParser::parseStructuralElement(
1493 const FormatToken *OpeningBrace, IfStmtKind *IfKind,
1494 FormatToken **IfLeftBrace,
bool *HasDoWhile,
bool *HasLabel) {
1495 if (Style.isTableGen() && FormatTok->is(tok::pp_include)) {
1497 if (FormatTok->is(tok::string_literal))
1504 while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
1506 }
else if (Style.isVerilog()) {
1508 while (FormatTok->is(tok::l_paren) &&
1509 Tokens->peekNextToken()->is(tok::star)) {
1512 skipVerilogQualifiers();
1514 if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
1515 Keywords.kw_unique0)) {
1519 if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {
1520 parseForOrWhileLoop(
false);
1523 if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {
1524 parseForOrWhileLoop();
1527 if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
1528 Keywords.kw_assume, Keywords.kw_cover)) {
1529 parseIfThenElse(IfKind,
false,
true);
1535 if (FormatTok->isAccessSpecifierKeyword()) {
1536 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
1539 parseAccessSpecifier();
1542 switch (FormatTok->Tok.getKind()) {
1547 bool DoNotFormat =
false;
1552 FormatTok->isOneOf(tok::kw_volatile, tok::kw_inline, tok::kw_goto)) {
1557 if (FormatTok->is(tok::l_brace)) {
1558 FormatTok->setFinalizedType(TT_InlineASMBrace);
1559 OpenType = tok::l_brace;
1560 CloseType = tok::r_brace;
1562 }
else if (FormatTok->is(tok::l_paren)) {
1563 OpenType = tok::l_paren;
1564 CloseType = tok::r_paren;
1565 FormatTok->setFinalizedType(TT_InlineASMParen);
1573 while (FormatTok && !
eof()) {
1574 if (FormatTok->is(OpenType)) {
1576 }
else if (FormatTok->is(CloseType)) {
1578 if (NestLevel < 1) {
1579 FormatTok->setFinalizedType(OpenTok->getType());
1585 FormatTok->Finalized =
true;
1591 case tok::kw_namespace:
1595 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1606 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1610 parseForOrWhileLoop();
1613 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1621 case tok::kw_switch:
1622 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1628 case tok::kw_default: {
1630 if (Style.isVerilog())
1632 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1638 if (FormatTok->is(tok::colon)) {
1639 FormatTok->setFinalizedType(TT_CaseLabelColon);
1643 if (FormatTok->is(tok::arrow)) {
1644 FormatTok->setFinalizedType(TT_CaseLabelArrow);
1645 Default->setFinalizedType(TT_SwitchExpressionLabel);
1658 if (Style.isVerilog()) {
1663 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1672 if (FormatTok->is(tok::kw_case))
1677 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1683 case tok::kw_extern:
1684 if (Style.isVerilog()) {
1687 parseVerilogExtern();
1691 if (FormatTok->is(tok::string_literal)) {
1693 if (FormatTok->is(tok::l_brace)) {
1694 if (Style.BraceWrapping.AfterExternBlock)
1698 unsigned AddLevels =
1700 (Style.BraceWrapping.AfterExternBlock &&
1701 Style.IndentExternBlock ==
1705 parseBlock(
true, AddLevels);
1711 case tok::kw_export:
1714 if (FormatTok->is(tok::kw_namespace)) {
1718 if (FormatTok->is(tok::l_brace)) {
1719 parseCppExportBlock();
1722 if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
1724 if (FormatTok->is(Keywords.kw_import) && parseImportDecl())
1728 if (Style.isJavaScript()) {
1729 parseJavaScriptEs6ImportExport();
1732 if (Style.isVerilog()) {
1733 parseVerilogExtern();
1737 case tok::kw_inline:
1739 if (FormatTok->is(tok::kw_namespace)) {
1744 case tok::identifier:
1745 if (FormatTok->is(TT_ForEachMacro)) {
1746 parseForOrWhileLoop();
1749 if (FormatTok->is(TT_MacroBlockBegin)) {
1750 parseBlock(
false, 1u,
1754 if (FormatTok->is(Keywords.kw_import)) {
1755 if (IsCpp && parseImportDecl())
1757 if (Style.isJavaScript()) {
1758 parseJavaScriptEs6ImportExport();
1763 if (FormatTok->is(tok::kw_public))
1765 if (FormatTok->isNot(tok::string_literal))
1768 if (FormatTok->is(tok::semi))
1773 if (Style.isVerilog()) {
1774 parseVerilogExtern();
1779 if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
1781 if (FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
1782 Keywords.kw_slots, Keywords.kw_qslots)) {
1784 if (FormatTok->is(tok::colon)) {
1790 if (FormatTok->is(TT_StatementMacro)) {
1791 parseStatementMacro();
1794 if (FormatTok->is(TT_NamespaceMacro)) {
1803 if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&
1804 Tokens->peekNextToken()->is(tok::colon) && !
Line->MustBeDeclaration) {
1806 if (!
Line->InMacroBody || CurrentLines->size() > 1)
1807 Line->Tokens.begin()->Tok->MustBreakBefore =
true;
1808 FormatTok->setFinalizedType(TT_GotoLabelColon);
1814 if (Style.isJava() && FormatTok->is(Keywords.kw_record)) {
1815 parseRecord(
false,
true);
1825 bool SeenEqual =
false;
1826 for (
const bool InRequiresExpression =
1827 OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
1828 TT_CompoundRequirementLBrace);
1831 switch (FormatTok->Tok.getKind()) {
1834 if (FormatTok->is(tok::l_brace)) {
1839 if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) {
1843 switch (
bool IsAutoRelease =
false; FormatTok->Tok.getObjCKeywordID()) {
1844 case tok::objc_public:
1845 case tok::objc_protected:
1846 case tok::objc_package:
1847 case tok::objc_private:
1848 return parseAccessSpecifier();
1849 case tok::objc_interface:
1850 case tok::objc_implementation:
1851 return parseObjCInterfaceOrImplementation();
1852 case tok::objc_protocol:
1853 if (parseObjCProtocol())
1858 case tok::objc_optional:
1859 case tok::objc_required:
1863 case tok::objc_autoreleasepool:
1864 IsAutoRelease =
true;
1866 case tok::objc_synchronized:
1868 if (!IsAutoRelease && FormatTok->is(tok::l_paren)) {
1872 if (FormatTok->is(tok::l_brace)) {
1873 if (Style.BraceWrapping.AfterControlStatement ==
1890 case tok::kw_requires: {
1892 bool ParsedClause = parseRequires(SeenEqual);
1913 if (!IsCpp && !Style.isVerilog()) {
1918 case tok::kw_typedef:
1920 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1921 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
1922 Keywords.kw_CF_CLOSED_ENUM,
1923 Keywords.kw_NS_CLOSED_ENUM)) {
1928 if (Style.isVerilog()) {
1933 if (Style.isTableGen()) {
1940 case tok::kw_struct:
1942 if (parseStructLike())
1945 case tok::kw_decltype:
1947 if (FormatTok->is(tok::l_paren)) {
1949 if (FormatTok->Previous &&
1950 FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
1952 Line->SeenDecltypeAuto =
true;
1959 if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class))
1961 if (Style.isJavaScript() && FormatTok &&
1962 FormatTok->Tok.getIdentifierInfo()) {
1975 case tok::string_literal:
1976 if (Style.isVerilog() && FormatTok->is(TT_VerilogProtected)) {
1977 FormatTok->Finalized =
true;
1984 case tok::l_paren: {
1991 Tokens->peekNextToken(
true),
1998 case tok::kw_operator:
2000 if (FormatTok->isBinaryOperator())
2004 const auto *Prev = FormatTok->getPreviousNonComment();
2006 if (Prev && Prev->is(tok::identifier))
2009 if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {
2012 if (FormatTok->is(tok::less)) {
2014 parseBracedList(
true);
2017 while (FormatTok->is(tok::star))
2021 if (FormatTok->is(tok::l_paren))
2024 if (FormatTok->is(tok::l_brace))
2029 if (InRequiresExpression)
2030 FormatTok->setFinalizedType(TT_BracedListLBrace);
2031 if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
2032 IsDecltypeAutoFunction =
Line->SeenDecltypeAuto;
2037 if (Style.isJava() &&
2038 Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
2041 if (Style.BraceWrapping.AfterControlStatement ==
2045 }
else if (Style.BraceWrapping.AfterFunction) {
2049 FormatTok->setFinalizedType(TT_FunctionLBrace);
2051 IsDecltypeAutoFunction =
false;
2059 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2065 if (Style.BraceWrapping.AfterFunction)
2069 case tok::identifier: {
2070 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&
2071 Line->MustBeDeclaration) {
2073 parseCSharpGenericTypeConstraint();
2076 if (FormatTok->is(TT_MacroBlockEnd)) {
2085 size_t TokenCount =
Line->Tokens.size();
2086 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&
2089 Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {
2090 tryToParseJSFunction();
2093 if ((Style.isJavaScript() || Style.isJava()) &&
2094 FormatTok->is(Keywords.kw_interface)) {
2095 if (Style.isJavaScript()) {
2100 unsigned StoredPosition = Tokens->getPosition();
2102 FormatTok = Tokens->setPosition(StoredPosition);
2113 if (Style.isVerilog()) {
2114 if (FormatTok->is(Keywords.kw_table)) {
2115 parseVerilogTable();
2118 if (Keywords.isVerilogBegin(*FormatTok) ||
2119 Keywords.isVerilogHierarchy(*FormatTok)) {
2126 if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
2127 if (parseStructLike())
2132 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
2133 parseStatementMacro();
2138 StringRef
Text = FormatTok->TokenText;
2145 if (Style.isJavaScript())
2148 auto OneTokenSoFar = [&]() {
2149 auto I =
Line->Tokens.begin(), E =
Line->Tokens.end();
2150 while (I != E && I->Tok->is(tok::comment))
2152 if (Style.isVerilog())
2153 while (I != E && I->Tok->is(tok::hash))
2155 return I != E && (++I == E);
2157 if (OneTokenSoFar()) {
2160 bool FunctionLike = FormatTok->is(tok::l_paren);
2164 bool FollowedByNewline =
2165 CommentsBeforeNextToken.empty()
2166 ? FormatTok->NewlinesBefore > 0
2167 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
2169 if (FollowedByNewline &&
2170 (
Text.size() >= 5 ||
2171 (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
2173 if (PreviousToken->isNot(TT_UntouchableMacroFunc))
2174 PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
2182 if ((Style.isJavaScript() || Style.isCSharp()) &&
2183 FormatTok->is(TT_FatArrow)) {
2184 tryToParseChildBlock();
2190 if (FormatTok->is(tok::l_brace)) {
2194 if (!Style.isJavaScript())
2195 FormatTok->setBlockKind(BK_BracedInit);
2198 if (Style.isTableGen() &&
2199 Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {
2200 FormatTok->setFinalizedType(TT_FunctionLBrace);
2201 parseBlock(
false, 1u,
2209 FormatTok->is(tok::less)) {
2211 parseBracedList(
true);
2218 if ((Style.isCSharp() &&
2219 (Tokens->peekNextToken()->isAccessSpecifierKeyword() ||
2221 FormatTok->endsSequence(tok::kw_new, tok::kw_operator)) {
2227 case tok::kw_switch:
2240 if (Style.isVerilog()) {
2245 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2252 case tok::kw_default:
2254 if (Style.isVerilog()) {
2255 if (FormatTok->is(tok::colon)) {
2259 if (FormatTok->is(Keywords.kw_clocking)) {
2265 parseVerilogCaseLabel();
2271 if (Style.isVerilog()) {
2272 parseVerilogCaseLabel();
2278 if (FormatTok->is(tok::l_brace))
2279 FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
2288bool UnwrappedLineParser::tryToParsePropertyAccessor() {
2289 assert(FormatTok->is(tok::l_brace));
2290 if (!Style.isCSharp())
2293 if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))
2301 unsigned int StoredPosition = Tokens->getPosition();
2307 bool HasSpecialAccessor =
false;
2308 bool IsTrivialPropertyAccessor =
true;
2311 if (
const bool IsAccessorKeyword =
2312 Tok->
isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set);
2313 IsAccessorKeyword ||
Tok->isAccessSpecifierKeyword() ||
2314 Tok->
isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {
2315 if (IsAccessorKeyword)
2316 HasSpecialAccessor =
true;
2317 else if (
Tok->
is(tok::l_square))
2319 Tok = Tokens->getNextToken();
2323 IsTrivialPropertyAccessor =
false;
2328 Tokens->setPosition(StoredPosition);
2334 Tokens->setPosition(StoredPosition);
2335 if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)
2339 switch (FormatTok->Tok.getKind()) {
2342 if (FormatTok->is(tok::equal)) {
2343 while (!
eof() && FormatTok->isNot(tok::semi))
2356 if (FormatTok->is(TT_FatArrow)) {
2360 }
while (!
eof() && FormatTok->isNot(tok::semi));
2369 if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,
2371 !IsTrivialPropertyAccessor) {
2383bool UnwrappedLineParser::tryToParseLambda() {
2384 assert(FormatTok->is(tok::l_square));
2390 if (!tryToParseLambdaIntroducer())
2394 bool InTemplateParameterList =
false;
2396 while (FormatTok->isNot(tok::l_brace)) {
2397 if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {
2401 switch (FormatTok->Tok.getKind()) {
2405 parseParens(TT_PointerOrReference);
2411 assert(FormatTok->Previous);
2412 if (FormatTok->Previous->is(tok::r_square))
2413 InTemplateParameterList =
true;
2418 case tok::kw_struct:
2420 case tok::kw_template:
2421 case tok::kw_typename:
2425 case tok::kw_constexpr:
2426 case tok::kw_consteval:
2429 case tok::identifier:
2430 case tok::numeric_constant:
2431 case tok::coloncolon:
2432 case tok::kw_mutable:
2433 case tok::kw_noexcept:
2434 case tok::kw_static:
2459 case tok::equalequal:
2460 case tok::exclaimequal:
2461 case tok::greaterequal:
2462 case tok::lessequal:
2468 if (Arrow || InTemplateParameterList) {
2477 case tok::kw_requires:
2478 parseRequiresClause();
2481 if (!InTemplateParameterList)
2490 FormatTok->setFinalizedType(TT_LambdaLBrace);
2491 LSquare.setFinalizedType(TT_LambdaLSquare);
2494 Arrow->setFinalizedType(TT_LambdaArrow);
2496 NestedLambdas.push_back(
Line->SeenDecltypeAuto);
2498 assert(!NestedLambdas.empty());
2499 NestedLambdas.pop_back();
2504bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
2509 const auto *PrevPrev =
Previous->getPreviousNonComment();
2510 if (
Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts))
2518 if (!PrevPrev || PrevPrev->isNoneOf(tok::greater, tok::r_paren))
2522 Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
2523 tok::kw_co_return)) {
2527 if (LeftSquare->isCppStructuredBinding(IsCpp))
2529 if (FormatTok->is(tok::l_square) ||
tok::isLiteral(FormatTok->Tok.getKind()))
2531 if (FormatTok->is(tok::r_square)) {
2533 if (
Next->is(tok::greater))
2540void UnwrappedLineParser::tryToParseJSFunction() {
2541 assert(FormatTok->is(Keywords.kw_function));
2542 if (FormatTok->is(Keywords.kw_async))
2548 if (FormatTok->is(tok::star)) {
2549 FormatTok->setFinalizedType(TT_OverloadedOperator);
2554 if (FormatTok->is(tok::identifier))
2557 if (FormatTok->isNot(tok::l_paren))
2563 if (FormatTok->is(tok::colon)) {
2569 if (FormatTok->is(tok::l_brace))
2570 tryToParseBracedList();
2572 while (FormatTok->isNoneOf(tok::l_brace, tok::semi) && !
eof())
2576 if (FormatTok->is(tok::semi))
2582bool UnwrappedLineParser::tryToParseBracedList() {
2583 if (FormatTok->is(BK_Unknown))
2584 calculateBraceTypes();
2585 assert(FormatTok->isNot(BK_Unknown));
2586 if (FormatTok->is(BK_Block))
2593bool UnwrappedLineParser::tryToParseChildBlock() {
2594 assert(Style.isJavaScript() || Style.isCSharp());
2595 assert(FormatTok->is(TT_FatArrow));
2600 if (FormatTok->isNot(tok::l_brace))
2606bool UnwrappedLineParser::parseBracedList(
bool IsAngleBracket,
bool IsEnum) {
2607 assert(!IsAngleBracket || !IsEnum);
2608 bool HasError =
false;
2613 if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
2614 tryToParseChildBlock()) {
2617 if (Style.isJavaScript()) {
2618 if (FormatTok->is(Keywords.kw_function)) {
2619 tryToParseJSFunction();
2622 if (FormatTok->is(tok::l_brace)) {
2624 if (tryToParseBracedList())
2629 if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
2631 FormatTok->setBlockKind(BK_Block);
2632 if (!Style.AllowShortEnumsOnASingleLine)
2638 switch (FormatTok->Tok.getKind()) {
2640 if (Style.isCSharp())
2649 if (Style.isJavaScript()) {
2650 if (FormatTok->is(tok::l_brace))
2658 FormatTok->setBlockKind(BK_BracedInit);
2659 if (!IsAngleBracket) {
2660 auto *Prev = FormatTok->Previous;
2661 if (Prev && Prev->is(tok::greater))
2662 Prev->setFinalizedType(TT_TemplateCloser);
2670 parseBracedList(
true);
2678 if (Style.isJavaScript() || Style.isProto() || Style.isJson()) {
2689 if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
2692 case tok::kw_requires:
2693 parseRequiresExpression();
2710bool UnwrappedLineParser::parseParens(TokenType StarAndAmpTokenType,
2712 assert(FormatTok->is(tok::l_paren) &&
"'(' expected.");
2713 auto *LParen = FormatTok;
2714 auto *Prev = FormatTok->Previous;
2715 bool SeenComma =
false;
2716 bool SeenEqual =
false;
2717 bool MightBeFoldExpr =
false;
2718 unsigned ExcessLess = 0;
2720 const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
2721 if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
2724 switch (FormatTok->Tok.getKind()) {
2726 if (parseParens(ExcessLess == 0 ? StarAndAmpTokenType : TT_Unknown,
2730 if (Style.isJava() && FormatTok->is(tok::l_brace))
2733 case tok::r_paren: {
2734 auto *RParen = FormatTok;
2737 auto OptionalParens = [&] {
2739 MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
2740 Line->InMacroBody || RParen->getPreviousNonComment() == LParen) {
2743 const bool DoubleParens =
2744 Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);
2746 const auto *PrevPrev = Prev->getPreviousNonComment();
2747 const bool Excluded =
2749 (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2751 (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2752 PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2756 const bool CommaSeparated =
2757 Prev->isOneOf(tok::l_paren, tok::comma) &&
2758 FormatTok->isOneOf(tok::comma, tok::r_paren);
2759 if (CommaSeparated &&
2761 !Prev->endsSequence(tok::comma, tok::ellipsis) &&
2763 !(FormatTok->is(tok::comma) &&
2764 Tokens->peekNextToken()->is(tok::ellipsis))) {
2767 const bool ReturnParens =
2769 ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2770 (!NestedLambdas.empty() && !NestedLambdas.back())) &&
2771 Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
2772 FormatTok->is(tok::semi);
2778 if (OptionalParens()) {
2779 LParen->Optional =
true;
2780 RParen->Optional =
true;
2781 }
else if (Prev->is(TT_TypenameMacro)) {
2782 LParen->setFinalizedType(TT_TypeDeclarationParen);
2783 RParen->setFinalizedType(TT_TypeDeclarationParen);
2784 }
else if (Prev->is(tok::greater) && RParen->Previous == LParen) {
2785 Prev->setFinalizedType(TT_TemplateCloser);
2786 }
else if (FormatTok->is(tok::l_brace) && Prev->is(tok::amp) &&
2788 FormatTok->setBlockKind(BK_BracedInit);
2800 if (!tryToParseBracedList())
2805 if (FormatTok->is(tok::l_brace)) {
2815 MightBeFoldExpr =
true;
2820 if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
2821 tryToParseChildBlock();
2826 if (Style.isJavaScript())
2831 case tok::identifier:
2832 if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))
2833 tryToParseJSFunction();
2837 case tok::kw_switch:
2843 case tok::kw_requires:
2844 parseRequiresExpression();
2860 if (StarAndAmpTokenType != TT_Unknown && ExcessLess == 0)
2861 FormatTok->setFinalizedType(StarAndAmpTokenType);
2871void UnwrappedLineParser::parseSquare(
bool SkipLambda) {
2873 assert(FormatTok->is(tok::l_square) &&
"'[' expected.");
2874 if (tryToParseLambda())
2878 switch (FormatTok->Tok.getKind()) {
2891 case tok::l_brace: {
2892 if (!tryToParseBracedList())
2899 if (FormatTok->is(tok::l_brace)) {
2911void UnwrappedLineParser::keepAncestorBraces() {
2912 if (!Style.RemoveBracesLLVM)
2915 const int MaxNestingLevels = 2;
2916 const int Size = NestedTooDeep.size();
2917 if (Size >= MaxNestingLevels)
2918 NestedTooDeep[
Size - MaxNestingLevels] =
true;
2919 NestedTooDeep.push_back(
false);
2923 for (
const auto &
Token : llvm::reverse(
Line.Tokens))
2931 return llvm::any_of(
2932 llvm::drop_begin(
Line.Tokens),
2936void UnwrappedLineParser::parseUnbracedBody(
bool CheckEOF) {
2939 if (Style.InsertBraces && !
Line->InPPDirective && !
Line->Tokens.empty() &&
2940 !containsPPDirective(*
Line) && FormatTok->isNot(tok::semi)) {
2942 ? getLastNonComment(*
Line)
2945 if (
Tok->BraceCount < 0) {
2946 assert(
Tok->BraceCount == -1);
2949 Tok->BraceCount = -1;
2954 const auto BodyStart = CurrentLines->size();
2956 ++
Line->UnbracedBodyLevel;
2957 parseStructuralElement();
2958 --
Line->UnbracedBodyLevel;
2961 assert(!
Line->InPPDirective);
2964 auto BodyEnd = CurrentLines->size();
2965 while (BodyEnd > 0) {
2966 const auto &L = (*CurrentLines)[--BodyEnd];
2968 Tok = L.Tokens.back().Tok;
2974 bool EnclosesPPDirective =
false;
2975 for (
size_t I = BodyStart; I <= BodyEnd && !EnclosesPPDirective; ++I) {
2976 const auto &BodyLine = (*CurrentLines)[I];
2977 EnclosesPPDirective =
2978 BodyLine.InPPDirective ||
2979 llvm::any_of(BodyLine.Tokens, [](
const UnwrappedLineNode &Node) {
2980 return Node.Tok->FirstAfterPPLine;
2983 if (EnclosesPPDirective)
2984 LBraceTok->BraceCount = 0;
2989 if (CheckEOF &&
eof())
2999 assert(LeftBrace->
is(tok::l_brace));
3007 assert(RightBrace->
is(tok::r_brace));
3015void UnwrappedLineParser::handleAttributes() {
3017 if (FormatTok->isAttribute())
3019 else if (FormatTok->is(tok::l_square))
3020 handleCppAttributes();
3023bool UnwrappedLineParser::handleCppAttributes() {
3025 assert(FormatTok->is(tok::l_square));
3026 if (!tryToParseSimpleAttribute())
3033bool UnwrappedLineParser::isBlockBegin(
const FormatToken &
Tok)
const {
3036 return Style.isVerilog() ? Keywords.isVerilogBegin(
Tok)
3037 :
Tok.
is(tok::l_brace);
3040FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
3042 bool IsVerilogAssert) {
3043 assert((FormatTok->is(tok::kw_if) ||
3044 (Style.isVerilog() &&
3045 FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
3046 Keywords.kw_assume, Keywords.kw_cover))) &&
3050 if (IsVerilogAssert) {
3052 if (FormatTok->is(Keywords.kw_verilogHash)) {
3054 if (FormatTok->is(tok::numeric_constant))
3056 }
else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,
3057 Keywords.kw_sequence)) {
3063 if (Style.isTableGen()) {
3064 while (!
eof() && FormatTok->isNot(Keywords.kw_then)) {
3071 if (FormatTok->is(tok::exclaim))
3074 bool KeepIfBraces =
true;
3075 if (FormatTok->is(tok::kw_consteval)) {
3078 KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;
3079 if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
3081 if (FormatTok->is(tok::l_paren)) {
3082 FormatTok->setFinalizedType(TT_ConditionLParen);
3088 if (IsVerilogAssert && FormatTok->is(tok::semi)) {
3094 bool NeedsUnwrappedLine =
false;
3095 keepAncestorBraces();
3098 IfStmtKind IfBlockKind = IfStmtKind::NotIf;
3100 if (isBlockBegin(*FormatTok)) {
3101 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3102 IfLeftBrace = FormatTok;
3103 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3104 parseBlock(
false, 1u,
3105 true, KeepIfBraces, &IfBlockKind);
3106 setPreviousRBraceType(TT_ControlStatementRBrace);
3107 if (Style.BraceWrapping.BeforeElse)
3110 NeedsUnwrappedLine =
true;
3111 }
else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {
3114 parseUnbracedBody();
3117 if (Style.RemoveBracesLLVM) {
3118 assert(!NestedTooDeep.empty());
3119 KeepIfBraces = KeepIfBraces ||
3120 (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
3121 NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
3122 IfBlockKind == IfStmtKind::IfElseIf;
3125 bool KeepElseBraces = KeepIfBraces;
3127 IfStmtKind
Kind = IfStmtKind::IfOnly;
3129 if (FormatTok->is(tok::kw_else)) {
3130 if (Style.RemoveBracesLLVM) {
3131 NestedTooDeep.back() =
false;
3132 Kind = IfStmtKind::IfElse;
3136 if (isBlockBegin(*FormatTok)) {
3137 const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
3138 FormatTok->setFinalizedType(TT_ElseLBrace);
3139 ElseLeftBrace = FormatTok;
3140 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3141 IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
3143 parseBlock(
false, 1u,
3144 true, KeepElseBraces, &ElseBlockKind);
3145 setPreviousRBraceType(TT_ElseRBrace);
3146 if (FormatTok->is(tok::kw_else)) {
3147 KeepElseBraces = KeepElseBraces ||
3148 ElseBlockKind == IfStmtKind::IfOnly ||
3149 ElseBlockKind == IfStmtKind::IfElseIf;
3150 }
else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
3151 KeepElseBraces =
true;
3152 assert(ElseLeftBrace->MatchingParen);
3156 }
else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {
3159 const bool IsPrecededByComment =
Previous->is(tok::comment);
3160 if (IsPrecededByComment) {
3164 bool TooDeep =
true;
3165 if (Style.RemoveBracesLLVM) {
3166 Kind = IfStmtKind::IfElseIf;
3167 TooDeep = NestedTooDeep.pop_back_val();
3169 ElseLeftBrace = parseIfThenElse(
nullptr, KeepIfBraces);
3170 if (Style.RemoveBracesLLVM)
3171 NestedTooDeep.push_back(TooDeep);
3172 if (IsPrecededByComment)
3175 parseUnbracedBody(
true);
3178 KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
3179 if (NeedsUnwrappedLine)
3183 if (!Style.RemoveBracesLLVM)
3186 assert(!NestedTooDeep.empty());
3187 KeepElseBraces = KeepElseBraces ||
3188 (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
3189 NestedTooDeep.back();
3191 NestedTooDeep.pop_back();
3193 if (!KeepIfBraces && !KeepElseBraces) {
3196 }
else if (IfLeftBrace) {
3197 FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
3199 assert(IfRightBrace->MatchingParen == IfLeftBrace);
3200 assert(!IfLeftBrace->Optional);
3201 assert(!IfRightBrace->Optional);
3202 IfLeftBrace->MatchingParen =
nullptr;
3203 IfRightBrace->MatchingParen =
nullptr;
3213void UnwrappedLineParser::parseTryCatch() {
3214 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) &&
"'try' expected");
3216 bool NeedsUnwrappedLine =
false;
3217 bool HasCtorInitializer =
false;
3218 if (FormatTok->is(tok::colon)) {
3219 auto *Colon = FormatTok;
3222 if (FormatTok->is(tok::identifier)) {
3223 HasCtorInitializer =
true;
3224 Colon->setFinalizedType(TT_CtorInitializerColon);
3229 while (FormatTok->is(tok::comma))
3232 while (FormatTok->is(tok::identifier)) {
3234 if (FormatTok->is(tok::l_paren)) {
3236 }
else if (FormatTok->is(tok::l_brace)) {
3243 while (FormatTok->is(tok::comma))
3248 if (Style.isJava() && FormatTok->is(tok::l_paren))
3251 keepAncestorBraces();
3253 if (FormatTok->is(tok::l_brace)) {
3254 if (HasCtorInitializer)
3255 FormatTok->setFinalizedType(TT_FunctionLBrace);
3256 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3258 if (Style.BraceWrapping.BeforeCatch)
3261 NeedsUnwrappedLine =
true;
3262 }
else if (FormatTok->isNot(tok::kw_catch)) {
3268 parseStructuralElement();
3271 for (
bool SeenCatch =
false;;) {
3272 if (FormatTok->is(tok::at))
3274 if (FormatTok->isNoneOf(tok::kw_catch, Keywords.kw___except,
3275 tok::kw___finally, tok::objc_catch,
3276 tok::objc_finally) &&
3277 !((Style.isJava() || Style.isJavaScript()) &&
3278 FormatTok->is(Keywords.kw_finally))) {
3281 if (FormatTok->is(tok::kw_catch))
3284 while (FormatTok->isNot(tok::l_brace)) {
3285 if (FormatTok->is(tok::l_paren)) {
3289 if (FormatTok->isOneOf(tok::semi, tok::r_brace) ||
eof()) {
3290 if (Style.RemoveBracesLLVM)
3291 NestedTooDeep.pop_back();
3297 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3300 NeedsUnwrappedLine =
false;
3301 Line->MustBeDeclaration =
false;
3302 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3304 if (Style.BraceWrapping.BeforeCatch)
3307 NeedsUnwrappedLine =
true;
3310 if (Style.RemoveBracesLLVM)
3311 NestedTooDeep.pop_back();
3313 if (NeedsUnwrappedLine)
3317void UnwrappedLineParser::parseNamespaceOrExportBlock(
unsigned AddLevels) {
3318 bool ManageWhitesmithsBraces =
3323 if (ManageWhitesmithsBraces)
3328 parseBlock(
true, AddLevels,
true,
3329 true,
nullptr, ManageWhitesmithsBraces);
3331 addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
3333 if (ManageWhitesmithsBraces)
3337void UnwrappedLineParser::parseNamespace() {
3338 assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
3339 "'namespace' expected");
3343 if (InitialToken.is(TT_NamespaceMacro)) {
3346 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
3347 tok::l_square, tok::period, tok::l_paren) ||
3348 (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
3349 if (FormatTok->is(tok::l_square))
3351 else if (FormatTok->is(tok::l_paren))
3357 if (FormatTok->is(tok::l_brace)) {
3358 FormatTok->setFinalizedType(TT_NamespaceLBrace);
3361 Tokens->peekNextToken()->is(tok::r_brace))) {
3365 unsigned AddLevels =
3368 DeclarationScopeStack.size() > 1)
3371 parseNamespaceOrExportBlock(AddLevels);
3376void UnwrappedLineParser::parseCppExportBlock() {
3377 if (FormatTok->is(tok::l_brace)) {
3378 FormatTok->setFinalizedType(TT_ExportLBrace);
3379 if (Style.BraceWrapping.AfterExportBlock)
3382 parseNamespaceOrExportBlock(Style.IndentExportBlock ? 1 : 0);
3385void UnwrappedLineParser::parseNew() {
3386 assert(FormatTok->is(tok::kw_new) &&
"'new' expected");
3389 if (Style.isCSharp()) {
3392 if (FormatTok->is(tok::l_paren))
3396 if (FormatTok->is(tok::l_brace))
3399 if (FormatTok->isOneOf(tok::semi, tok::comma))
3404 }
else if (Style.isJava()) {
3408 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
3412 if (FormatTok->is(tok::l_paren)) {
3417 if (FormatTok->is(tok::l_brace))
3423 }
else if (Style.isCpp()) {
3427 if (FormatTok->is(tok::l_brace))
3429 if (FormatTok->is(tok::l_paren))
3431 if (FormatTok->is(tok::l_paren)) {
3437 if (FormatTok->isOneOf(tok::kw_alignas, tok::kw_decltype)) {
3439 if (FormatTok->is(tok::l_paren))
3441 }
else if (FormatTok->is(tok::l_square)) {
3444 }
else if (FormatTok->is(tok::less)) {
3446 parseBracedList(
true);
3447 }
else if (FormatTok->Tok.getIdentifierInfo() ||
3448 FormatTok->isOneOf(tok::coloncolon, tok::star)) {
3455 if (FormatTok->is(tok::l_brace))
3457 else if (FormatTok->is(tok::l_paren))
3462void UnwrappedLineParser::parseLoopBody(
bool KeepBraces,
bool WrapRightBrace) {
3463 keepAncestorBraces();
3465 if (isBlockBegin(*FormatTok)) {
3466 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3468 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3469 parseBlock(
false, 1u,
3471 setPreviousRBraceType(TT_ControlStatementRBrace);
3473 assert(!NestedTooDeep.empty());
3474 if (!NestedTooDeep.back())
3480 parseUnbracedBody();
3484 NestedTooDeep.pop_back();
3487void UnwrappedLineParser::parseForOrWhileLoop(
bool HasParens) {
3488 assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||
3489 (Style.isVerilog() &&
3490 FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,
3491 Keywords.kw_always_ff, Keywords.kw_always_latch,
3492 Keywords.kw_final, Keywords.kw_initial,
3493 Keywords.kw_foreach, Keywords.kw_forever,
3494 Keywords.kw_repeat))) &&
3495 "'for', 'while' or foreach macro expected");
3496 const bool KeepBraces = !Style.RemoveBracesLLVM ||
3497 FormatTok->isNoneOf(tok::kw_for, tok::kw_while);
3501 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
3503 if (IsCpp && FormatTok->is(tok::kw_co_await))
3505 if (HasParens && FormatTok->is(tok::l_paren)) {
3509 if (Style.isVerilog())
3510 FormatTok->setFinalizedType(TT_ConditionLParen);
3514 if (Style.isVerilog()) {
3516 parseVerilogSensitivityList();
3517 }
else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&
3518 Tokens->getPreviousToken()->is(tok::r_paren)) {
3525 parseLoopBody(KeepBraces,
true);
3528void UnwrappedLineParser::parseDoWhile() {
3529 assert(FormatTok->is(tok::kw_do) &&
"'do' expected");
3532 parseLoopBody(
true, Style.BraceWrapping.BeforeWhile);
3535 if (FormatTok->isNot(tok::kw_while)) {
3540 FormatTok->setFinalizedType(TT_DoWhile);
3548 parseStructuralElement();
3551void UnwrappedLineParser::parseLabel(
bool IsGotoLabel) {
3554 const auto IndentGotoLabel = Style.IndentGotoLabels;
3555 const auto OldLineLevel =
Line->Level;
3562 if (OldLineLevel > 1 || (!
Line->InPPDirective && OldLineLevel > 0))
3566 if (!IsGotoLabel && !Style.IndentCaseBlocks &&
3567 CommentsBeforeNextToken.empty() && FormatTok->is(tok::l_brace)) {
3568 CompoundStatementIndenter Indenter(
this,
Level,
3569 Style.BraceWrapping.AfterCaseLabel,
3570 Style.BraceWrapping.IndentBraces);
3572 if (FormatTok->is(tok::kw_break)) {
3573 if (Style.BraceWrapping.AfterControlStatement ==
3575 Style.CompactCaseLabels) {
3577 if (!Style.IndentCaseBlocks &&
3582 parseStructuralElement();
3586 if (FormatTok->is(tok::semi))
3591 Level = OldLineLevel;
3593 if (FormatTok->isNot(tok::l_brace)) {
3594 parseStructuralElement();
3599void UnwrappedLineParser::parseCaseLabel() {
3600 assert(FormatTok->is(tok::kw_case) &&
"'case' expected");
3601 auto *Case = FormatTok;
3606 if (FormatTok->is(tok::colon)) {
3607 FormatTok->setFinalizedType(TT_CaseLabelColon);
3610 if (Style.isJava() && FormatTok->is(tok::arrow)) {
3611 FormatTok->setFinalizedType(TT_CaseLabelArrow);
3612 Case->setFinalizedType(TT_SwitchExpressionLabel);
3619void UnwrappedLineParser::parseSwitch(
bool IsExpr) {
3620 assert(FormatTok->is(tok::kw_switch) &&
"'switch' expected");
3622 if (FormatTok->is(tok::l_paren))
3625 keepAncestorBraces();
3627 if (FormatTok->is(tok::l_brace)) {
3628 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3629 FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
3630 : TT_ControlStatementLBrace);
3635 setPreviousRBraceType(TT_ControlStatementRBrace);
3641 parseStructuralElement();
3645 if (Style.RemoveBracesLLVM)
3646 NestedTooDeep.pop_back();
3649void UnwrappedLineParser::parseAccessSpecifier() {
3652 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
3655 if (FormatTok->is(tok::colon))
3663bool UnwrappedLineParser::parseRequires(
bool SeenEqual) {
3664 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3668 switch (Tokens->peekNextToken(
true)->Tok.getKind()) {
3671 parseRequiresExpression();
3678 parseRequiresClause();
3689 auto *PreviousNonComment = FormatTok->getPreviousNonComment();
3691 if (!PreviousNonComment ||
3692 PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
3695 parseRequiresClause();
3699 switch (PreviousNonComment->Tok.getKind()) {
3702 case tok::kw_noexcept:
3707 parseRequiresClause();
3716 auto PrevPrev = PreviousNonComment->getPreviousNonComment();
3717 if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {
3718 parseRequiresClause();
3724 if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
3726 parseRequiresClause();
3730 parseRequiresExpression();
3740 unsigned StoredPosition = Tokens->getPosition();
3743 auto PeekNext = [&Lookahead, &NextToken,
this] {
3745 NextToken = Tokens->getNextToken();
3748 bool FoundType =
false;
3749 bool LastWasColonColon =
false;
3752 for (; Lookahead < 50; PeekNext()) {
3753 switch (NextToken->Tok.getKind()) {
3754 case tok::kw_volatile:
3757 if (OpenAngles == 0) {
3758 FormatTok = Tokens->setPosition(StoredPosition);
3759 parseRequiresExpression();
3767 case tok::coloncolon:
3768 LastWasColonColon =
true;
3770 case tok::kw_decltype:
3771 case tok::identifier:
3772 if (FoundType && !LastWasColonColon && OpenAngles == 0) {
3773 FormatTok = Tokens->setPosition(StoredPosition);
3774 parseRequiresExpression();
3778 LastWasColonColon =
false;
3787 if (NextToken->isTypeName(LangOpts)) {
3788 FormatTok = Tokens->setPosition(StoredPosition);
3789 parseRequiresExpression();
3796 FormatTok = Tokens->setPosition(StoredPosition);
3797 parseRequiresClause();
3806void UnwrappedLineParser::parseRequiresClause() {
3807 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3812 bool InRequiresExpression =
3813 !FormatTok->Previous ||
3814 FormatTok->Previous->is(TT_RequiresExpressionLBrace);
3816 FormatTok->setFinalizedType(InRequiresExpression
3817 ? TT_RequiresClauseInARequiresExpression
3818 : TT_RequiresClause);
3823 parseConstraintExpression();
3825 if (!InRequiresExpression && FormatTok->Previous)
3826 FormatTok->Previous->ClosesRequiresClause =
true;
3834void UnwrappedLineParser::parseRequiresExpression() {
3835 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3837 FormatTok->setFinalizedType(TT_RequiresExpression);
3840 if (FormatTok->is(tok::l_paren)) {
3841 FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
3845 if (FormatTok->is(tok::l_brace)) {
3846 FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
3855void UnwrappedLineParser::parseConstraintExpression() {
3862 bool LambdaNextTimeAllowed =
true;
3872 bool TopLevelParensAllowed =
true;
3875 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed,
false);
3877 switch (FormatTok->Tok.getKind()) {
3878 case tok::kw_requires:
3879 parseRequiresExpression();
3883 if (!TopLevelParensAllowed)
3885 parseParens(TT_BinaryOperator);
3886 TopLevelParensAllowed =
false;
3890 if (!LambdaThisTimeAllowed || !tryToParseLambda())
3897 case tok::kw_struct:
3907 FormatTok->setFinalizedType(TT_BinaryOperator);
3909 LambdaNextTimeAllowed =
true;
3910 TopLevelParensAllowed =
true;
3915 LambdaNextTimeAllowed = LambdaThisTimeAllowed;
3919 case tok::kw_sizeof:
3921 case tok::greaterequal:
3922 case tok::greatergreater:
3924 case tok::lessequal:
3926 case tok::equalequal:
3928 case tok::exclaimequal:
3933 LambdaNextTimeAllowed =
true;
3934 TopLevelParensAllowed =
true;
3939 case tok::numeric_constant:
3940 case tok::coloncolon:
3943 TopLevelParensAllowed =
false;
3948 case tok::kw_static_cast:
3949 case tok::kw_const_cast:
3950 case tok::kw_reinterpret_cast:
3951 case tok::kw_dynamic_cast:
3953 if (FormatTok->isNot(tok::less))
3957 parseBracedList(
true);
3961 if (!FormatTok->Tok.getIdentifierInfo()) {
3971 assert(FormatTok->Previous);
3972 switch (FormatTok->Previous->Tok.getKind()) {
3973 case tok::coloncolon:
3977 case tok::kw_requires:
3979 case tok::kw_template:
3987 if (FormatTok->is(tok::less)) {
3989 parseBracedList(
true);
3991 TopLevelParensAllowed =
false;
3997bool UnwrappedLineParser::parseEnum() {
4001 if (FormatTok->is(tok::kw_enum))
4007 if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
4016 if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
4018 while (FormatTok->is(tok::l_square))
4019 if (!handleCppAttributes())
4023 while (FormatTok->Tok.getIdentifierInfo() ||
4024 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
4025 tok::greater, tok::comma, tok::question,
4027 if (FormatTok->is(tok::colon))
4028 FormatTok->setFinalizedType(TT_EnumUnderlyingTypeColon);
4029 if (Style.isVerilog()) {
4030 FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
4033 while (FormatTok->is(tok::l_square))
4039 if (FormatTok->is(tok::l_paren))
4041 if (FormatTok->is(tok::identifier)) {
4045 if (IsCpp && FormatTok->is(tok::identifier))
4051 if (FormatTok->isNot(tok::l_brace))
4053 FormatTok->setFinalizedType(TT_EnumLBrace);
4054 FormatTok->setBlockKind(BK_Block);
4056 if (Style.isJava()) {
4058 parseJavaEnumBody();
4066 const bool ManageWhitesmithsBraces =
4069 if (!Style.AllowShortEnumsOnASingleLine &&
4071 Tokens->peekNextToken()->is(tok::r_brace))) {
4076 if (ManageWhitesmithsBraces)
4081 if (!Style.AllowShortEnumsOnASingleLine) {
4083 if (!ManageWhitesmithsBraces)
4086 const auto OpeningLineIndex =
4087 CurrentLines->empty() || !CurrentExpandedLines.empty()
4088 ? UnwrappedLine::kInvalidIndex
4089 : CurrentLines->size() - 1;
4090 bool HasError = !parseBracedList(
false,
true);
4091 if (!Style.AllowShortEnumsOnASingleLine && !ManageWhitesmithsBraces)
4094 if (FormatTok->is(tok::semi))
4098 setPreviousRBraceType(TT_EnumRBrace);
4099 if (ManageWhitesmithsBraces && CurrentExpandedLines.empty() &&
4100 !containsExpansion(*
Line)) {
4101 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
4110bool UnwrappedLineParser::parseStructLike() {
4115 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) {
4116 if (FormatTok->is(tok::semi))
4127class ScopedTokenPosition {
4128 unsigned StoredPosition;
4129 FormatTokenSource *Tokens;
4132 ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
4133 assert(Tokens &&
"Tokens expected to not be null");
4134 StoredPosition = Tokens->getPosition();
4137 ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
4143bool UnwrappedLineParser::tryToParseSimpleAttribute() {
4144 ScopedTokenPosition AutoPosition(Tokens);
4152 if (
Tok->
is(tok::r_square))
4154 Tok = Tokens->getNextToken();
4156 if (
Tok->
is(tok::eof))
4158 Tok = Tokens->getNextToken();
4161 Tok = Tokens->getNextToken();
4162 if (
Tok->
is(tok::semi))
4167void UnwrappedLineParser::parseJavaEnumBody() {
4168 assert(FormatTok->is(tok::l_brace));
4174 unsigned StoredPosition = Tokens->getPosition();
4175 bool IsSimple =
true;
4178 if (
Tok->
is(tok::r_brace))
4186 Tok = Tokens->getNextToken();
4188 FormatTok = Tokens->setPosition(StoredPosition);
4205 if (FormatTok->is(tok::l_brace)) {
4207 parseBlock(
true, 1u,
4209 }
else if (FormatTok->is(tok::l_paren)) {
4211 }
else if (FormatTok->is(tok::comma)) {
4214 }
else if (FormatTok->is(tok::semi)) {
4218 }
else if (FormatTok->is(tok::r_brace)) {
4227 parseLevel(OpeningBrace);
4233void UnwrappedLineParser::parseRecord(
bool ParseAsExpr,
bool IsJavaRecord) {
4234 assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record));
4239 IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok :
nullptr;
4240 bool IsDerived =
false;
4242 return Tok->
is(tok::identifier) &&
Tok->TokenText !=
Tok->TokenText.upper();
4246 bool JSPastExtendsOrImplements =
false;
4250 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
4251 tok::kw_alignas, tok::l_square) ||
4252 FormatTok->isAttribute() ||
4253 ((Style.isJava() || Style.isJavaScript()) &&
4254 FormatTok->isOneOf(tok::period, tok::comma)) ||
4255 (Style.isVerilog() &&
4256 FormatTok->isOneOf(tok::kw_signed, tok::kw_unsigned))) {
4257 if (Style.isJavaScript() &&
4258 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
4259 JSPastExtendsOrImplements =
true;
4264 if (FormatTok->is(tok::l_brace)) {
4265 tryToParseBracedList();
4269 if (FormatTok->is(tok::l_square) && handleCppAttributes())
4273 switch (FormatTok->Tok.getKind()) {
4276 if (IsJavaRecord || !IsNonMacroIdentifier(
Previous) ||
4278 Previous->Previous == &InitialToken) {
4282 case tok::coloncolon:
4286 if (JSPastExtendsOrImplements || ClassName ||
4297 auto IsListInitialization = [&] {
4298 if (!ClassName || IsDerived || JSPastExtendsOrImplements)
4300 assert(FormatTok->is(tok::l_brace));
4301 const auto *Prev = FormatTok->getPreviousNonComment();
4303 return Prev != ClassName && Prev->is(tok::identifier) &&
4304 Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
4307 if (FormatTok->isOneOf(tok::colon, tok::less)) {
4308 int AngleNestingLevel = 0;
4310 if (FormatTok->is(tok::less))
4311 ++AngleNestingLevel;
4312 else if (FormatTok->is(tok::greater))
4313 --AngleNestingLevel;
4315 if (AngleNestingLevel == 0) {
4316 if (FormatTok->is(tok::colon)) {
4318 }
else if (!IsDerived && FormatTok->is(tok::identifier) &&
4319 FormatTok->Previous->is(tok::coloncolon)) {
4320 ClassName = FormatTok;
4321 }
else if (FormatTok->is(tok::l_paren) &&
4322 IsNonMacroIdentifier(FormatTok->Previous)) {
4326 if (FormatTok->is(tok::l_brace)) {
4327 if (AngleNestingLevel == 0 && IsListInitialization())
4329 calculateBraceTypes(
true);
4330 if (!tryToParseBracedList())
4333 if (FormatTok->is(tok::l_square)) {
4336 !
Previous->isTypeOrIdentifier(LangOpts))) {
4339 if (!tryToParseLambda())
4346 if (FormatTok->is(tok::semi))
4348 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {
4351 parseCSharpGenericTypeConstraint();
4358 auto GetBraceTypes =
4359 [](
const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {
4360 switch (RecordTok.Tok.getKind()) {
4362 return {TT_ClassLBrace, TT_ClassRBrace};
4363 case tok::kw_struct:
4364 return {TT_StructLBrace, TT_StructRBrace};
4366 return {TT_UnionLBrace, TT_UnionRBrace};
4369 return {TT_RecordLBrace, TT_RecordRBrace};
4372 if (FormatTok->is(tok::l_brace)) {
4373 if (IsListInitialization())
4376 ClassName->setFinalizedType(TT_ClassHeadName);
4377 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
4378 FormatTok->setFinalizedType(OpenBraceType);
4383 Tokens->peekNextToken()->is(tok::r_brace),
4388 bool IndentAfterExplicitAccessModifier =
false;
4389 unsigned AddLevels = 1u;
4390 switch (Style.IndentAccessModifiers) {
4394 if (Style.isCpp()) {
4395 IndentAfterExplicitAccessModifier =
true;
4404 parseBlock(
true, AddLevels,
false,
4407 IndentAfterExplicitAccessModifier);
4409 setPreviousRBraceType(ClosingBraceType);
4416void UnwrappedLineParser::parseObjCMethod() {
4417 assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
4418 "'(' or identifier expected.");
4420 if (FormatTok->is(tok::semi)) {
4424 }
else if (FormatTok->is(tok::l_brace)) {
4425 if (Style.BraceWrapping.AfterFunction)
4436void UnwrappedLineParser::parseObjCProtocolList() {
4437 assert(FormatTok->is(tok::less) &&
"'<' expected.");
4441 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4443 }
while (!
eof() && FormatTok->isNot(tok::greater));
4447void UnwrappedLineParser::parseObjCUntilAtEnd() {
4449 if (FormatTok->is(tok::objc_end)) {
4454 if (FormatTok->is(tok::l_brace)) {
4458 }
else if (FormatTok->is(tok::r_brace)) {
4462 }
else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
4464 if (FormatTok->isOneOf(tok::l_paren, tok::identifier))
4467 parseStructuralElement();
4472void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
4473 assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation));
4479 if (FormatTok->is(tok::less))
4480 parseObjCLightweightGenerics();
4481 if (FormatTok->is(tok::colon)) {
4485 if (FormatTok->is(tok::less))
4486 parseObjCLightweightGenerics();
4487 }
else if (FormatTok->is(tok::l_paren)) {
4492 if (FormatTok->is(tok::less))
4493 parseObjCProtocolList();
4495 if (FormatTok->is(tok::l_brace)) {
4496 if (Style.BraceWrapping.AfterObjCDeclaration)
4505 parseObjCUntilAtEnd();
4508void UnwrappedLineParser::parseObjCLightweightGenerics() {
4509 assert(FormatTok->is(tok::less));
4517 unsigned NumOpenAngles = 1;
4521 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4523 if (FormatTok->is(tok::less)) {
4525 }
else if (FormatTok->is(tok::greater)) {
4526 assert(NumOpenAngles > 0 &&
"'>' makes NumOpenAngles negative");
4529 }
while (!
eof() && NumOpenAngles != 0);
4535bool UnwrappedLineParser::parseObjCProtocol() {
4536 assert(FormatTok->is(tok::objc_protocol));
4539 if (FormatTok->is(tok::l_paren)) {
4551 if (FormatTok->is(tok::less))
4552 parseObjCProtocolList();
4555 if (FormatTok->is(tok::semi)) {
4562 parseObjCUntilAtEnd();
4566void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
4567 bool IsImport = FormatTok->is(Keywords.kw_import);
4568 assert(IsImport || FormatTok->is(tok::kw_export));
4572 if (FormatTok->is(tok::kw_default))
4578 if (FormatTok->is(Keywords.kw_async))
4580 if (FormatTok->is(Keywords.kw_function)) {
4589 if (!IsImport && FormatTok->isNoneOf(tok::l_brace, tok::star) &&
4590 !FormatTok->isStringLiteral() &&
4591 !(FormatTok->is(Keywords.kw_type) &&
4592 Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {
4597 if (FormatTok->is(tok::semi))
4599 if (
Line->Tokens.empty()) {
4604 if (FormatTok->is(tok::l_brace)) {
4605 FormatTok->setBlockKind(BK_Block);
4614void UnwrappedLineParser::parseStatementMacro() {
4616 if (FormatTok->is(tok::l_paren))
4618 if (FormatTok->is(tok::semi))
4623void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
4626 if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
4627 tok::coloncolon, tok::hash) ||
4628 Keywords.isVerilogIdentifier(*FormatTok)) {
4630 }
else if (FormatTok->is(tok::l_square)) {
4638void UnwrappedLineParser::parseVerilogSensitivityList() {
4639 if (FormatTok->isNot(tok::at))
4643 if (FormatTok->is(tok::at))
4645 switch (FormatTok->Tok.getKind()) {
4653 parseVerilogHierarchyIdentifier();
4658unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
4659 unsigned AddLevels = 0;
4661 if (FormatTok->is(Keywords.kw_clocking)) {
4663 if (Keywords.isVerilogIdentifier(*FormatTok))
4665 parseVerilogSensitivityList();
4666 if (FormatTok->is(tok::semi))
4668 }
else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
4669 Keywords.kw_casez, Keywords.kw_randcase,
4670 Keywords.kw_randsequence)) {
4671 if (Style.IndentCaseLabels)
4674 if (FormatTok->is(tok::l_paren)) {
4675 FormatTok->setFinalizedType(TT_ConditionLParen);
4678 if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
4687 if (FormatTok->is(tok::l_square)) {
4688 auto Prev = FormatTok->getPreviousNonComment();
4689 if (Prev && Keywords.isVerilogIdentifier(*Prev))
4690 Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
4692 }
else if (Keywords.isVerilogIdentifier(*FormatTok) ||
4693 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
4694 Keywords.kw_automatic, tok::kw_static)) {
4701 auto NewLine = [
this]() {
4703 Line->IsContinuation =
true;
4707 while (FormatTok->is(Keywords.kw_import)) {
4710 parseVerilogHierarchyIdentifier();
4711 if (FormatTok->is(tok::semi))
4716 if (FormatTok->is(Keywords.kw_verilogHash)) {
4719 if (FormatTok->is(tok::l_paren)) {
4720 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4724 if (FormatTok->is(tok::l_paren)) {
4726 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4731 if (FormatTok->is(Keywords.kw_extends)) {
4734 parseVerilogHierarchyIdentifier();
4735 if (FormatTok->is(tok::l_paren))
4738 if (FormatTok->is(Keywords.kw_implements)) {
4742 parseVerilogHierarchyIdentifier();
4743 }
while (FormatTok->is(tok::comma));
4747 if (FormatTok->is(tok::at)) {
4749 parseVerilogSensitivityList();
4752 if (FormatTok->is(tok::semi))
4760void UnwrappedLineParser::parseVerilogTable() {
4761 assert(FormatTok->is(Keywords.kw_table));
4765 auto InitialLevel =
Line->Level++;
4766 while (!
eof() && !Keywords.isVerilogEnd(*FormatTok)) {
4769 if (
Tok->
is(tok::semi))
4771 else if (
Tok->
isOneOf(tok::star, tok::colon, tok::question, tok::minus))
4772 Tok->setFinalizedType(TT_VerilogTableItem);
4774 Line->Level = InitialLevel;
4779void UnwrappedLineParser::parseVerilogCaseLabel() {
4785 auto OrigLevel =
Line->Level;
4786 auto FirstLine = CurrentLines->size();
4787 if (
Line->Level == 0 || (
Line->InPPDirective &&
Line->Level <= 1))
4789 else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
4791 parseStructuralElement();
4794 if (CurrentLines->size() > FirstLine)
4795 (*CurrentLines)[FirstLine].Level = OrigLevel;
4796 Line->Level = OrigLevel;
4799void UnwrappedLineParser::parseVerilogExtern() {
4801 FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
4804 if (FormatTok->is(tok::string_literal))
4806 skipVerilogQualifiers();
4807 if (Keywords.isVerilogIdentifier(*FormatTok))
4809 if (FormatTok->is(tok::equal))
4811 if (Keywords.isVerilogHierarchy(*FormatTok))
4812 parseVerilogHierarchyHeader();
4815void UnwrappedLineParser::skipVerilogQualifiers() {
4816 while (FormatTok->isOneOf(tok::kw_protected, tok::kw_virtual, tok::kw_static,
4817 Keywords.kw_rand, Keywords.kw_context,
4818 Keywords.kw_pure, Keywords.kw_randc,
4819 Keywords.kw_local)) {
4824bool UnwrappedLineParser::containsExpansion(
const UnwrappedLine &
Line)
const {
4825 for (
const auto &N :
Line.Tokens) {
4826 if (N.Tok->MacroCtx)
4828 for (
const UnwrappedLine &Child : N.Children)
4829 if (containsExpansion(Child))
4835void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
4836 if (
Line->Tokens.empty())
4839 if (!parsingPPDirective()) {
4840 llvm::dbgs() <<
"Adding unwrapped line:\n";
4841 printDebugInfo(*
Line);
4849 bool ClosesWhitesmithsBlock =
4850 Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
4856 if (!parsingPPDirective() && !InExpansion && containsExpansion(*
Line)) {
4858 Reconstruct.emplace(
Line->Level, Unexpanded);
4859 Reconstruct->addLine(*
Line);
4864 CurrentExpandedLines.push_back(std::move(*
Line));
4866 if (Reconstruct->finished()) {
4867 UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();
4868 assert(!Reconstructed.Tokens.empty() &&
4869 "Reconstructed must at least contain the macro identifier.");
4870 assert(!parsingPPDirective());
4872 llvm::dbgs() <<
"Adding unexpanded line:\n";
4873 printDebugInfo(Reconstructed);
4875 ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;
4876 Lines.push_back(std::move(Reconstructed));
4877 CurrentExpandedLines.clear();
4878 Reconstruct.reset();
4883 assert(!Reconstruct || (CurrentLines != &Lines) || !PP.Stack.empty());
4884 CurrentLines->push_back(std::move(*
Line));
4886 Line->Tokens.clear();
4887 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
4888 Line->FirstStartColumn = 0;
4889 Line->IsContinuation =
false;
4890 Line->SeenDecltypeAuto =
false;
4891 Line->IsModuleOrImportDecl =
false;
4893 if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
4895 if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {
4896 CurrentLines->append(
4897 std::make_move_iterator(PreprocessorDirectives.begin()),
4898 std::make_move_iterator(PreprocessorDirectives.end()));
4899 PreprocessorDirectives.clear();
4902 FormatTok->Previous =
nullptr;
4905bool UnwrappedLineParser::eof()
const {
return FormatTok->is(tok::eof); }
4907bool UnwrappedLineParser::isOnNewLine(
const FormatToken &FormatTok) {
4908 return (
Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
4909 FormatTok.NewlinesBefore > 0;
4917 const llvm::Regex &CommentPragmasRegex) {
4921 StringRef IndentContent = FormatTok.
TokenText;
4922 if (FormatTok.
TokenText.starts_with(
"//") ||
4923 FormatTok.
TokenText.starts_with(
"/*")) {
4924 IndentContent = FormatTok.
TokenText.substr(2);
4926 if (CommentPragmasRegex.match(IndentContent))
5001 if (PreviousToken && PreviousToken->
is(tok::l_brace) &&
5003 MinColumnToken = PreviousToken;
5006 PreviousToken = Node.
Tok;
5010 MinColumnToken = Node.
Tok;
5012 if (PreviousToken && PreviousToken->
is(tok::l_brace))
5013 MinColumnToken = PreviousToken;
5019void UnwrappedLineParser::flushComments(
bool NewlineBeforeNext) {
5020 bool JustComments =
Line->Tokens.empty();
5030 Tok->ContinuesLineCommentSection =
5031 continuesLineCommentSection(*
Tok, *
Line, Style, CommentPragmasRegex);
5032 if (isOnNewLine(*
Tok) && JustComments && !
Tok->ContinuesLineCommentSection)
5036 if (NewlineBeforeNext && JustComments)
5038 CommentsBeforeNextToken.clear();
5041void UnwrappedLineParser::nextToken(
int LevelDifference) {
5044 flushComments(isOnNewLine(*FormatTok));
5045 pushToken(FormatTok);
5047 if (!Style.isJavaScript())
5048 readToken(LevelDifference);
5050 readTokenWithJavaScriptASI();
5052 if (Style.isVerilog()) {
5059 if (Keywords.isVerilogEnd(*FormatTok))
5060 FormatTok->Tok.setKind(tok::r_brace);
5064void UnwrappedLineParser::distributeComments(
5084 if (Comments.empty())
5086 bool ShouldPushCommentsInCurrentLine =
true;
5087 bool HasTrailAlignedWithNextToken =
false;
5088 unsigned StartOfTrailAlignedWithNextToken = 0;
5091 for (
unsigned i = Comments.size() - 1; i > 0; --i) {
5093 HasTrailAlignedWithNextToken =
true;
5094 StartOfTrailAlignedWithNextToken = i;
5098 for (
unsigned i = 0, e = Comments.size(); i < e; ++i) {
5100 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
5101 FormatTok->ContinuesLineCommentSection =
false;
5104 *FormatTok, *
Line, Style, CommentPragmasRegex);
5106 if (!FormatTok->ContinuesLineCommentSection &&
5107 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
5108 ShouldPushCommentsInCurrentLine =
false;
5110 if (ShouldPushCommentsInCurrentLine)
5111 pushToken(FormatTok);
5113 CommentsBeforeNextToken.push_back(FormatTok);
5117void UnwrappedLineParser::readToken(
int LevelDifference) {
5119 bool PreviousWasComment =
false;
5120 bool FirstNonCommentOnLine =
false;
5122 FormatTok = Tokens->getNextToken();
5124 while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
5125 TT_ConflictAlternative)) {
5126 if (FormatTok->is(TT_ConflictStart))
5127 conditionalCompilationStart(
false);
5128 else if (FormatTok->is(TT_ConflictAlternative))
5129 conditionalCompilationAlternative();
5130 else if (FormatTok->is(TT_ConflictEnd))
5131 conditionalCompilationEnd();
5132 FormatTok = Tokens->getNextToken();
5133 FormatTok->MustBreakBefore =
true;
5134 FormatTok->MustBreakBeforeFinalized =
true;
5137 auto IsFirstNonCommentOnLine = [](
bool FirstNonCommentOnLine,
5139 bool PreviousWasComment) {
5141 return Tok.HasUnescapedNewline ||
Tok.IsFirst;
5146 if (PreviousWasComment)
5147 return FirstNonCommentOnLine || IsFirstOnLine(
Tok);
5148 return IsFirstOnLine(
Tok);
5151 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
5152 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
5153 PreviousWasComment = FormatTok->is(tok::comment);
5155 while (!
Line->InPPDirective && FormatTok->is(tok::hash) &&
5156 FirstNonCommentOnLine) {
5159 const auto *
Next = Tokens->peekNextToken();
5160 if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*
Next)) ||
5161 (Style.isTableGen() &&
5162 Next->isNoneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef,
5163 tok::pp_ifndef, tok::pp_endif))) {
5166 distributeComments(Comments, FormatTok);
5171 const bool ParsedBefore = !ParsedPPDirectives.insert(FormatTok).second;
5174 bool SwitchToPreprocessorLines = !
Line->Tokens.empty();
5175 ScopedLineState BlockState(*
this, SwitchToPreprocessorLines,
5177 assert((LevelDifference >= 0 ||
5178 static_cast<unsigned>(-LevelDifference) <=
Line->Level) &&
5179 "LevelDifference makes Line->Level negative");
5180 Line->Level += LevelDifference;
5185 PP.BranchLevel > 0) {
5186 Line->Level += PP.BranchLevel;
5188 assert(
Line->Level >=
Line->UnbracedBodyLevel);
5189 Line->Level -=
Line->UnbracedBodyLevel;
5190 flushComments(isOnNewLine(*FormatTok));
5191 const bool IsEndIf = Tokens->peekNextToken()->is(tok::pp_endif);
5193 PreviousWasComment = FormatTok->is(tok::comment);
5194 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
5195 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
5198 if (IsEndIf && PP.IncludeGuard == IG_Defined && PP.BranchLevel == -1 &&
5199 getIncludeGuardState(Style.IndentPPDirectives) == IG_Inited &&
5201 (PreviousWasComment &&
5202 Tokens->peekNextToken(
true)->is(tok::eof)))) {
5203 PP.IncludeGuard = IG_Found;
5207 if (!PP.Stack.empty() && (PP.Stack.back().Kind == PP_Unreachable) &&
5208 !
Line->InPPDirective) {
5212 if (FormatTok->is(tok::identifier) &&
5213 Macros.defined(FormatTok->TokenText) &&
5215 !
Line->InPPDirective) {
5217 unsigned Position = Tokens->getPosition();
5222 const auto SavedPPState = PP;
5226 auto PreCall = std::move(
Line);
5227 Line.reset(
new UnwrappedLine);
5228 bool OldInExpansion = InExpansion;
5231 auto Args = parseMacroCall(SavedPPState);
5232 InExpansion = OldInExpansion;
5233 assert(
Line->Tokens.front().Tok == ID);
5235 auto UnexpandedLine = std::move(
Line);
5237 Line = std::move(PreCall);
5240 llvm::dbgs() <<
"Macro call: " <<
ID->TokenText <<
"(";
5242 llvm::dbgs() <<
"(";
5243 for (
const auto &Arg : Args.value())
5244 for (
const auto &
T : Arg)
5245 llvm::dbgs() <<
T->TokenText <<
" ";
5246 llvm::dbgs() <<
")";
5248 llvm::dbgs() <<
"\n";
5250 if (
Macros.objectLike(
ID->TokenText) && Args &&
5251 !
Macros.hasArity(
ID->TokenText, Args->size())) {
5257 LLVM_DEBUG(llvm::dbgs()
5258 <<
"Macro \"" <<
ID->TokenText
5259 <<
"\" not overloaded for arity " << Args->size()
5260 <<
"or not function-like, using object-like overload.");
5262 UnexpandedLine->Tokens.resize(1);
5263 Tokens->setPosition(Position);
5265 FormatTok = Tokens->getNextToken();
5267 assert(!Args &&
Macros.objectLike(
ID->TokenText));
5269 if ((!Args &&
Macros.objectLike(
ID->TokenText)) ||
5270 (Args &&
Macros.hasArity(
ID->TokenText, Args->size()))) {
5273 Unexpanded[
ID] = std::move(UnexpandedLine);
5275 Macros.expand(ID, std::move(Args));
5276 if (!Expansion.empty())
5277 FormatTok = Tokens->insertTokens(Expansion);
5280 llvm::dbgs() <<
"Expanded: ";
5281 for (
const auto &
T : Expansion)
5282 llvm::dbgs() <<
T->TokenText <<
" ";
5283 llvm::dbgs() <<
"\n";
5287 llvm::dbgs() <<
"Did not expand macro \"" <<
ID->TokenText
5288 <<
"\", because it was used ";
5290 llvm::dbgs() <<
"with " << Args->size();
5292 llvm::dbgs() <<
"without";
5293 llvm::dbgs() <<
" arguments, which doesn't match any definition.\n";
5295 Tokens->setPosition(Position);
5301 if (FormatTok->isNot(tok::comment)) {
5302 distributeComments(Comments, FormatTok);
5307 Comments.push_back(FormatTok);
5310 distributeComments(Comments,
nullptr);
5315template <
typename Iterator>
5316void pushTokens(Iterator Begin, Iterator End,
5318 for (
auto I = Begin; I != End; ++I) {
5319 Into.push_back(I->Tok);
5320 for (
const auto &Child : I->Children)
5321 pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);
5326std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
5327UnwrappedLineParser::parseMacroCall(
const PPState &SavedPPState) {
5328 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;
5329 assert(
Line->Tokens.empty());
5332 auto ConsumeLastTokenOfCall = [
this] {
5333 flushComments(isOnNewLine(*FormatTok));
5334 pushToken(FormatTok);
5335 FormatTok = Tokens->getNextToken();
5337 if (Tokens->peekNextToken(
true)->isNot(tok::l_paren)) {
5338 ConsumeLastTokenOfCall();
5342 assert(FormatTok->is(tok::l_paren));
5343 unsigned Position = Tokens->getPosition();
5347 auto ArgStart = std::prev(
Line->Tokens.end());
5351 switch (FormatTok->Tok.getKind()) {
5356 case tok::r_paren: {
5362 Args->push_back({});
5363 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5364 ConsumeLastTokenOfCall();
5372 Args->push_back({});
5373 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5375 ArgStart = std::prev(
Line->Tokens.end());
5383 Line->Tokens.resize(1);
5384 Tokens->setPosition(Position);
5391 Line->Tokens.push_back(UnwrappedLineNode(
Tok));
5392 if (PP.AtEndOfPPLine) {
5393 auto &
Tok = *
Line->Tokens.back().Tok;
5394 Tok.MustBreakBefore =
true;
5395 Tok.MustBreakBeforeFinalized =
true;
5396 Tok.FirstAfterPPLine =
true;
5397 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