clang: lib/Format/UnwrappedLineParser.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/raw_os_ostream.h"
26#include "llvm/Support/raw_ostream.h"
27
28#include
29#include
30
31#define DEBUG_TYPE "format-parser"
32
34namespace format {
35
36namespace {
37
38void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,
39 StringRef Prefix = "", bool PrintText = false) {
40 OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn
41 << ")" << (Line.InPPDirective ? " MACRO" : "") << ": ";
43 for (std::list::const_iterator I = Line.Tokens.begin(),
45 I != E; ++I) {
47 OS << Prefix;
49 }
50 OS << I->Tok->Tok.getName() << "["
51 << "T=" << (unsigned)I->Tok->getType()
52 << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText
53 << "\"] ";
54 for (const auto *CI = I->Children.begin(), *CE = I->Children.end();
55 CI != CE; ++CI) {
56 OS << "\n";
57 printLine(OS, *CI, (Prefix + " ").str());
59 }
60 }
62 OS << "\n";
63}
64
65LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line) {
66 printLine(llvm::dbgs(), Line);
67}
68
69class ScopedDeclarationState {
70public:
71 ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack,
72 bool MustBeDeclaration)
73 : Line(Line), Stack(Stack) {
74 Line.MustBeDeclaration = MustBeDeclaration;
75 Stack.push_back(MustBeDeclaration);
76 }
77 ~ScopedDeclarationState() {
78 Stack.pop_back();
79 if (!Stack.empty())
80 Line.MustBeDeclaration = Stack.back();
81 else
82 Line.MustBeDeclaration = true;
83 }
84
85private:
86 UnwrappedLine &Line;
87 llvm::BitVector &Stack;
88};
89
90}
91
93 llvm::raw_os_ostream OS(Stream);
94 printLine(OS, Line);
95 return Stream;
96}
97
99public:
101 bool SwitchToPreprocessorLines = false)
103 if (SwitchToPreprocessorLines)
104 Parser.CurrentLines = &Parser.PreprocessorDirectives;
105 else if (.Line->Tokens.empty())
106 Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
107 PreBlockLine = std::move(Parser.Line);
108 Parser.Line = std::make_unique();
109 Parser.Line->Level = PreBlockLine->Level;
110 Parser.Line->PPLevel = PreBlockLine->PPLevel;
111 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
112 Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
113 Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel;
114 }
115
117 if (.Line->Tokens.empty())
118 Parser.addUnwrappedLine();
119 assert(Parser.Line->Tokens.empty());
120 Parser.Line = std::move(PreBlockLine);
121 if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
122 Parser.MustBreakBeforeNextToken = true;
123 Parser.CurrentLines = OriginalLines;
124 }
125
126private:
128
129 std::unique_ptr PreBlockLine;
131};
132
134public:
136 const FormatStyle &Style, unsigned &LineLevel)
138 Style.BraceWrapping.AfterControlStatement,
139 Style.BraceWrapping.IndentBraces) {}
141 bool WrapBrace, bool IndentBrace)
142 : LineLevel(LineLevel), OldLineLevel(LineLevel) {
143 if (WrapBrace)
144 Parser->addUnwrappedLine();
145 if (IndentBrace)
146 ++LineLevel;
147 }
149
150private:
151 unsigned &LineLevel;
152 unsigned OldLineLevel;
153};
154
159 llvm::SpecificBumpPtrAllocator &Allocator,
162 CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()),
164 CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
165 Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
166 IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
167 ? IG_Rejected
168 : IG_Inited),
169 IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn),
170 Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {
171 assert(IsCpp == LangOpts.CXXOperatorNames);
172}
173
174void UnwrappedLineParser::reset() {
175 PPBranchLevel = -1;
177 ? IG_Rejected
178 : IG_Inited;
179 IncludeGuardToken = nullptr;
181 CommentsBeforeNextToken.clear();
182 FormatTok = nullptr;
183 MustBreakBeforeNextToken = false;
184 IsDecltypeAutoFunction = false;
185 PreprocessorDirectives.clear();
186 CurrentLines = &Lines;
187 DeclarationScopeStack.clear();
188 NestedTooDeep.clear();
189 NestedLambdas.clear();
190 PPStack.clear();
191 Line->FirstStartColumn = FirstStartColumn;
192
193 if (!Unexpanded.empty())
195 Token->MacroCtx.reset();
196 CurrentExpandedLines.clear();
197 ExpandedLines.clear();
198 Unexpanded.clear();
199 InExpansion = false;
200 Reconstruct.reset();
201}
202
205 Line->FirstStartColumn = FirstStartColumn;
206 do {
207 LLVM_DEBUG(llvm::dbgs() << "----\n");
208 reset();
209 Tokens = &TokenSource;
210 TokenSource.reset();
211
212 readToken();
213 parseFile();
214
215
216
217 if (IncludeGuard == IG_Found) {
218 for (auto &Line : Lines)
219 if (Line.InPPDirective && Line.Level > 0)
220 --Line.Level;
221 }
222
223
224 assert(eof());
225 pushToken(FormatTok);
226 addUnwrappedLine();
227
228
229
230 if (!ExpandedLines.empty()) {
231 LLVM_DEBUG(llvm::dbgs() << "Expanded lines:\n");
232 for (const auto &Line : Lines) {
233 if (!Line.Tokens.empty()) {
234 auto it = ExpandedLines.find(Line.Tokens.begin()->Tok);
235 if (it != ExpandedLines.end()) {
236 for (const auto &Expanded : it->second) {
237 LLVM_DEBUG(printDebugInfo(Expanded));
239 }
240 continue;
241 }
242 }
243 LLVM_DEBUG(printDebugInfo(Line));
245 }
247 }
248
249 LLVM_DEBUG(llvm::dbgs() << "Unwrapped lines:\n");
251 LLVM_DEBUG(printDebugInfo(Line));
253 }
255 Lines.clear();
256 while (!PPLevelBranchIndex.empty() &&
257 PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {
258 PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);
259 PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);
260 }
261 if (!PPLevelBranchIndex.empty()) {
262 ++PPLevelBranchIndex.back();
263 assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());
264 assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
265 }
266 } while (!PPLevelBranchIndex.empty());
267}
268
269void UnwrappedLineParser::parseFile() {
270
271
272 bool MustBeDeclaration = !Line->InPPDirective && !Style.isJavaScript();
273 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
274 MustBeDeclaration);
276 parseBracedList();
277 else
278 parseLevel();
279
280
281
282
283
284
285
286
287
288
290 !CommentsBeforeNextToken.empty()) {
291 addUnwrappedLine();
292 }
293 flushComments(true);
294 addUnwrappedLine();
295}
296
297void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {
298 do {
300 case tok::l_brace:
301 return;
302 default:
303 if (FormatTok->is(Keywords.kw_where)) {
304 addUnwrappedLine();
305 nextToken();
306 parseCSharpGenericTypeConstraint();
307 break;
308 }
309 nextToken();
310 break;
311 }
312 } while (!eof());
313}
314
315void UnwrappedLineParser::parseCSharpAttribute() {
316 int UnpairedSquareBrackets = 1;
317 do {
319 case tok::r_square:
320 nextToken();
321 --UnpairedSquareBrackets;
322 if (UnpairedSquareBrackets == 0) {
323 addUnwrappedLine();
324 return;
325 }
326 break;
327 case tok::l_square:
328 ++UnpairedSquareBrackets;
329 nextToken();
330 break;
331 default:
332 nextToken();
333 break;
334 }
335 } while (!eof());
336}
337
338bool UnwrappedLineParser::precededByCommentOrPPDirective() const {
339 if (!Lines.empty() && Lines.back().InPPDirective)
340 return true;
341
345}
346
347
348
349
350
351
352
353bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
354 IfStmtKind *IfKind,
355 FormatToken **IfLeftBrace) {
356 const bool InRequiresExpression =
357 OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
358 const bool IsPrecededByCommentOrPPDirective =
360 FormatToken *IfLBrace = nullptr;
361 bool HasDoWhile = false;
362 bool HasLabel = false;
363 unsigned StatementCount = 0;
364 bool SwitchLabelEncountered = false;
365
366 do {
368 nextToken();
369 if (FormatTok->is(tok::l_paren))
370 parseParens();
371 continue;
372 }
374 if (FormatTok->is(TT_MacroBlockBegin))
375 Kind = tok::l_brace;
376 else if (FormatTok->is(TT_MacroBlockEnd))
377 Kind = tok::r_brace;
378
379 auto ParseDefault = [this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
380 &HasLabel, &StatementCount] {
381 parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,
382 HasDoWhile ? nullptr : &HasDoWhile,
383 HasLabel ? nullptr : &HasLabel);
384 ++StatementCount;
385 assert(StatementCount > 0 && "StatementCount overflow!");
386 };
387
388 switch (Kind) {
389 case tok::comment:
390 nextToken();
391 addUnwrappedLine();
392 break;
393 case tok::l_brace:
394 if (InRequiresExpression) {
396 } else if (FormatTok->Previous &&
398
399
400 ParseDefault();
401 continue;
402 }
403 if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {
404 if (tryToParseBracedList())
405 continue;
407 }
408 parseBlock();
409 ++StatementCount;
410 assert(StatementCount > 0 && "StatementCount overflow!");
411 addUnwrappedLine();
412 break;
413 case tok::r_brace:
414 if (OpeningBrace) {
416 !OpeningBrace->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
417 return false;
418 }
419 if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||
420 HasDoWhile || IsPrecededByCommentOrPPDirective ||
421 precededByCommentOrPPDirective()) {
422 return false;
423 }
424 const FormatToken *Next = Tokens->peekNextToken();
425 if (Next->is(tok::comment) && Next->NewlinesBefore == 0)
426 return false;
427 if (IfLeftBrace)
428 *IfLeftBrace = IfLBrace;
429 return true;
430 }
431 nextToken();
432 addUnwrappedLine();
433 break;
434 case tok::kw_default: {
435 unsigned StoredPosition = Tokens->getPosition();
437 FormatTok = Tokens->setPosition(StoredPosition);
438 if (!Next->isOneOf(tok::colon, tok::arrow)) {
439
440
441 parseStructuralElement();
442 break;
443 }
444
445 [[fallthrough]];
446 }
447 case tok::kw_case:
449 (Style.isJavaScript() && Line->MustBeDeclaration)) {
450
451
452
453
454 ParseDefault();
455 break;
456 }
457 if (!SwitchLabelEncountered &&
459 (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||
460 (Line->InPPDirective && Line->Level == 1))) {
461 ++Line->Level;
462 }
463 SwitchLabelEncountered = true;
464 parseStructuralElement();
465 break;
466 case tok::l_square:
468 nextToken();
469 parseCSharpAttribute();
470 break;
471 }
472 if (handleCppAttributes())
473 break;
474 [[fallthrough]];
475 default:
476 ParseDefault();
477 break;
478 }
479 } while (!eof());
480
481 return false;
482}
483
484void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
485
486
487
488
489 unsigned StoredPosition = Tokens->getPosition();
490 FormatToken *Tok = FormatTok;
491 const FormatToken *PrevTok = Tok->Previous;
492
493
494
495 struct StackEntry {
496 FormatToken *Tok;
497 const FormatToken *PrevTok;
498 };
499 SmallVector<StackEntry, 8> LBraceStack;
500 assert(Tok->is(tok::l_brace));
501
502 do {
504
505 if (!Line->InMacroBody && !Style.isTableGen()) {
506
507 while (NextTok->is(tok::hash)) {
509 if (NextTok->is(tok::pp_not_keyword))
510 break;
511 do {
513 } while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));
514
515 while (NextTok->is(tok::comment))
517 }
518 }
519
520 switch (Tok->Tok.getKind()) {
521 case tok::l_brace:
523 if (PrevTok->isOneOf(tok::colon, tok::less)) {
524
525
526
527
528
529
530
531
532
534 } else if (PrevTok->is(tok::r_paren)) {
535
537 }
538 } else {
540 }
541 LBraceStack.push_back({Tok, PrevTok});
542 break;
543 case tok::r_brace:
544 if (LBraceStack.empty())
545 break;
546 if (auto *LBrace = LBraceStack.back().Tok; LBrace->is(BK_Unknown)) {
547 bool ProbablyBracedList = false;
549 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
550 } else if (LBrace->isNot(TT_EnumLBrace)) {
551
552
553 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
554 NextTok->OriginalColumn == 0;
555
556
557
558
559
560
561
562
563
564 ProbablyBracedList = LBrace->is(TT_BracedListLBrace);
565
566 ProbablyBracedList = ProbablyBracedList ||
568 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
569 Keywords.kw_as));
570 ProbablyBracedList =
571 ProbablyBracedList ||
572 (IsCpp && (PrevTok->Tok.isLiteral() ||
573 NextTok->isOneOf(tok::l_paren, tok::arrow)));
574
575
576
577
578
579 ProbablyBracedList =
580 ProbablyBracedList ||
581 NextTok->isOneOf(tok::comma, tok::period, tok::colon,
582 tok::r_paren, tok::r_square, tok::ellipsis);
583
584
585
586 ProbablyBracedList =
587 ProbablyBracedList ||
588 (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&
589 LBraceStack.back().PrevTok->isOneOf(tok::identifier,
590 tok::greater));
591
592 ProbablyBracedList =
593 ProbablyBracedList ||
594 (NextTok->is(tok::identifier) &&
595 !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace));
596
597 ProbablyBracedList = ProbablyBracedList ||
598 (NextTok->is(tok::semi) &&
599 (!ExpectClassBody || LBraceStack.size() != 1));
600
601 ProbablyBracedList =
602 ProbablyBracedList ||
603 (NextTok->isBinaryOperator() && !NextIsObjCMethod);
604
605 if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
606
607
609 ProbablyBracedList = NextTok->isNot(tok::l_square);
610 }
611
612
613 if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
614 !FormatTok->Previous && NextTok->is(tok::eof) &&
615
616
617
618 !PrevTok->isOneOf(tok::semi, BK_Block, tok::colon)) {
619 ProbablyBracedList = true;
620 }
621 }
623 Tok->setBlockKind(BlockKind);
624 LBrace->setBlockKind(BlockKind);
625 }
626 LBraceStack.pop_back();
627 break;
628 case tok::identifier:
629 if (Tok->isNot(TT_StatementMacro))
630 break;
631 [[fallthrough]];
632 case tok::at:
633 case tok:🚛
634 case tok::kw_if:
635 case tok::kw_while:
636 case tok::kw_for:
637 case tok::kw_switch:
638 case tok::kw_try:
639 case tok::kw___try:
640 if (!LBraceStack.empty() && LBraceStack.back().Tok->is(BK_Unknown))
641 LBraceStack.back().Tok->setBlockKind(BK_Block);
642 break;
643 default:
644 break;
645 }
646
647 PrevTok = Tok;
648 Tok = NextTok;
649 } while (Tok->isNot(tok::eof) && !LBraceStack.empty());
650
651
652 for (const auto &Entry : LBraceStack)
654 Entry.Tok->setBlockKind(BK_Block);
655
656 FormatTok = Tokens->setPosition(StoredPosition);
657}
658
659
660void UnwrappedLineParser::setPreviousRBraceType(TokenType Type) {
662 Prev && Prev->is(tok::r_brace)) {
664 }
665}
666
667template
669 std::hash hasher;
670 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
671}
672
673size_t UnwrappedLineParser::computePPHash() const {
674 size_t h = 0;
675 for (const auto &i : PPStack) {
678 }
679 return h;
680}
681
682
683
684
685
686bool UnwrappedLineParser::mightFitOnOneLine(
687 UnwrappedLine &ParsedLine, const FormatToken *OpeningBrace) const {
688 const auto ColumnLimit = Style.ColumnLimit;
689 if (ColumnLimit == 0)
690 return true;
691
692 auto &Tokens = ParsedLine.Tokens;
693 assert(!Tokens.empty());
694
695 const auto *LastToken = Tokens.back().Tok;
696 assert(LastToken);
697
698 SmallVector SavedTokens(Tokens.size());
699
700 int Index = 0;
701 for (const auto &Token : Tokens) {
702 assert(Token.Tok);
703 auto &SavedToken = SavedTokens[Index++];
704 SavedToken.Tok = new FormatToken;
705 SavedToken.Tok->copyFrom(*Token.Tok);
706 SavedToken.Children = std::move(Token.Children);
707 }
708
709 AnnotatedLine Line(ParsedLine);
710 assert(Line.Last == LastToken);
711
712 TokenAnnotator Annotator(Style, Keywords);
713 Annotator.annotate(Line);
714 Annotator.calculateFormattingInformation(Line);
715
716 auto Length = LastToken->TotalLength;
717 if (OpeningBrace) {
718 assert(OpeningBrace != Tokens.front().Tok);
719 if (auto Prev = OpeningBrace->Previous;
720 Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
721 Length -= ColumnLimit;
722 }
723 Length -= OpeningBrace->TokenText.size() + 1;
724 }
725
726 if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
727 assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
728 Length -= FirstToken->TokenText.size() + 1;
729 }
730
731 Index = 0;
732 for (auto &Token : Tokens) {
733 const auto &SavedToken = SavedTokens[Index++];
734 Token.Tok->copyFrom(*SavedToken.Tok);
735 Token.Children = std::move(SavedToken.Children);
736 delete SavedToken.Tok;
737 }
738
739
740 assert(!Line.InMacroBody);
741 assert(!Line.InPPDirective);
742 return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
743}
744
745FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration,
746 unsigned AddLevels, bool MunchSemi,
747 bool KeepBraces,
748 IfStmtKind *IfKind,
749 bool UnindentWhitesmithsBraces) {
750 auto HandleVerilogBlockLabel = [this]() {
751
752 if (Style.isVerilog() && FormatTok->is(tok::colon)) {
753 nextToken();
755 nextToken();
756 }
757 };
758
759
760
761 const bool VerilogHierarchy =
763 assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
765 (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
766 "'{' or macro block token expected");
767 FormatToken *Tok = FormatTok;
768 const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
769 auto Index = CurrentLines->size();
770 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
772
773
774
775 if (!VerilogHierarchy && AddLevels > 0 &&
777 ++Line->Level;
778 }
779
780 size_t PPStartHash = computePPHash();
781
782 const unsigned InitialLevel = Line->Level;
783 if (VerilogHierarchy) {
784 AddLevels += parseVerilogHierarchyHeader();
785 } else {
786 nextToken(AddLevels);
787 HandleVerilogBlockLabel();
788 }
789
790
791 if (Line->Level > 300)
792 return nullptr;
793
794 if (MacroBlock && FormatTok->is(tok::l_paren))
795 parseParens();
796
797 size_t NbPreprocessorDirectives =
798 !parsingPPDirective() ? PreprocessorDirectives.size() : 0;
799 addUnwrappedLine();
800 size_t OpeningLineIndex =
801 CurrentLines->empty()
803 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
804
805
806
807
808 if (UnindentWhitesmithsBraces)
809 --Line->Level;
810
811 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
812 MustBeDeclaration);
814 Line->Level += AddLevels;
815
816 FormatToken *IfLBrace = nullptr;
817 const bool SimpleBlock = parseLevel(Tok, IfKind, &IfLBrace);
818
819 if (eof())
820 return IfLBrace;
821
822 if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)
823 : FormatTok->isNot(tok::r_brace)) {
824 Line->Level = InitialLevel;
826 return IfLBrace;
827 }
828
829 if (FormatTok->is(tok::r_brace)) {
831 if (Tok->is(TT_NamespaceLBrace))
833 }
834
835 const bool IsFunctionRBrace =
836 FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
837
838 auto RemoveBraces = [=]() mutable {
839 if (!SimpleBlock)
840 return false;
841 assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
842 assert(FormatTok->is(tok::r_brace));
843 const bool WrappedOpeningBrace = !Tok->Previous;
844 if (WrappedOpeningBrace && FollowedByComment)
845 return false;
846 const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
847 if (KeepBraces && !HasRequiredIfBraces)
848 return false;
849 if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
850 const FormatToken *Previous = Tokens->getPreviousToken();
853 return false;
854 }
855 assert(!CurrentLines->empty());
856 auto &LastLine = CurrentLines->back();
857 if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
858 return false;
859 if (Tok->is(TT_ElseLBrace))
860 return true;
861 if (WrappedOpeningBrace) {
862 assert(Index > 0);
863 --Index;
864 Tok = nullptr;
865 }
866 return mightFitOnOneLine((*CurrentLines)[Index], Tok);
867 };
868 if (RemoveBraces()) {
869 Tok->MatchingParen = FormatTok;
871 }
872
873 size_t PPEndHash = computePPHash();
874
875
876 nextToken(-AddLevels);
877
878
879
880
882 while (FormatTok->is(tok::semi)) {
884 nextToken();
885 }
886 }
887
888 HandleVerilogBlockLabel();
889
890 if (MacroBlock && FormatTok->is(tok::l_paren))
891 parseParens();
892
893 Line->Level = InitialLevel;
894
895 if (FormatTok->is(tok::kw_noexcept)) {
896
897 nextToken();
898 }
899
900 if (FormatTok->is(tok::arrow)) {
901
902
903 nextToken();
904 parseStructuralElement();
905 }
906
907 if (MunchSemi && FormatTok->is(tok::semi))
908 nextToken();
909
910 if (PPStartHash == PPEndHash) {
911 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
913
914 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
915 CurrentLines->size() - 1;
916 }
917 }
918
919 return IfLBrace;
920}
921
923
924
925 if (Line.Tokens.size() < 4)
926 return false;
927 auto I = Line.Tokens.begin();
928 if (I->Tok->TokenText != "goog")
929 return false;
930 ++I;
931 if (I->Tok->isNot(tok::period))
932 return false;
933 ++I;
934 if (I->Tok->TokenText != "scope")
935 return false;
936 ++I;
937 return I->Tok->is(tok::l_paren);
938}
939
942
943
944
945
946 if (Line.Tokens.size() < 3)
947 return false;
948 auto I = Line.Tokens.begin();
949 if (I->Tok->isNot(tok::l_paren))
950 return false;
951 ++I;
953 return false;
954 ++I;
955 return I->Tok->is(tok::l_paren);
956}
957
961 if (InitialToken.is(TT_NamespaceMacro))
962 Kind = tok::kw_namespace;
963
964 switch (Kind) {
965 case tok::kw_namespace:
967 case tok::kw_class:
969 case tok::kw_union:
971 case tok::kw_struct:
973 case tok::kw_enum:
975 default:
976 return false;
977 }
978}
979
980void UnwrappedLineParser::parseChildBlock() {
981 assert(FormatTok->is(tok::l_brace));
983 const FormatToken *OpeningBrace = FormatTok;
984 nextToken();
985 {
989 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
990 false);
991 Line->Level += SkipIndent ? 0 : 1;
992 parseLevel(OpeningBrace);
993 flushComments(isOnNewLine(*FormatTok));
994 Line->Level -= SkipIndent ? 0 : 1;
995 }
996 nextToken();
997}
998
999void UnwrappedLineParser::parsePPDirective() {
1000 assert(FormatTok->is(tok::hash) && "'#' expected");
1001 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
1002
1003 nextToken();
1004
1006 parsePPUnknown();
1007 return;
1008 }
1009
1011 case tok::pp_define:
1012 parsePPDefine();
1013 return;
1014 case tok::pp_if:
1015 parsePPIf(false);
1016 break;
1017 case tok::pp_ifdef:
1018 case tok::pp_ifndef:
1019 parsePPIf(true);
1020 break;
1021 case tok::pp_else:
1022 case tok::pp_elifdef:
1023 case tok::pp_elifndef:
1024 case tok::pp_elif:
1025 parsePPElse();
1026 break;
1027 case tok::pp_endif:
1028 parsePPEndIf();
1029 break;
1030 case tok::pp_pragma:
1031 parsePPPragma();
1032 break;
1033 case tok::pp_error:
1034 case tok::pp_warning:
1035 nextToken();
1036 if (!eof() && Style.isCpp())
1038 [[fallthrough]];
1039 default:
1040 parsePPUnknown();
1041 break;
1042 }
1043}
1044
1045void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {
1046 size_t Line = CurrentLines->size();
1047 if (CurrentLines == &PreprocessorDirectives)
1048 Line += Lines.size();
1049
1050 if (Unreachable ||
1051 (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) {
1052 PPStack.push_back({PP_Unreachable, Line});
1053 } else {
1054 PPStack.push_back({PP_Conditional, Line});
1055 }
1056}
1057
1058void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
1059 ++PPBranchLevel;
1060 assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());
1061 if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {
1062 PPLevelBranchIndex.push_back(0);
1063 PPLevelBranchCount.push_back(0);
1064 }
1065 PPChainBranchIndex.push(Unreachable ? -1 : 0);
1066 bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
1067 conditionalCompilationCondition(Unreachable || Skip);
1068}
1069
1070void UnwrappedLineParser::conditionalCompilationAlternative() {
1071 if (!PPStack.empty())
1072 PPStack.pop_back();
1073 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
1074 if (!PPChainBranchIndex.empty())
1075 ++PPChainBranchIndex.top();
1076 conditionalCompilationCondition(
1077 PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
1078 PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());
1079}
1080
1081void UnwrappedLineParser::conditionalCompilationEnd() {
1082 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
1083 if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
1084 if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel])
1085 PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;
1086 }
1087
1088 if (PPBranchLevel > -1)
1089 --PPBranchLevel;
1090 if (!PPChainBranchIndex.empty())
1091 PPChainBranchIndex.pop();
1092 if (!PPStack.empty())
1093 PPStack.pop_back();
1094}
1095
1096void UnwrappedLineParser::parsePPIf(bool IfDef) {
1097 bool IfNDef = FormatTok->is(tok::pp_ifndef);
1098 nextToken();
1099 bool Unreachable = false;
1100 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0"))
1101 Unreachable = true;
1102 if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")
1103 Unreachable = true;
1104 conditionalCompilationStart(Unreachable);
1105 FormatToken *IfCondition = FormatTok;
1106
1107
1108 bool MaybeIncludeGuard = IfNDef;
1109 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1110 for (auto &Line : Lines) {
1111 if (Line.Tokens.front().Tok->isNot(tok::comment)) {
1112 MaybeIncludeGuard = false;
1113 IncludeGuard = IG_Rejected;
1114 break;
1115 }
1116 }
1117 }
1118 --PPBranchLevel;
1119 parsePPUnknown();
1120 ++PPBranchLevel;
1121 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1122 IncludeGuard = IG_IfNdefed;
1123 IncludeGuardToken = IfCondition;
1124 }
1125}
1126
1127void UnwrappedLineParser::parsePPElse() {
1128
1129 if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
1130 IncludeGuard = IG_Rejected;
1131
1132 assert(PPBranchLevel >= -1);
1133 if (PPBranchLevel == -1)
1134 conditionalCompilationStart(true);
1135 conditionalCompilationAlternative();
1136 --PPBranchLevel;
1137 parsePPUnknown();
1138 ++PPBranchLevel;
1139}
1140
1141void UnwrappedLineParser::parsePPEndIf() {
1142 conditionalCompilationEnd();
1143 parsePPUnknown();
1144
1145
1146 if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&
1148 IncludeGuard = IG_Found;
1149 }
1150}
1151
1152void UnwrappedLineParser::parsePPDefine() {
1153 nextToken();
1154
1156 IncludeGuard = IG_Rejected;
1157 IncludeGuardToken = nullptr;
1158 parsePPUnknown();
1159 return;
1160 }
1161
1162 if (IncludeGuard == IG_IfNdefed &&
1164 IncludeGuard = IG_Defined;
1165 IncludeGuardToken = nullptr;
1166 for (auto &Line : Lines) {
1167 if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {
1168 IncludeGuard = IG_Rejected;
1169 break;
1170 }
1171 }
1172 }
1173
1174
1175
1176
1177
1178
1179 FormatTok->Tok.setKind(tok::identifier);
1181 nextToken();
1182 if (FormatTok->Tok.getKind() == tok::l_paren &&
1184 parseParens();
1185 }
1187 Line->Level += PPBranchLevel + 1;
1188 addUnwrappedLine();
1189 ++Line->Level;
1190
1191 Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
1192 assert((int)Line->PPLevel >= 0);
1193 Line->InMacroBody = true;
1194
1196 while (!eof()) {
1198 FormatTok = Tokens->getNextToken();
1199 }
1200 addUnwrappedLine();
1201 return;
1202 }
1203
1204
1205
1206
1207
1208
1209 parseFile();
1210}
1211
1212void UnwrappedLineParser::parsePPPragma() {
1213 Line->InPragmaDirective = true;
1214 parsePPUnknown();
1215}
1216
1217void UnwrappedLineParser::parsePPUnknown() {
1218 while (!eof())
1219 nextToken();
1221 Line->Level += PPBranchLevel + 1;
1222 addUnwrappedLine();
1223}
1224
1225
1226
1227
1229
1230
1231 return !Tok.isOneOf(tok::semi, tok::l_brace,
1232
1233
1234 tok::period, tok::periodstar, tok::arrow, tok::arrowstar,
1235 tok::less, tok::greater, tok::slash, tok::percent,
1236 tok::lessless, tok::greatergreater, tok::equal,
1237 tok::plusequal, tok::minusequal, tok::starequal,
1238 tok::slashequal, tok::percentequal, tok::ampequal,
1239 tok::pipeequal, tok::caretequal, tok::greatergreaterequal,
1240 tok::lesslessequal,
1241
1242
1243
1244 tok::colon,
1245
1246 tok::kw_noexcept);
1247}
1248
1251
1252 return FormatTok->is(tok::identifier) &&
1258 Keywords.kw_let, Keywords.kw_var, tok::kw_const,
1262}
1263
1267 FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
1269}
1270
1271
1272
1275 return FormatTok->isOneOf(
1276 tok::kw_return, Keywords.kw_yield,
1277
1278 tok::kw_if, tok::kw_else,
1279
1280 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
1281
1282 tok::kw_switch, tok::kw_case,
1283
1284 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,
1285
1286 tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,
1288
1289 Keywords.kw_import, tok::kw_export);
1290}
1291
1292
1294 return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
1295 tok::kw_unsigned, tok::kw_float, tok::kw_double,
1296 tok::identifier);
1297}
1298
1299
1300
1301
1302
1303
1304
1305
1308 assert(Tok);
1309 assert(Next);
1310 assert(FuncName);
1311
1312 if (FuncName->isNot(tok::identifier))
1313 return false;
1314
1316 if (!Prev || (Prev->isNot(tok::star) && (*Prev)))
1317 return false;
1318
1320 !Tok->isOneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
1321 return false;
1322 }
1323
1324 if (Next->isNot(tok::star) && !Next->Tok.getIdentifierInfo())
1325 return false;
1326
1328 if (!Tok || Tok->isNot(tok::r_paren))
1329 return false;
1330
1332 if (!Tok || Tok->isNot(tok::identifier))
1333 return false;
1334
1336}
1337
1338bool UnwrappedLineParser::parseModuleImport() {
1339 assert(FormatTok->is(Keywords.kw_import) && "'import' expected");
1340
1341 if (auto Token = Tokens->peekNextToken(true);
1343 ->isOneOf(tok::colon, tok::less, tok::string_literal)) {
1344 return false;
1345 }
1346
1347 nextToken();
1348 while (!eof()) {
1349 if (FormatTok->is(tok::colon)) {
1351 }
1352
1353 else if (FormatTok->is(tok::less)) {
1354 nextToken();
1355 while (!FormatTok->isOneOf(tok::semi, tok::greater, tok::eof)) {
1356
1357
1358 if (FormatTok->isNot(tok::comment) &&
1359 !FormatTok->TokenText.starts_with("//")) {
1361 }
1362 nextToken();
1363 }
1364 }
1365 if (FormatTok->is(tok::semi)) {
1366 nextToken();
1367 break;
1368 }
1369 nextToken();
1370 }
1371
1372 addUnwrappedLine();
1373 return true;
1374}
1375
1376
1377
1378
1379
1380
1381
1382
1383void UnwrappedLineParser::readTokenWithJavaScriptASI() {
1384 FormatToken *Previous = FormatTok;
1385 readToken();
1386 FormatToken *Next = FormatTok;
1387
1388 bool IsOnSameLine =
1389 CommentsBeforeNextToken.empty()
1390 ? Next->NewlinesBefore == 0
1391 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
1392 if (IsOnSameLine)
1393 return;
1394
1396 bool PreviousStartsTemplateExpr =
1397 Previous->is(TT_TemplateString) && Previous->TokenText.ends_with("${");
1398 if (PreviousMustBeValue || Previous->is(tok::r_paren)) {
1399
1400
1401 bool HasAt = llvm::any_of(Line->Tokens, [](UnwrappedLineNode &LineNode) {
1402 return LineNode.Tok->is(tok::at);
1403 });
1404 if (HasAt)
1405 return;
1406 }
1407 if (Next->is(tok::exclaim) && PreviousMustBeValue)
1408 return addUnwrappedLine();
1410 bool NextEndsTemplateExpr =
1411 Next->is(TT_TemplateString) && Next->TokenText.starts_with("}");
1412 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
1413 (PreviousMustBeValue ||
1414 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
1415 tok::minusminus))) {
1416 return addUnwrappedLine();
1417 }
1418 if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&
1420 return addUnwrappedLine();
1421 }
1422}
1423
1424void UnwrappedLineParser::parseStructuralElement(
1425 const FormatToken *OpeningBrace, IfStmtKind *IfKind,
1426 FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) {
1428 FormatTok->is(tok::pp_include)) {
1429 nextToken();
1430 if (FormatTok->is(tok::string_literal))
1431 nextToken();
1432 addUnwrappedLine();
1433 return;
1434 }
1435
1436 if (IsCpp) {
1437 while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
1438 }
1441 parseForOrWhileLoop(false);
1442 return;
1443 }
1445 parseForOrWhileLoop();
1446 return;
1447 }
1448 if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
1450 parseIfThenElse(IfKind, false, true);
1451 return;
1452 }
1453
1454
1455 while (true) {
1458 nextToken();
1459 } else if (FormatTok->is(tok::l_paren) &&
1460 Tokens->peekNextToken()->is(tok::star)) {
1461 parseParens();
1462 } else {
1463 break;
1464 }
1465 }
1466 }
1467
1468
1472 nextToken();
1473 } else {
1474 parseAccessSpecifier();
1475 }
1476 return;
1477 }
1479 case tok::kw_asm:
1480 nextToken();
1481 if (FormatTok->is(tok::l_brace)) {
1483 nextToken();
1484 while (FormatTok && !eof()) {
1485 if (FormatTok->is(tok::r_brace)) {
1487 nextToken();
1488 addUnwrappedLine();
1489 break;
1490 }
1492 nextToken();
1493 }
1494 }
1495 break;
1496 case tok::kw_namespace:
1497 parseNamespace();
1498 return;
1499 case tok::kw_if: {
1500 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1501
1502 break;
1503 }
1504 FormatToken *Tok = parseIfThenElse(IfKind);
1505 if (IfLeftBrace)
1506 *IfLeftBrace = Tok;
1507 return;
1508 }
1509 case tok::kw_for:
1510 case tok::kw_while:
1511 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1512
1513 break;
1514 }
1515 parseForOrWhileLoop();
1516 return;
1517 case tok::kw_do:
1518 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1519
1520 break;
1521 }
1522 parseDoWhile();
1523 if (HasDoWhile)
1524 *HasDoWhile = true;
1525 return;
1526 case tok::kw_switch:
1527 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1528
1529 break;
1530 }
1531 parseSwitch(false);
1532 return;
1533 case tok::kw_default: {
1534
1536 break;
1537 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1538
1539 break;
1540 }
1541 auto *Default = FormatTok;
1542 nextToken();
1543 if (FormatTok->is(tok::colon)) {
1545 parseLabel();
1546 return;
1547 }
1548 if (FormatTok->is(tok::arrow)) {
1550 Default->setFinalizedType(TT_SwitchExpressionLabel);
1551 parseLabel();
1552 return;
1553 }
1554
1555 break;
1556 }
1557 case tok::kw_case:
1558
1560 nextToken();
1561 return;
1562 }
1564 parseBlock();
1565 addUnwrappedLine();
1566 return;
1567 }
1568 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1569
1570 nextToken();
1571 break;
1572 }
1573 parseCaseLabel();
1574 return;
1575 case tok::kw_goto:
1576 nextToken();
1577 if (FormatTok->is(tok::kw_case))
1578 nextToken();
1579 break;
1580 case tok::kw_try:
1581 case tok::kw___try:
1582 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1583
1584 break;
1585 }
1586 parseTryCatch();
1587 return;
1588 case tok::kw_extern:
1589 nextToken();
1591
1592
1594 parseVerilogHierarchyHeader();
1595 return;
1596 }
1597 } else if (FormatTok->is(tok::string_literal)) {
1598 nextToken();
1599 if (FormatTok->is(tok::l_brace)) {
1601 addUnwrappedLine();
1602
1603
1604 unsigned AddLevels =
1609 ? 1u
1610 : 0u;
1611 parseBlock(true, AddLevels);
1612 addUnwrappedLine();
1613 return;
1614 }
1615 }
1616 break;
1617 case tok::kw_export:
1619 parseJavaScriptEs6ImportExport();
1620 return;
1621 }
1622 if (IsCpp) {
1623 nextToken();
1624 if (FormatTok->is(tok::kw_namespace)) {
1625 parseNamespace();
1626 return;
1627 }
1628 if (FormatTok->is(Keywords.kw_import) && parseModuleImport())
1629 return;
1630 }
1631 break;
1632 case tok::kw_inline:
1633 nextToken();
1634 if (FormatTok->is(tok::kw_namespace)) {
1635 parseNamespace();
1636 return;
1637 }
1638 break;
1639 case tok::identifier:
1640 if (FormatTok->is(TT_ForEachMacro)) {
1641 parseForOrWhileLoop();
1642 return;
1643 }
1644 if (FormatTok->is(TT_MacroBlockBegin)) {
1645 parseBlock(false, 1u,
1646 false);
1647 return;
1648 }
1649 if (FormatTok->is(Keywords.kw_import)) {
1651 parseJavaScriptEs6ImportExport();
1652 return;
1653 }
1655 nextToken();
1656 if (FormatTok->is(tok::kw_public))
1657 nextToken();
1658 if (FormatTok->isNot(tok::string_literal))
1659 return;
1660 nextToken();
1661 if (FormatTok->is(tok::semi))
1662 nextToken();
1663 addUnwrappedLine();
1664 return;
1665 }
1666 if (IsCpp && parseModuleImport())
1667 return;
1668 }
1671 nextToken();
1672 if (FormatTok->is(tok::colon)) {
1673 nextToken();
1674 addUnwrappedLine();
1675 return;
1676 }
1677 }
1678 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
1679 parseStatementMacro();
1680 return;
1681 }
1682 if (IsCpp && FormatTok->is(TT_NamespaceMacro)) {
1683 parseNamespace();
1684 return;
1685 }
1686
1687
1688
1689
1691 Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) {
1692 nextToken();
1693 if (!Line->InMacroBody || CurrentLines->size() > 1)
1694 Line->Tokens.begin()->Tok->MustBreakBefore = true;
1697 if (HasLabel)
1698 *HasLabel = true;
1699 return;
1700 }
1701
1702 break;
1703 default:
1704 break;
1705 }
1706
1707 for (const bool InRequiresExpression =
1708 OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
1709 TT_CompoundRequirementLBrace);
1710 !eof();) {
1712 if (auto *Next = Tokens->peekNextToken(true);
1713 Next && Next->isBinaryOperator()) {
1714 FormatTok->Tok.setKind(tok::identifier);
1715 }
1716 }
1719 case tok::at:
1720 nextToken();
1721 if (FormatTok->is(tok::l_brace)) {
1722 nextToken();
1723 parseBracedList();
1724 break;
1727 nextToken();
1728 break;
1729 }
1731 case tok::objc_public:
1732 case tok::objc_protected:
1733 case tok::objc_package:
1734 case tok::objc_private:
1735 return parseAccessSpecifier();
1736 case tok::objc_interface:
1737 case tok::objc_implementation:
1738 return parseObjCInterfaceOrImplementation();
1739 case tok::objc_protocol:
1740 if (parseObjCProtocol())
1741 return;
1742 break;
1743 case tok::objc_end:
1744 return;
1745 case tok::objc_optional:
1746 case tok::objc_required:
1747 nextToken();
1748 addUnwrappedLine();
1749 return;
1750 case tok::objc_autoreleasepool:
1751 nextToken();
1752 if (FormatTok->is(tok::l_brace)) {
1755 addUnwrappedLine();
1756 }
1757 parseBlock();
1758 }
1759 addUnwrappedLine();
1760 return;
1761 case tok::objc_synchronized:
1762 nextToken();
1763 if (FormatTok->is(tok::l_paren)) {
1764
1765 parseParens();
1766 }
1767 if (FormatTok->is(tok::l_brace)) {
1770 addUnwrappedLine();
1771 }
1772 parseBlock();
1773 }
1774 addUnwrappedLine();
1775 return;
1776 case tok::objc_try:
1777
1778
1779 parseTryCatch();
1780 return;
1781 default:
1782 break;
1783 }
1784 break;
1785 case tok::kw_requires: {
1786 if (IsCpp) {
1787 bool ParsedClause = parseRequires();
1788 if (ParsedClause)
1789 return;
1790 } else {
1791 nextToken();
1792 }
1793 break;
1794 }
1795 case tok::kw_enum:
1796
1797
1798 if (Previous && Previous->isOneOf(tok::less, tok::arrow, tok::comma)) {
1799 nextToken();
1800 break;
1801 }
1802
1803
1804
1805 if (!parseEnum())
1806 break;
1807
1808 if (!IsCpp && !Style.isVerilog()) {
1809 addUnwrappedLine();
1810 return;
1811 }
1812 break;
1813 case tok::kw_typedef:
1814 nextToken();
1819 parseEnum();
1820 }
1821 break;
1822 case tok::kw_class:
1824 parseBlock();
1825 addUnwrappedLine();
1826 return;
1827 }
1829
1830
1831 nextToken();
1832 break;
1833 }
1834 [[fallthrough]];
1835 case tok::kw_struct:
1836 case tok::kw_union:
1837 if (parseStructLike())
1838 return;
1839 break;
1840 case tok::kw_decltype:
1841 nextToken();
1842 if (FormatTok->is(tok::l_paren)) {
1843 parseParens();
1844 assert(FormatTok->Previous);
1846 tok::l_paren)) {
1847 Line->SeenDecltypeAuto = true;
1848 }
1849 }
1850 break;
1851 case tok::period:
1852 nextToken();
1853
1855 FormatTok->is(tok::kw_class)) {
1856 nextToken();
1857 }
1860
1861
1862 nextToken();
1863 }
1864 break;
1865 case tok:🚛
1866 nextToken();
1867 addUnwrappedLine();
1868 return;
1869 case tok::r_brace:
1870 addUnwrappedLine();
1871 return;
1872 case tok::l_paren: {
1873 parseParens();
1874
1875
1876 if (OpeningBrace || !IsCpp || || eof())
1877 break;
1879 Tokens->peekNextToken(true),
1881 addUnwrappedLine();
1882 return;
1883 }
1884 break;
1885 }
1886 case tok::kw_operator:
1887 nextToken();
1889 nextToken();
1890 break;
1891 case tok::caret:
1892 nextToken();
1893
1895 nextToken();
1896
1897 while (FormatTok->is(tok::star))
1898 nextToken();
1899 }
1900
1901 if (FormatTok->is(tok::l_paren))
1902 parseParens();
1903
1904 if (FormatTok->is(tok::l_brace))
1905 parseChildBlock();
1906 break;
1907 case tok::l_brace:
1908 if (InRequiresExpression)
1910 if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
1911 IsDecltypeAutoFunction = Line->SeenDecltypeAuto;
1912
1913
1914
1915
1917 Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
1918
1919
1922 addUnwrappedLine();
1923 }
1925 addUnwrappedLine();
1926 }
1929 parseBlock();
1930 IsDecltypeAutoFunction = false;
1931 addUnwrappedLine();
1932 return;
1933 }
1934
1935
1936 break;
1937 case tok::kw_try:
1938 if (Style.isJavaScript() && Line->MustBeDeclaration) {
1939
1940 nextToken();
1941 break;
1942 }
1943
1945 addUnwrappedLine();
1946 parseTryCatch();
1947 return;
1948 case tok::identifier: {
1950 Line->MustBeDeclaration) {
1951 addUnwrappedLine();
1952 parseCSharpGenericTypeConstraint();
1953 break;
1954 }
1955 if (FormatTok->is(TT_MacroBlockEnd)) {
1956 addUnwrappedLine();
1957 return;
1958 }
1959
1960
1961
1962
1963
1964 size_t TokenCount = Line->Tokens.size();
1966 (TokenCount > 1 ||
1967 (TokenCount == 1 &&
1968 Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {
1969 tryToParseJSFunction();
1970 break;
1971 }
1975
1976
1977
1978
1979 unsigned StoredPosition = Tokens->getPosition();
1980 FormatToken *Next = Tokens->getNextToken();
1981 FormatTok = Tokens->setPosition(StoredPosition);
1983 nextToken();
1984 break;
1985 }
1986 }
1987 parseRecord();
1988 addUnwrappedLine();
1989 return;
1990 }
1991
1993 if (FormatTok->is(Keywords.kw_table)) {
1994 parseVerilogTable();
1995 return;
1996 }
1999 parseBlock();
2000 addUnwrappedLine();
2001 return;
2002 }
2003 }
2004
2005 if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
2006 if (parseStructLike())
2007 return;
2008 break;
2009 }
2010
2011 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
2012 parseStatementMacro();
2013 return;
2014 }
2015
2016
2018
2019 FormatToken *PreviousToken = FormatTok;
2020 nextToken();
2021
2022
2023
2025 break;
2026
2027 auto OneTokenSoFar = [&]() {
2028 auto I = Line->Tokens.begin(), E = Line->Tokens.end();
2029 while (I != E && I->Tok->is(tok::comment))
2030 ++I;
2032 while (I != E && I->Tok->is(tok::hash))
2033 ++I;
2034 return I != E && (++I == E);
2035 };
2036 if (OneTokenSoFar()) {
2037
2038
2039 bool FunctionLike = FormatTok->is(tok::l_paren);
2040 if (FunctionLike)
2041 parseParens();
2042
2043 bool FollowedByNewline =
2044 CommentsBeforeNextToken.empty()
2046 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
2047
2048 if (FollowedByNewline &&
2049 (Text.size() >= 5 ||
2050 (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
2052 if (PreviousToken->isNot(TT_UntouchableMacroFunc))
2053 PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
2054 addUnwrappedLine();
2055 return;
2056 }
2057 }
2058 break;
2059 }
2060 case tok::equal:
2062 FormatTok->is(TT_FatArrow)) {
2063 tryToParseChildBlock();
2064 break;
2065 }
2066
2067 nextToken();
2068 if (FormatTok->is(tok::l_brace)) {
2069
2070
2071
2074
2075
2077 Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {
2079 parseBlock(false, 1u,
2080 false);
2081 addUnwrappedLine();
2082 break;
2083 }
2084 nextToken();
2085 parseBracedList();
2087 FormatTok->is(tok::less)) {
2088 nextToken();
2089 parseBracedList(true);
2090 }
2091 break;
2092 case tok::l_square:
2093 parseSquare();
2094 break;
2095 case tok::kw_new:
2096 parseNew();
2097 break;
2098 case tok::kw_switch:
2100 parseSwitch(true);
2101 else
2102 nextToken();
2103 break;
2104 case tok::kw_case:
2105
2107 nextToken();
2108 return;
2109 }
2110
2112 parseBlock();
2113 addUnwrappedLine();
2114 return;
2115 }
2116 if (Style.isJavaScript() && Line->MustBeDeclaration) {
2117
2118 nextToken();
2119 break;
2120 }
2121 parseCaseLabel();
2122 break;
2123 case tok::kw_default:
2124 nextToken();
2126 if (FormatTok->is(tok::colon)) {
2127
2128 break;
2129 }
2131
2132 parseBlock();
2133 addUnwrappedLine();
2134 return;
2135 }
2136 parseVerilogCaseLabel();
2137 return;
2138 }
2139 break;
2140 case tok::colon:
2141 nextToken();
2143 parseVerilogCaseLabel();
2144 return;
2145 }
2146 break;
2147 case tok::greater:
2148 nextToken();
2149 if (FormatTok->is(tok::l_brace))
2151 break;
2152 default:
2153 nextToken();
2154 break;
2155 }
2156 }
2157}
2158
2159bool UnwrappedLineParser::tryToParsePropertyAccessor() {
2160 assert(FormatTok->is(tok::l_brace));
2162 return false;
2163
2165 return false;
2166
2167
2168
2169
2170
2171
2172 unsigned int StoredPosition = Tokens->getPosition();
2173 FormatToken *Tok = Tokens->getNextToken();
2174
2175
2176
2177
2178 bool HasSpecialAccessor = false;
2179 bool IsTrivialPropertyAccessor = true;
2180 bool HasAttribute = false;
2181 while (!eof()) {
2182 if (const bool IsAccessorKeyword =
2184 IsAccessorKeyword || Tok->isAccessSpecifierKeyword() ||
2185 Tok->isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {
2186 if (IsAccessorKeyword)
2187 HasSpecialAccessor = true;
2188 else if (Tok->is(tok::l_square))
2189 HasAttribute = true;
2190 Tok = Tokens->getNextToken();
2191 continue;
2192 }
2193 if (Tok->isNot(tok::r_brace))
2194 IsTrivialPropertyAccessor = false;
2195 break;
2196 }
2197
2198 if (!HasSpecialAccessor || HasAttribute) {
2199 Tokens->setPosition(StoredPosition);
2200 return false;
2201 }
2202
2203
2204
2205 Tokens->setPosition(StoredPosition);
2207 addUnwrappedLine();
2208 nextToken();
2209 do {
2211 case tok::r_brace:
2212 nextToken();
2213 if (FormatTok->is(tok::equal)) {
2214 while (!eof() && FormatTok->isNot(tok::semi))
2215 nextToken();
2216 nextToken();
2217 }
2218 addUnwrappedLine();
2219 return true;
2220 case tok::l_brace:
2221 ++Line->Level;
2222 parseBlock(true);
2223 addUnwrappedLine();
2224 --Line->Level;
2225 break;
2226 case tok::equal:
2227 if (FormatTok->is(TT_FatArrow)) {
2228 ++Line->Level;
2229 do {
2230 nextToken();
2231 } while (!eof() && FormatTok->isNot(tok::semi));
2232 nextToken();
2233 addUnwrappedLine();
2234 --Line->Level;
2235 break;
2236 }
2237 nextToken();
2238 break;
2239 default:
2242 !IsTrivialPropertyAccessor) {
2243
2244 addUnwrappedLine();
2245 }
2246 nextToken();
2247 }
2248 } while (!eof());
2249
2250
2251 return true;
2252}
2253
2254bool UnwrappedLineParser::tryToParseLambda() {
2255 assert(FormatTok->is(tok::l_square));
2256 if (!IsCpp) {
2257 nextToken();
2258 return false;
2259 }
2260 FormatToken &LSquare = *FormatTok;
2261 if (!tryToParseLambdaIntroducer())
2262 return false;
2263
2264 bool SeenArrow = false;
2265 bool InTemplateParameterList = false;
2266
2267 while (FormatTok->isNot(tok::l_brace)) {
2269 nextToken();
2270 continue;
2271 }
2273 case tok::l_brace:
2274 break;
2275 case tok::l_paren:
2276 parseParens(TT_PointerOrReference);
2277 break;
2278 case tok::l_square:
2279 parseSquare();
2280 break;
2281 case tok::less:
2282 assert(FormatTok->Previous);
2283 if (FormatTok->Previous->is(tok::r_square))
2284 InTemplateParameterList = true;
2285 nextToken();
2286 break;
2287 case tok::kw_auto:
2288 case tok::kw_class:
2289 case tok::kw_struct:
2290 case tok::kw_union:
2291 case tok::kw_template:
2292 case tok::kw_typename:
2293 case tok::amp:
2294 case tok:⭐
2295 case tok::kw_const:
2296 case tok::kw_constexpr:
2297 case tok::kw_consteval:
2298 case tok::comma:
2299 case tok::greater:
2300 case tok::identifier:
2301 case tok::numeric_constant:
2302 case tok::coloncolon:
2303 case tok::kw_mutable:
2304 case tok::kw_noexcept:
2305 case tok::kw_static:
2306 nextToken();
2307 break;
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319 case tok:➕
2320 case tok:➖
2321 case tok::exclaim:
2322 case tok::tilde:
2323 case tok::slash:
2324 case tok::percent:
2325 case tok::lessless:
2326 case tok::pipe:
2327 case tok::pipepipe:
2328 case tok::ampamp:
2329 case tok::caret:
2330 case tok::equalequal:
2331 case tok::exclaimequal:
2332 case tok::greaterequal:
2333 case tok::lessequal:
2334 case tok::question:
2335 case tok::colon:
2336 case tok::ellipsis:
2337 case tok::kw_true:
2338 case tok::kw_false:
2339 if (SeenArrow || InTemplateParameterList) {
2340 nextToken();
2341 break;
2342 }
2343 return true;
2344 case tok::arrow:
2345
2346
2347
2349 SeenArrow = true;
2350 nextToken();
2351 break;
2352 case tok::kw_requires: {
2353 auto *RequiresToken = FormatTok;
2354 nextToken();
2355 parseRequiresClause(RequiresToken);
2356 break;
2357 }
2358 case tok::equal:
2359 if (!InTemplateParameterList)
2360 return true;
2361 nextToken();
2362 break;
2363 default:
2364 return true;
2365 }
2366 }
2367
2369 LSquare.setFinalizedType(TT_LambdaLSquare);
2370
2371 NestedLambdas.push_back(Line->SeenDecltypeAuto);
2372 parseChildBlock();
2373 assert(!NestedLambdas.empty());
2374 NestedLambdas.pop_back();
2375
2376 return true;
2377}
2378
2379bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
2381 const FormatToken *LeftSquare = FormatTok;
2382 nextToken();
2384 ->isOneOf(tok::kw_return, tok::kw_co_await,
2385 tok::kw_co_yield, tok::kw_co_return)) ||
2386 Previous->closesScope())) ||
2387 LeftSquare->isCppStructuredBinding(IsCpp)) {
2388 return false;
2389 }
2391 return false;
2392 if (FormatTok->is(tok::r_square)) {
2393 const FormatToken *Next = Tokens->peekNextToken(true);
2394 if (Next->is(tok::greater))
2395 return false;
2396 }
2397 parseSquare(true);
2398 return true;
2399}
2400
2401void UnwrappedLineParser::tryToParseJSFunction() {
2403 if (FormatTok->is(Keywords.kw_async))
2404 nextToken();
2405
2406 nextToken();
2407
2408
2409 if (FormatTok->is(tok::star)) {
2411 nextToken();
2412 }
2413
2414
2415 if (FormatTok->is(tok::identifier))
2416 nextToken();
2417
2418 if (FormatTok->isNot(tok::l_paren))
2419 return;
2420
2421
2422 parseParens();
2423
2424 if (FormatTok->is(tok::colon)) {
2425
2426 nextToken();
2427
2428
2429
2430 if (FormatTok->is(tok::l_brace))
2431 tryToParseBracedList();
2432 else
2433 while (!FormatTok->isOneOf(tok::l_brace, tok::semi) && !eof())
2434 nextToken();
2435 }
2436
2437 if (FormatTok->is(tok::semi))
2438 return;
2439
2440 parseChildBlock();
2441}
2442
2443bool UnwrappedLineParser::tryToParseBracedList() {
2445 calculateBraceTypes();
2448 return false;
2449 nextToken();
2450 parseBracedList();
2451 return true;
2452}
2453
2454bool UnwrappedLineParser::tryToParseChildBlock() {
2456 assert(FormatTok->is(TT_FatArrow));
2457
2458
2459
2460 nextToken();
2461 if (FormatTok->isNot(tok::l_brace))
2462 return false;
2463 parseChildBlock();
2464 return true;
2465}
2466
2467bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
2468 assert(!IsAngleBracket || !IsEnum);
2469 bool HasError = false;
2470
2471
2472
2473 do {
2474 if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
2475 tryToParseChildBlock()) {
2476 continue;
2477 }
2480 tryToParseJSFunction();
2481 continue;
2482 }
2483 if (FormatTok->is(tok::l_brace)) {
2484
2485 if (tryToParseBracedList())
2486 continue;
2487 parseChildBlock();
2488 }
2489 }
2490 if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
2491 if (IsEnum) {
2494 addUnwrappedLine();
2495 }
2496 nextToken();
2497 return !HasError;
2498 }
2500 case tok::l_square:
2502 parseSquare();
2503 else
2504 tryToParseLambda();
2505 break;
2506 case tok::l_paren:
2507 parseParens();
2508
2509
2511 if (FormatTok->is(tok::l_brace))
2512 parseChildBlock();
2513 break;
2514 }
2515 break;
2516 case tok::l_brace:
2517
2518
2520 if (!IsAngleBracket) {
2521 auto *Prev = FormatTok->Previous;
2522 if (Prev && Prev->is(tok::greater))
2524 }
2525 nextToken();
2526 parseBracedList();
2527 break;
2528 case tok::less:
2529 nextToken();
2530 if (IsAngleBracket)
2531 parseBracedList(true);
2532 break;
2533 case tok:🚛
2534
2535
2536
2537
2539 nextToken();
2540 break;
2541 }
2542 HasError = true;
2543 if (!IsEnum)
2544 return false;
2545 nextToken();
2546 break;
2547 case tok::comma:
2548 nextToken();
2550 addUnwrappedLine();
2551 break;
2552 default:
2553 nextToken();
2554 break;
2555 }
2556 } while (!eof());
2557 return false;
2558}
2559
2560
2561
2562
2563
2564
2565bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
2566 assert(FormatTok->is(tok::l_paren) && "'(' expected.");
2567 auto *LeftParen = FormatTok;
2568 bool SeenComma = false;
2569 bool SeenEqual = false;
2570 bool MightBeFoldExpr = false;
2571 const bool MightBeStmtExpr = Tokens->peekNextToken()->is(tok::l_brace);
2572 nextToken();
2573 do {
2575 case tok::l_paren:
2576 if (parseParens(AmpAmpTokenType))
2577 SeenEqual = true;
2579 parseChildBlock();
2580 break;
2581 case tok::r_paren: {
2582 auto *Prev = LeftParen->Previous;
2583 if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody &&
2585 const auto *Next = Tokens->peekNextToken();
2586 const bool DoubleParens =
2587 Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren);
2588 const bool CommaSeparated =
2589 !DoubleParens && Prev && Prev->isOneOf(tok::l_paren, tok::comma) &&
2590 Next && Next->isOneOf(tok::comma, tok::r_paren);
2591 const auto *PrevPrev = Prev ? Prev->getPreviousNonComment() : nullptr;
2592 const bool Excluded =
2593 PrevPrev &&
2594 (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2595 SeenComma ||
2596 (SeenEqual &&
2597 (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2598 PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2599 const bool ReturnParens =
2601 ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2602 (!NestedLambdas.empty() && !NestedLambdas.back())) &&
2603 Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next &&
2604 Next->is(tok::semi);
2605 if ((DoubleParens && !Excluded) || (CommaSeparated && !SeenComma) ||
2606 ReturnParens) {
2607 LeftParen->Optional = true;
2609 }
2610 }
2611 if (Prev) {
2612 if (Prev->is(TT_TypenameMacro)) {
2613 LeftParen->setFinalizedType(TT_TypeDeclarationParen);
2615 } else if (Prev->is(tok::greater) && FormatTok->Previous == LeftParen) {
2616 Prev->setFinalizedType(TT_TemplateCloser);
2617 }
2618 }
2619 nextToken();
2620 return SeenEqual;
2621 }
2622 case tok::r_brace:
2623
2624 return SeenEqual;
2625 case tok::l_square:
2626 tryToParseLambda();
2627 break;
2628 case tok::l_brace:
2629 if (!tryToParseBracedList())
2630 parseChildBlock();
2631 break;
2632 case tok::at:
2633 nextToken();
2634 if (FormatTok->is(tok::l_brace)) {
2635 nextToken();
2636 parseBracedList();
2637 }
2638 break;
2639 case tok::comma:
2640 SeenComma = true;
2641 nextToken();
2642 break;
2643 case tok::ellipsis:
2644 MightBeFoldExpr = true;
2645 nextToken();
2646 break;
2647 case tok::equal:
2648 SeenEqual = true;
2649 if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
2650 tryToParseChildBlock();
2651 else
2652 nextToken();
2653 break;
2654 case tok::kw_class:
2656 parseRecord(true);
2657 else
2658 nextToken();
2659 break;
2660 case tok::identifier:
2662 tryToParseJSFunction();
2663 else
2664 nextToken();
2665 break;
2666 case tok::kw_switch:
2668 parseSwitch(true);
2669 else
2670 nextToken();
2671 break;
2672 case tok::kw_requires: {
2673 auto RequiresToken = FormatTok;
2674 nextToken();
2675 parseRequiresExpression(RequiresToken);
2676 break;
2677 }
2678 case tok::ampamp:
2679 if (AmpAmpTokenType != TT_Unknown)
2681 [[fallthrough]];
2682 default:
2683 nextToken();
2684 break;
2685 }
2686 } while (!eof());
2687 return SeenEqual;
2688}
2689
2690void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
2691 if (!LambdaIntroducer) {
2692 assert(FormatTok->is(tok::l_square) && "'[' expected.");
2693 if (tryToParseLambda())
2694 return;
2695 }
2696 do {
2698 case tok::l_paren:
2699 parseParens();
2700 break;
2701 case tok::r_square:
2702 nextToken();
2703 return;
2704 case tok::r_brace:
2705
2706 return;
2707 case tok::l_square:
2708 parseSquare();
2709 break;
2710 case tok::l_brace: {
2711 if (!tryToParseBracedList())
2712 parseChildBlock();
2713 break;
2714 }
2715 case tok::at:
2716 case tok::colon:
2717 nextToken();
2718 if (FormatTok->is(tok::l_brace)) {
2719 nextToken();
2720 parseBracedList();
2721 }
2722 break;
2723 default:
2724 nextToken();
2725 break;
2726 }
2727 } while (!eof());
2728}
2729
2730void UnwrappedLineParser::keepAncestorBraces() {
2732 return;
2733
2734 const int MaxNestingLevels = 2;
2735 const int Size = NestedTooDeep.size();
2736 if (Size >= MaxNestingLevels)
2737 NestedTooDeep[Size - MaxNestingLevels] = true;
2738 NestedTooDeep.push_back(false);
2739}
2740
2742 for (const auto &Token : llvm::reverse(Line.Tokens))
2744 return Token.Tok;
2745
2746 return nullptr;
2747}
2748
2749void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {
2750 FormatToken *Tok = nullptr;
2751
2752 if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() &&
2753 PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
2756 : Line->Tokens.back().Tok;
2757 assert(Tok);
2758 if (Tok->BraceCount < 0) {
2759 assert(Tok->BraceCount == -1);
2760 Tok = nullptr;
2761 } else {
2762 Tok->BraceCount = -1;
2763 }
2764 }
2765
2766 addUnwrappedLine();
2767 ++Line->Level;
2768 ++Line->UnbracedBodyLevel;
2769 parseStructuralElement();
2770 --Line->UnbracedBodyLevel;
2771
2772 if (Tok) {
2773 assert(!Line->InPPDirective);
2774 Tok = nullptr;
2775 for (const auto &L : llvm::reverse(*CurrentLines)) {
2777 Tok = L.Tokens.back().Tok;
2778 break;
2779 }
2780 }
2781 assert(Tok);
2782 ++Tok->BraceCount;
2783 }
2784
2785 if (CheckEOF && eof())
2786 addUnwrappedLine();
2787
2788 --Line->Level;
2789}
2790
2792 if (!LeftBrace)
2793 return;
2794
2795 assert(LeftBrace->is(tok::l_brace));
2796
2798 if (!RightBrace) {
2799 assert(!LeftBrace->Optional);
2800 return;
2801 }
2802
2803 assert(RightBrace->is(tok::r_brace));
2806
2808 RightBrace->Optional = true;
2809}
2810
2811void UnwrappedLineParser::handleAttributes() {
2812
2814 nextToken();
2815 else if (FormatTok->is(tok::l_square))
2816 handleCppAttributes();
2817}
2818
2819bool UnwrappedLineParser::handleCppAttributes() {
2820
2821 assert(FormatTok->is(tok::l_square));
2822 if (!tryToParseSimpleAttribute())
2823 return false;
2824 parseSquare();
2825 return true;
2826}
2827
2828
2829bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const {
2830
2831
2833 : Tok.is(tok::l_brace);
2834}
2835
2836FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
2837 bool KeepBraces,
2838 bool IsVerilogAssert) {
2839 assert((FormatTok->is(tok::kw_if) ||
2843 "'if' expected");
2844 nextToken();
2845
2846 if (IsVerilogAssert) {
2847
2849 nextToken();
2850 if (FormatTok->is(tok::numeric_constant))
2851 nextToken();
2854 nextToken();
2855 }
2856 }
2857
2858
2860 while (!eof() && FormatTok->isNot(Keywords.kw_then)) {
2861
2862 nextToken();
2863 }
2864 }
2865
2866
2867 if (FormatTok->is(tok::exclaim))
2868 nextToken();
2869
2870 bool KeepIfBraces = true;
2871 if (FormatTok->is(tok::kw_consteval)) {
2872 nextToken();
2873 } else {
2875 if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
2876 nextToken();
2877 if (FormatTok->is(tok::l_paren)) {
2879 parseParens();
2880 }
2881 }
2882 handleAttributes();
2883
2884 if (IsVerilogAssert && FormatTok->is(tok::semi)) {
2885 nextToken();
2886 addUnwrappedLine();
2887 return nullptr;
2888 }
2889
2890 bool NeedsUnwrappedLine = false;
2891 keepAncestorBraces();
2892
2893 FormatToken *IfLeftBrace = nullptr;
2894 IfStmtKind IfBlockKind = IfStmtKind::NotIf;
2895
2896 if (isBlockBegin(*FormatTok)) {
2898 IfLeftBrace = FormatTok;
2900 parseBlock(false, 1u,
2901 true, KeepIfBraces, &IfBlockKind);
2902 setPreviousRBraceType(TT_ControlStatementRBrace);
2904 addUnwrappedLine();
2905 else
2906 NeedsUnwrappedLine = true;
2907 } else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {
2908 addUnwrappedLine();
2909 } else {
2910 parseUnbracedBody();
2911 }
2912
2914 assert(!NestedTooDeep.empty());
2915 KeepIfBraces = KeepIfBraces ||
2916 (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
2917 NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
2918 IfBlockKind == IfStmtKind::IfElseIf;
2919 }
2920
2921 bool KeepElseBraces = KeepIfBraces;
2922 FormatToken *ElseLeftBrace = nullptr;
2923 IfStmtKind Kind = IfStmtKind::IfOnly;
2924
2925 if (FormatTok->is(tok::kw_else)) {
2927 NestedTooDeep.back() = false;
2928 Kind = IfStmtKind::IfElse;
2929 }
2930 nextToken();
2931 handleAttributes();
2932 if (isBlockBegin(*FormatTok)) {
2933 const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
2935 ElseLeftBrace = FormatTok;
2937 IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
2938 FormatToken *IfLBrace =
2939 parseBlock(false, 1u,
2940 true, KeepElseBraces, &ElseBlockKind);
2941 setPreviousRBraceType(TT_ElseRBrace);
2942 if (FormatTok->is(tok::kw_else)) {
2943 KeepElseBraces = KeepElseBraces ||
2944 ElseBlockKind == IfStmtKind::IfOnly ||
2945 ElseBlockKind == IfStmtKind::IfElseIf;
2946 } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
2947 KeepElseBraces = true;
2948 assert(ElseLeftBrace->MatchingParen);
2950 }
2951 addUnwrappedLine();
2952 } else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {
2953 const FormatToken *Previous = Tokens->getPreviousToken();
2955 const bool IsPrecededByComment = Previous->is(tok::comment);
2956 if (IsPrecededByComment) {
2957 addUnwrappedLine();
2958 ++Line->Level;
2959 }
2960 bool TooDeep = true;
2962 Kind = IfStmtKind::IfElseIf;
2963 TooDeep = NestedTooDeep.pop_back_val();
2964 }
2965 ElseLeftBrace = parseIfThenElse(nullptr, KeepIfBraces);
2967 NestedTooDeep.push_back(TooDeep);
2968 if (IsPrecededByComment)
2969 --Line->Level;
2970 } else {
2971 parseUnbracedBody(true);
2972 }
2973 } else {
2974 KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
2975 if (NeedsUnwrappedLine)
2976 addUnwrappedLine();
2977 }
2978
2980 return nullptr;
2981
2982 assert(!NestedTooDeep.empty());
2983 KeepElseBraces = KeepElseBraces ||
2984 (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
2985 NestedTooDeep.back();
2986
2987 NestedTooDeep.pop_back();
2988
2989 if (!KeepIfBraces && !KeepElseBraces) {
2992 } else if (IfLeftBrace) {
2993 FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
2994 if (IfRightBrace) {
2995 assert(IfRightBrace->MatchingParen == IfLeftBrace);
2996 assert(!IfLeftBrace->Optional);
2997 assert(!IfRightBrace->Optional);
2998 IfLeftBrace->MatchingParen = nullptr;
2999 IfRightBrace->MatchingParen = nullptr;
3000 }
3001 }
3002
3003 if (IfKind)
3004 *IfKind = Kind;
3005
3006 return IfLeftBrace;
3007}
3008
3009void UnwrappedLineParser::parseTryCatch() {
3010 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
3011 nextToken();
3012 bool NeedsUnwrappedLine = false;
3013 bool HasCtorInitializer = false;
3014 if (FormatTok->is(tok::colon)) {
3015 auto *Colon = FormatTok;
3016
3017 nextToken();
3018 if (FormatTok->is(tok::identifier)) {
3019 HasCtorInitializer = true;
3020 Colon->setFinalizedType(TT_CtorInitializerColon);
3021 }
3022
3023
3024
3025 while (FormatTok->is(tok::comma))
3026 nextToken();
3027
3028 while (FormatTok->is(tok::identifier)) {
3029 nextToken();
3030 if (FormatTok->is(tok::l_paren)) {
3031 parseParens();
3032 } else if (FormatTok->is(tok::l_brace)) {
3033 nextToken();
3034 parseBracedList();
3035 }
3036
3037
3038
3039 while (FormatTok->is(tok::comma))
3040 nextToken();
3041 }
3042 }
3043
3045 parseParens();
3046
3047 keepAncestorBraces();
3048
3049 if (FormatTok->is(tok::l_brace)) {
3050 if (HasCtorInitializer)
3053 parseBlock();
3055 addUnwrappedLine();
3056 else
3057 NeedsUnwrappedLine = true;
3058 } else if (FormatTok->isNot(tok::kw_catch)) {
3059
3060
3061
3062 addUnwrappedLine();
3063 ++Line->Level;
3064 parseStructuralElement();
3065 --Line->Level;
3066 }
3067 while (true) {
3068 if (FormatTok->is(tok::at))
3069 nextToken();
3071 tok::kw___finally) ||
3076 break;
3077 }
3078 nextToken();
3079 while (FormatTok->isNot(tok::l_brace)) {
3080 if (FormatTok->is(tok::l_paren)) {
3081 parseParens();
3082 continue;
3083 }
3084 if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof)) {
3086 NestedTooDeep.pop_back();
3087 return;
3088 }
3089 nextToken();
3090 }
3091 NeedsUnwrappedLine = false;
3092 Line->MustBeDeclaration = false;
3094 parseBlock();
3096 addUnwrappedLine();
3097 else
3098 NeedsUnwrappedLine = true;
3099 }
3100
3102 NestedTooDeep.pop_back();
3103
3104 if (NeedsUnwrappedLine)
3105 addUnwrappedLine();
3106}
3107
3108void UnwrappedLineParser::parseNamespace() {
3109 assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
3110 "'namespace' expected");
3111
3112 const FormatToken &InitialToken = *FormatTok;
3113 nextToken();
3114 if (InitialToken.is(TT_NamespaceMacro)) {
3115 parseParens();
3116 } else {
3117 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
3118 tok::l_square, tok::period, tok::l_paren) ||
3119 (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
3120 if (FormatTok->is(tok::l_square))
3121 parseSquare();
3122 else if (FormatTok->is(tok::l_paren))
3123 parseParens();
3124 else
3125 nextToken();
3126 }
3127 }
3128 if (FormatTok->is(tok::l_brace)) {
3130
3132 addUnwrappedLine();
3133
3134 unsigned AddLevels =
3137 DeclarationScopeStack.size() > 1)
3138 ? 1u
3139 : 0u;
3140 bool ManageWhitesmithsBraces =
3141 AddLevels == 0u &&
3143
3144
3145
3146 if (ManageWhitesmithsBraces)
3147 ++Line->Level;
3148
3149
3150
3151 parseBlock(true, AddLevels, true,
3152 true, nullptr,
3153 ManageWhitesmithsBraces);
3154
3155 addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
3156
3157 if (ManageWhitesmithsBraces)
3158 --Line->Level;
3159 }
3160
3161}
3162
3163void UnwrappedLineParser::parseNew() {
3164 assert(FormatTok->is(tok::kw_new) && "'new' expected");
3165 nextToken();
3166
3168 do {
3169
3170 if (FormatTok->is(tok::l_paren))
3171 parseParens();
3172
3173
3174 if (FormatTok->is(tok::l_brace))
3175 parseBracedList();
3176
3177 if (FormatTok->isOneOf(tok::semi, tok::comma))
3178 return;
3179
3180 nextToken();
3181 } while (!eof());
3182 }
3183
3185 return;
3186
3187
3188 do {
3189
3190 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
3191 return;
3192
3193
3194 if (FormatTok->is(tok::l_paren)) {
3195 parseParens();
3196
3197
3198 if (FormatTok->is(tok::l_brace))
3199 parseChildBlock();
3200 return;
3201 }
3202 nextToken();
3203 } while (!eof());
3204}
3205
3206void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {
3207 keepAncestorBraces();
3208
3209 if (isBlockBegin(*FormatTok)) {
3211 FormatToken *LeftBrace = FormatTok;
3213 parseBlock(false, 1u,
3214 true, KeepBraces);
3215 setPreviousRBraceType(TT_ControlStatementRBrace);
3216 if (!KeepBraces) {
3217 assert(!NestedTooDeep.empty());
3218 if (!NestedTooDeep.back())
3220 }
3221 if (WrapRightBrace)
3222 addUnwrappedLine();
3223 } else {
3224 parseUnbracedBody();
3225 }
3226
3227 if (!KeepBraces)
3228 NestedTooDeep.pop_back();
3229}
3230
3231void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) {
3232 assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||
3239 "'for', 'while' or foreach macro expected");
3241 !FormatTok->isOneOf(tok::kw_for, tok::kw_while);
3242
3243 nextToken();
3244
3246 nextToken();
3247 if (IsCpp && FormatTok->is(tok::kw_co_await))
3248 nextToken();
3249 if (HasParens && FormatTok->is(tok::l_paren)) {
3250
3251
3252
3255 parseParens();
3256 }
3257
3259
3260 parseVerilogSensitivityList();
3262 Tokens->getPreviousToken()->is(tok::r_paren)) {
3263 nextToken();
3264 addUnwrappedLine();
3265 return;
3266 }
3267
3268 handleAttributes();
3269 parseLoopBody(KeepBraces, true);
3270}
3271
3272void UnwrappedLineParser::parseDoWhile() {
3273 assert(FormatTok->is(tok::kw_do) && "'do' expected");
3274 nextToken();
3275
3277
3278
3279 if (FormatTok->isNot(tok::kw_while)) {
3280 addUnwrappedLine();
3281 return;
3282 }
3283
3285
3286
3287
3289 ++Line->Level;
3290
3291 nextToken();
3292 parseStructuralElement();
3293}
3294
3295void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
3296 nextToken();
3297 unsigned OldLineLevel = Line->Level;
3298
3299 if (LeftAlignLabel)
3300 Line->Level = 0;
3301 else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
3302 --Line->Level;
3303
3304 if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
3305 FormatTok->is(tok::l_brace)) {
3306
3310 parseBlock();
3311 if (FormatTok->is(tok::kw_break)) {
3314 addUnwrappedLine();
3317 ++Line->Level;
3318 }
3319 }
3320 parseStructuralElement();
3321 }
3322 addUnwrappedLine();
3323 } else {
3324 if (FormatTok->is(tok::semi))
3325 nextToken();
3326 addUnwrappedLine();
3327 }
3328 Line->Level = OldLineLevel;
3329 if (FormatTok->isNot(tok::l_brace)) {
3330 parseStructuralElement();
3331 addUnwrappedLine();
3332 }
3333}
3334
3335void UnwrappedLineParser::parseCaseLabel() {
3336 assert(FormatTok->is(tok::kw_case) && "'case' expected");
3337 auto *Case = FormatTok;
3338
3339
3340 do {
3341 nextToken();
3342 if (FormatTok->is(tok::colon)) {
3344 break;
3345 }
3348 Case->setFinalizedType(TT_SwitchExpressionLabel);
3349 break;
3350 }
3351 } while (!eof());
3352 parseLabel();
3353}
3354
3355void UnwrappedLineParser::parseSwitch(bool IsExpr) {
3356 assert(FormatTok->is(tok::kw_switch) && "'switch' expected");
3357 nextToken();
3358 if (FormatTok->is(tok::l_paren))
3359 parseParens();
3360
3361 keepAncestorBraces();
3362
3363 if (FormatTok->is(tok::l_brace)) {
3365 FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
3366 : TT_ControlStatementLBrace);
3367 if (IsExpr)
3368 parseChildBlock();
3369 else
3370 parseBlock();
3371 setPreviousRBraceType(TT_ControlStatementRBrace);
3372 if (!IsExpr)
3373 addUnwrappedLine();
3374 } else {
3375 addUnwrappedLine();
3376 ++Line->Level;
3377 parseStructuralElement();
3378 --Line->Level;
3379 }
3380
3382 NestedTooDeep.pop_back();
3383}
3384
3385
3387 switch (Kind) {
3388 case tok::ampamp:
3389 case tok::ampequal:
3390 case tok::arrow:
3391 case tok::caret:
3392 case tok::caretequal:
3393 case tok::comma:
3394 case tok::ellipsis:
3395 case tok::equal:
3396 case tok::equalequal:
3397 case tok::exclaim:
3398 case tok::exclaimequal:
3399 case tok::greater:
3400 case tok::greaterequal:
3401 case tok::greatergreater:
3402 case tok::greatergreaterequal:
3403 case tok::l_paren:
3404 case tok::l_square:
3405 case tok::less:
3406 case tok::lessequal:
3407 case tok::lessless:
3408 case tok::lesslessequal:
3409 case tok:➖
3410 case tok::minusequal:
3411 case tok::minusminus:
3412 case tok::percent:
3413 case tok::percentequal:
3414 case tok::period:
3415 case tok::pipe:
3416 case tok::pipeequal:
3417 case tok::pipepipe:
3418 case tok:➕
3419 case tok::plusequal:
3420 case tok::plusplus:
3421 case tok::question:
3422 case tok::r_brace:
3423 case tok::r_paren:
3424 case tok::r_square:
3425 case tok:🚛
3426 case tok::slash:
3427 case tok::slashequal:
3428 case tok:⭐
3429 case tok::starequal:
3430 return true;
3431 default:
3432 return false;
3433 }
3434}
3435
3436void UnwrappedLineParser::parseAccessSpecifier() {
3437 FormatToken *AccessSpecifierCandidate = FormatTok;
3438 nextToken();
3439
3441 nextToken();
3442
3443 if (FormatTok->is(tok::colon)) {
3444 nextToken();
3445 addUnwrappedLine();
3446 } else if (FormatTok->isNot(tok::coloncolon) &&
3448
3449 addUnwrappedLine();
3450 } else if (AccessSpecifierCandidate) {
3451
3452 AccessSpecifierCandidate->Tok.setKind(tok::identifier);
3453 }
3454}
3455
3456
3457
3458
3459bool UnwrappedLineParser::parseRequires() {
3460 assert(FormatTok->is(tok::kw_requires) && "'requires' expected");
3461 auto RequiresToken = FormatTok;
3462
3463
3464
3465 nextToken();
3466
3468 case tok::l_brace:
3469
3470 parseRequiresExpression(RequiresToken);
3471 return false;
3472 case tok::l_paren:
3473
3474 break;
3475 default:
3476
3477 parseRequiresClause(RequiresToken);
3478 return true;
3479 }
3480
3481
3482
3483
3484
3485
3486
3487
3488 auto *PreviousNonComment = RequiresToken->getPreviousNonComment();
3489
3490 if (!PreviousNonComment ||
3491 PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
3492
3493
3494 parseRequiresClause(RequiresToken);
3495 return true;
3496 }
3497
3498 switch (PreviousNonComment->Tok.getKind()) {
3499 case tok::greater:
3500 case tok::r_paren:
3501 case tok::kw_noexcept:
3502 case tok::kw_const:
3503 case tok::amp:
3504
3505 parseRequiresClause(RequiresToken);
3506 return true;
3507 case tok::ampamp: {
3508
3509
3510
3511
3512
3513
3514 auto PrevPrev = PreviousNonComment->getPreviousNonComment();
3515 if (PrevPrev && PrevPrev->is(tok::kw_const)) {
3516 parseRequiresClause(RequiresToken);
3517 return true;
3518 }
3519 break;
3520 }
3521 default:
3522 if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
3523
3524 parseRequiresClause(RequiresToken);
3525 return true;
3526 }
3527
3528 parseRequiresExpression(RequiresToken);
3529 return false;
3530 }
3531
3532
3533
3534
3535
3536
3537
3538 unsigned StoredPosition = Tokens->getPosition();
3539 FormatToken *NextToken = Tokens->getNextToken();
3540 int Lookahead = 0;
3541 auto PeekNext = [&Lookahead, &NextToken, this] {
3542 ++Lookahead;
3543 NextToken = Tokens->getNextToken();
3544 };
3545
3546 bool FoundType = false;
3547 bool LastWasColonColon = false;
3548 int OpenAngles = 0;
3549
3550 for (; Lookahead < 50; PeekNext()) {
3551 switch (NextToken->Tok.getKind()) {
3552 case tok::kw_volatile:
3553 case tok::kw_const:
3554 case tok::comma:
3555 if (OpenAngles == 0) {
3556 FormatTok = Tokens->setPosition(StoredPosition);
3557 parseRequiresExpression(RequiresToken);
3558 return false;
3559 }
3560 break;
3561 case tok::eof:
3562
3563 Lookahead = 50;
3564 break;
3565 case tok::coloncolon:
3566 LastWasColonColon = true;
3567 break;
3568 case tok::kw_decltype:
3569 case tok::identifier:
3570 if (FoundType && !LastWasColonColon && OpenAngles == 0) {
3571 FormatTok = Tokens->setPosition(StoredPosition);
3572 parseRequiresExpression(RequiresToken);
3573 return false;
3574 }
3575 FoundType = true;
3576 LastWasColonColon = false;
3577 break;
3578 case tok::less:
3579 ++OpenAngles;
3580 break;
3581 case tok::greater:
3582 --OpenAngles;
3583 break;
3584 default:
3585 if (NextToken->isTypeName(LangOpts)) {
3586 FormatTok = Tokens->setPosition(StoredPosition);
3587 parseRequiresExpression(RequiresToken);
3588 return false;
3589 }
3590 break;
3591 }
3592 }
3593
3594 FormatTok = Tokens->setPosition(StoredPosition);
3595 parseRequiresClause(RequiresToken);
3596 return true;
3597}
3598
3599
3600
3601
3602
3603
3604
3605
3606void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) {
3608 assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");
3609
3610
3611
3612
3613 bool InRequiresExpression =
3614 !RequiresToken->Previous ||
3615 RequiresToken->Previous->is(TT_RequiresExpressionLBrace);
3616
3617 RequiresToken->setFinalizedType(InRequiresExpression
3618 ? TT_RequiresClauseInARequiresExpression
3619 : TT_RequiresClause);
3620
3621
3622
3623 parseConstraintExpression();
3624
3625 if (!InRequiresExpression)
3627}
3628
3629
3630
3631
3632
3633
3634
3635
3636void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) {
3638 assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");
3639
3640 RequiresToken->setFinalizedType(TT_RequiresExpression);
3641
3642 if (FormatTok->is(tok::l_paren)) {
3644 parseParens();
3645 }
3646
3647 if (FormatTok->is(tok::l_brace)) {
3649 parseChildBlock();
3650 }
3651}
3652
3653
3654
3655
3656
3657void UnwrappedLineParser::parseConstraintExpression() {
3658
3659
3660
3661
3662
3663
3664 bool LambdaNextTimeAllowed = true;
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674 bool TopLevelParensAllowed = true;
3675
3676 do {
3677 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false);
3678
3680 case tok::kw_requires: {
3681 auto RequiresToken = FormatTok;
3682 nextToken();
3683 parseRequiresExpression(RequiresToken);
3684 break;
3685 }
3686
3687 case tok::l_paren:
3688 if (!TopLevelParensAllowed)
3689 return;
3690 parseParens(TT_BinaryOperator);
3691 TopLevelParensAllowed = false;
3692 break;
3693
3694 case tok::l_square:
3695 if (!LambdaThisTimeAllowed || !tryToParseLambda())
3696 return;
3697 break;
3698
3699 case tok::kw_const:
3700 case tok:🚛
3701 case tok::kw_class:
3702 case tok::kw_struct:
3703 case tok::kw_union:
3704 return;
3705
3706 case tok::l_brace:
3707
3708 return;
3709
3710 case tok::ampamp:
3711 case tok::pipepipe:
3713 nextToken();
3714 LambdaNextTimeAllowed = true;
3715 TopLevelParensAllowed = true;
3716 break;
3717
3718 case tok::comma:
3719 case tok::comment:
3720 LambdaNextTimeAllowed = LambdaThisTimeAllowed;
3721 nextToken();
3722 break;
3723
3724 case tok::kw_sizeof:
3725 case tok::greater:
3726 case tok::greaterequal:
3727 case tok::greatergreater:
3728 case tok::less:
3729 case tok::lessequal:
3730 case tok::lessless:
3731 case tok::equalequal:
3732 case tok::exclaim:
3733 case tok::exclaimequal:
3734 case tok:➕
3735 case tok:➖
3736 case tok:⭐
3737 case tok::slash:
3738 LambdaNextTimeAllowed = true;
3739 TopLevelParensAllowed = true;
3740
3741 nextToken();
3742 break;
3743
3744 case tok::numeric_constant:
3745 case tok::coloncolon:
3746 case tok::kw_true:
3747 case tok::kw_false:
3748 TopLevelParensAllowed = false;
3749
3750 nextToken();
3751 break;
3752
3753 case tok::kw_static_cast:
3754 case tok::kw_const_cast:
3755 case tok::kw_reinterpret_cast:
3756 case tok::kw_dynamic_cast:
3757 nextToken();
3758 if (FormatTok->isNot(tok::less))
3759 return;
3760
3761 nextToken();
3762 parseBracedList(true);
3763 break;
3764
3765 default:
3767
3768
3769 return;
3770 }
3771
3772
3773
3774
3775
3776 assert(FormatTok->Previous);
3778 case tok::coloncolon:
3779 case tok::ampamp:
3780 case tok::pipepipe:
3781 case tok::exclaim:
3782 case tok::kw_requires:
3783 case tok::equal:
3784 break;
3785 default:
3786 return;
3787 }
3788
3789
3790 nextToken();
3791 if (FormatTok->is(tok::less)) {
3792 nextToken();
3793 parseBracedList(true);
3794 }
3795 TopLevelParensAllowed = false;
3796 break;
3797 }
3798 } while (!eof());
3799}
3800
3801bool UnwrappedLineParser::parseEnum() {
3802 const FormatToken &InitialToken = *FormatTok;
3803
3804
3805 if (FormatTok->is(tok::kw_enum))
3806 nextToken();
3807
3808
3809
3810
3811 if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
3812 return false;
3813
3814
3816 return false;
3817
3818 if (IsCpp) {
3819
3820 if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
3821 nextToken();
3822 while (FormatTok->is(tok::l_square))
3823 if (!handleCppAttributes())
3824 return false;
3825 }
3826
3828 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
3829 tok::greater, tok::comma, tok::question,
3830 tok::l_square)) {
3833 nextToken();
3834
3835 while (FormatTok->is(tok::l_square))
3836 parseSquare();
3837 } else {
3838 nextToken();
3839 }
3840
3841 if (FormatTok->is(tok::l_paren))
3842 parseParens();
3843 if (FormatTok->is(tok::identifier)) {
3844 nextToken();
3845
3846
3847 if (IsCpp && FormatTok->is(tok::identifier))
3848 return false;
3849 }
3850 }
3851
3852
3853 if (FormatTok->isNot(tok::l_brace))
3854 return true;
3857
3859
3860 parseJavaEnumBody();
3861 return true;
3862 }
3864 parseBlock(true);
3865 return true;
3866 }
3867
3870 addUnwrappedLine();
3871 }
3872
3873 nextToken();
3875 addUnwrappedLine();
3876 Line->Level += 1;
3877 }
3878 bool HasError = !parseBracedList(false, true);
3880 Line->Level -= 1;
3881 if (HasError) {
3882 if (FormatTok->is(tok::semi))
3883 nextToken();
3884 addUnwrappedLine();
3885 }
3886 setPreviousRBraceType(TT_EnumRBrace);
3887 return true;
3888
3889
3890
3891
3892}
3893
3894bool UnwrappedLineParser::parseStructLike() {
3895
3896
3897 parseRecord();
3898
3901 if (FormatTok->is(tok::semi))
3902 nextToken();
3903 addUnwrappedLine();
3904 return true;
3905 }
3906 return false;
3907}
3908
3909namespace {
3910
3911
3912class ScopedTokenPosition {
3913 unsigned StoredPosition;
3914 FormatTokenSource *Tokens;
3915
3916public:
3917 ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
3918 assert(Tokens && "Tokens expected to not be null");
3919 StoredPosition = Tokens->getPosition();
3920 }
3921
3922 ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
3923};
3924}
3925
3926
3927
3928bool UnwrappedLineParser::tryToParseSimpleAttribute() {
3929 ScopedTokenPosition AutoPosition(Tokens);
3930 FormatToken *Tok = Tokens->getNextToken();
3931
3932 if (Tok->isNot(tok::l_square))
3933 return false;
3934
3935
3936 while (Tok->isNot(tok::eof)) {
3937 if (Tok->is(tok::r_square))
3938 break;
3939 Tok = Tokens->getNextToken();
3940 }
3941 if (Tok->is(tok::eof))
3942 return false;
3943 Tok = Tokens->getNextToken();
3944 if (Tok->isNot(tok::r_square))
3945 return false;
3946 Tok = Tokens->getNextToken();
3947 if (Tok->is(tok::semi))
3948 return false;
3949 return true;
3950}
3951
3952void UnwrappedLineParser::parseJavaEnumBody() {
3953 assert(FormatTok->is(tok::l_brace));
3954 const FormatToken *OpeningBrace = FormatTok;
3955
3956
3957
3958
3959 unsigned StoredPosition = Tokens->getPosition();
3960 bool IsSimple = true;
3961 FormatToken *Tok = Tokens->getNextToken();
3962 while (Tok->isNot(tok::eof)) {
3963 if (Tok->is(tok::r_brace))
3964 break;
3965 if (Tok->isOneOf(tok::l_brace, tok::semi)) {
3966 IsSimple = false;
3967 break;
3968 }
3969
3970
3971 Tok = Tokens->getNextToken();
3972 }
3973 FormatTok = Tokens->setPosition(StoredPosition);
3974
3975 if (IsSimple) {
3976 nextToken();
3977 parseBracedList();
3978 addUnwrappedLine();
3979 return;
3980 }
3981
3982
3983
3984 nextToken();
3985 addUnwrappedLine();
3986 ++Line->Level;
3987
3988
3989 while (!eof()) {
3990 if (FormatTok->is(tok::l_brace)) {
3991
3992 parseBlock(true, 1u,
3993 false);
3994 } else if (FormatTok->is(tok::l_paren)) {
3995 parseParens();
3996 } else if (FormatTok->is(tok::comma)) {
3997 nextToken();
3998 addUnwrappedLine();
3999 } else if (FormatTok->is(tok::semi)) {
4000 nextToken();
4001 addUnwrappedLine();
4002 break;
4003 } else if (FormatTok->is(tok::r_brace)) {
4004 addUnwrappedLine();
4005 break;
4006 } else {
4007 nextToken();
4008 }
4009 }
4010
4011
4012 parseLevel(OpeningBrace);
4013 nextToken();
4014 --Line->Level;
4015 addUnwrappedLine();
4016}
4017
4018void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
4019 const FormatToken &InitialToken = *FormatTok;
4020 nextToken();
4021
4022 const FormatToken *ClassName = nullptr;
4023 bool IsDerived = false;
4024 auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
4025 return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();
4026 };
4027
4028
4029 bool JSPastExtendsOrImplements = false;
4030
4031
4032
4033 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
4034 tok::kw_alignas, tok::l_square) ||
4037 FormatTok->isOneOf(tok::period, tok::comma))) {
4040 JSPastExtendsOrImplements = true;
4041
4042
4043
4044 nextToken();
4045 if (FormatTok->is(tok::l_brace)) {
4046 tryToParseBracedList();
4047 continue;
4048 }
4049 }
4050 if (FormatTok->is(tok::l_square) && handleCppAttributes())
4051 continue;
4052 const auto *Previous = FormatTok;
4053 nextToken();
4055 case tok::l_paren:
4056
4057 if (!IsNonMacroIdentifier(Previous) ||
4058
4059 Previous->Previous == &InitialToken) {
4060 parseParens();
4061 }
4062 break;
4063 case tok::coloncolon:
4064 case tok::hashhash:
4065 break;
4066 default:
4067 if (!JSPastExtendsOrImplements && !ClassName &&
4068 Previous->is(tok::identifier) && Previous->isNot(TT_AttributeMacro)) {
4070 }
4071 }
4072 }
4073
4074 auto IsListInitialization = [&] {
4075 if (!ClassName || IsDerived || JSPastExtendsOrImplements)
4076 return false;
4077 assert(FormatTok->is(tok::l_brace));
4079 assert(Prev);
4080 return Prev != ClassName && Prev->is(tok::identifier) &&
4081 Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
4082 };
4083
4084 if (FormatTok->isOneOf(tok::colon, tok::less)) {
4085 int AngleNestingLevel = 0;
4086 do {
4087 if (FormatTok->is(tok::less))
4088 ++AngleNestingLevel;
4089 else if (FormatTok->is(tok::greater))
4090 --AngleNestingLevel;
4091
4092 if (AngleNestingLevel == 0) {
4093 if (FormatTok->is(tok::colon)) {
4094 IsDerived = true;
4095 } else if (FormatTok->is(tok::identifier) &&
4096 FormatTok->Previous->is(tok::coloncolon)) {
4097 ClassName = FormatTok;
4098 } else if (FormatTok->is(tok::l_paren) &&
4099 IsNonMacroIdentifier(FormatTok->Previous)) {
4100 break;
4101 }
4102 }
4103 if (FormatTok->is(tok::l_brace)) {
4104 if (AngleNestingLevel == 0 && IsListInitialization())
4105 return;
4106 calculateBraceTypes(true);
4107 if (!tryToParseBracedList())
4108 break;
4109 }
4110 if (FormatTok->is(tok::l_square)) {
4113 ->isTypeOrIdentifier(LangOpts))) {
4114
4115
4116 if (!tryToParseLambda())
4117 continue;
4118 } else {
4119 parseSquare();
4120 continue;
4121 }
4122 }
4123 if (FormatTok->is(tok::semi))
4124 return;
4126 addUnwrappedLine();
4127 nextToken();
4128 parseCSharpGenericTypeConstraint();
4129 break;
4130 }
4131 nextToken();
4132 } while (!eof());
4133 }
4134
4135 auto GetBraceTypes =
4136 [](const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {
4137 switch (RecordTok.Tok.getKind()) {
4138 case tok::kw_class:
4139 return {TT_ClassLBrace, TT_ClassRBrace};
4140 case tok::kw_struct:
4141 return {TT_StructLBrace, TT_StructRBrace};
4142 case tok::kw_union:
4143 return {TT_UnionLBrace, TT_UnionRBrace};
4144 default:
4145
4146 return {TT_RecordLBrace, TT_RecordRBrace};
4147 }
4148 };
4149 if (FormatTok->is(tok::l_brace)) {
4150 if (IsListInitialization())
4151 return;
4152 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
4154 if (ParseAsExpr) {
4155 parseChildBlock();
4156 } else {
4158 addUnwrappedLine();
4159
4161 parseBlock(true, AddLevels, false);
4162 }
4163 setPreviousRBraceType(ClosingBraceType);
4164 }
4165
4166
4167
4168}
4169
4170void UnwrappedLineParser::parseObjCMethod() {
4171 assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
4172 "'(' or identifier expected.");
4173 do {
4174 if (FormatTok->is(tok::semi)) {
4175 nextToken();
4176 addUnwrappedLine();
4177 return;
4178 } else if (FormatTok->is(tok::l_brace)) {
4180 addUnwrappedLine();
4181 parseBlock();
4182 addUnwrappedLine();
4183 return;
4184 } else {
4185 nextToken();
4186 }
4187 } while (!eof());
4188}
4189
4190void UnwrappedLineParser::parseObjCProtocolList() {
4191 assert(FormatTok->is(tok::less) && "'<' expected.");
4192 do {
4193 nextToken();
4194
4195 if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
4197 return;
4198 }
4199 } while (!eof() && FormatTok->isNot(tok::greater));
4200 nextToken();
4201}
4202
4203void UnwrappedLineParser::parseObjCUntilAtEnd() {
4204 do {
4206 nextToken();
4207 addUnwrappedLine();
4208 break;
4209 }
4210 if (FormatTok->is(tok::l_brace)) {
4211 parseBlock();
4212
4213 addUnwrappedLine();
4214 } else if (FormatTok->is(tok::r_brace)) {
4215
4216 nextToken();
4217 addUnwrappedLine();
4218 } else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
4219 nextToken();
4220 parseObjCMethod();
4221 } else {
4222 parseStructuralElement();
4223 }
4224 } while (!eof());
4225}
4226
4227void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
4230 nextToken();
4231 nextToken();
4232
4233
4234
4235 if (FormatTok->is(tok::less))
4236 parseObjCLightweightGenerics();
4237 if (FormatTok->is(tok::colon)) {
4238 nextToken();
4239 nextToken();
4240
4241 if (FormatTok->is(tok::less))
4242 parseObjCLightweightGenerics();
4243 } else if (FormatTok->is(tok::l_paren)) {
4244
4245 parseParens();
4246 }
4247
4248 if (FormatTok->is(tok::less))
4249 parseObjCProtocolList();
4250
4251 if (FormatTok->is(tok::l_brace)) {
4253 addUnwrappedLine();
4254 parseBlock(true);
4255 }
4256
4257
4258
4259 addUnwrappedLine();
4260
4261 parseObjCUntilAtEnd();
4262}
4263
4264void UnwrappedLineParser::parseObjCLightweightGenerics() {
4265 assert(FormatTok->is(tok::less));
4266
4267
4268
4269
4270
4271
4272
4273 unsigned NumOpenAngles = 1;
4274 do {
4275 nextToken();
4276
4277 if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
4279 break;
4280 }
4281 if (FormatTok->is(tok::less)) {
4282 ++NumOpenAngles;
4283 } else if (FormatTok->is(tok::greater)) {
4284 assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");
4285 --NumOpenAngles;
4286 }
4287 } while (!eof() && NumOpenAngles != 0);
4288 nextToken();
4289}
4290
4291
4292
4293bool UnwrappedLineParser::parseObjCProtocol() {
4295 nextToken();
4296
4297 if (FormatTok->is(tok::l_paren)) {
4298
4299 return false;
4300 }
4301
4302
4303
4304
4305
4306
4307 nextToken();
4308
4309 if (FormatTok->is(tok::less))
4310 parseObjCProtocolList();
4311
4312
4313 if (FormatTok->is(tok::semi)) {
4314 nextToken();
4315 addUnwrappedLine();
4316 return true;
4317 }
4318
4319 addUnwrappedLine();
4320 parseObjCUntilAtEnd();
4321 return true;
4322}
4323
4324void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
4325 bool IsImport = FormatTok->is(Keywords.kw_import);
4326 assert(IsImport || FormatTok->is(tok::kw_export));
4327 nextToken();
4328
4329
4330 if (FormatTok->is(tok::kw_default))
4331 nextToken();
4332
4333
4334
4335
4336 if (FormatTok->is(Keywords.kw_async))
4337 nextToken();
4339 nextToken();
4340 return;
4341 }
4342
4343
4344
4345
4346
4347 if (!IsImport && !FormatTok->isOneOf(tok::l_brace, tok::star) &&
4349 !(FormatTok->is(Keywords.kw_type) &&
4350 Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {
4351 return;
4352 }
4353
4354 while (!eof()) {
4355 if (FormatTok->is(tok::semi))
4356 return;
4357 if (Line->Tokens.empty()) {
4358
4359
4360 return;
4361 }
4362 if (FormatTok->is(tok::l_brace)) {
4364 nextToken();
4365 parseBracedList();
4366 } else {
4367 nextToken();
4368 }
4369 }
4370}
4371
4372void UnwrappedLineParser::parseStatementMacro() {
4373 nextToken();
4374 if (FormatTok->is(tok::l_paren))
4375 parseParens();
4376 if (FormatTok->is(tok::semi))
4377 nextToken();
4378 addUnwrappedLine();
4379}
4380
4381void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
4382
4383 while (true) {
4384 if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
4385 tok::coloncolon, tok::hash) ||
4387 nextToken();
4388 } else if (FormatTok->is(tok::l_square)) {
4389 parseSquare();
4390 } else {
4391 break;
4392 }
4393 }
4394}
4395
4396void UnwrappedLineParser::parseVerilogSensitivityList() {
4397 if (FormatTok->isNot(tok::at))
4398 return;
4399 nextToken();
4400
4401 if (FormatTok->is(tok::at))
4402 nextToken();
4404 case tok:⭐
4405 nextToken();
4406 break;
4407 case tok::l_paren:
4408 parseParens();
4409 break;
4410 default:
4411 parseVerilogHierarchyIdentifier();
4412 break;
4413 }
4414}
4415
4416unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
4417 unsigned AddLevels = 0;
4418
4420 nextToken();
4422 nextToken();
4423 parseVerilogSensitivityList();
4424 if (FormatTok->is(tok::semi))
4425 nextToken();
4426 } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
4430 AddLevels++;
4431 nextToken();
4432 if (FormatTok->is(tok::l_paren)) {
4434 parseParens();
4435 }
4437 nextToken();
4438
4439 } else {
4440
4441 nextToken();
4442
4443
4444 while (true) {
4445 if (FormatTok->is(tok::l_square)) {
4449 parseSquare();
4451 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
4453 nextToken();
4454 } else {
4455 break;
4456 }
4457 }
4458
4459 auto NewLine = [this]() {
4460 addUnwrappedLine();
4461 Line->IsContinuation = true;
4462 };
4463
4464
4465 while (FormatTok->is(Keywords.kw_import)) {
4467 nextToken();
4468 parseVerilogHierarchyIdentifier();
4469 if (FormatTok->is(tok::semi))
4470 nextToken();
4471 }
4472
4473
4476 nextToken();
4477 if (FormatTok->is(tok::l_paren)) {
4479 parseParens();
4480 }
4481 }
4482 if (FormatTok->is(tok::l_paren)) {
4485 parseParens();
4486 }
4487
4488
4491 nextToken();
4492 parseVerilogHierarchyIdentifier();
4493 if (FormatTok->is(tok::l_paren))
4494 parseParens();
4495 }
4498 do {
4499 nextToken();
4500 parseVerilogHierarchyIdentifier();
4501 } while (FormatTok->is(tok::comma));
4502 }
4503
4504
4505 if (FormatTok->is(tok::at)) {
4507 parseVerilogSensitivityList();
4508 }
4509
4510 if (FormatTok->is(tok::semi))
4511 nextToken(1);
4512 addUnwrappedLine();
4513 }
4514
4515 return AddLevels;
4516}
4517
4518void UnwrappedLineParser::parseVerilogTable() {
4519 assert(FormatTok->is(Keywords.kw_table));
4520 nextToken(1);
4521 addUnwrappedLine();
4522
4523 auto InitialLevel = Line->Level++;
4524 while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) {
4525 FormatToken *Tok = FormatTok;
4526 nextToken();
4527 if (Tok->is(tok::semi))
4528 addUnwrappedLine();
4529 else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus))
4530 Tok->setFinalizedType(TT_VerilogTableItem);
4531 }
4532 Line->Level = InitialLevel;
4533 nextToken(-1);
4534 addUnwrappedLine();
4535}
4536
4537void UnwrappedLineParser::parseVerilogCaseLabel() {
4538
4539
4540
4541
4542
4543 auto OrigLevel = Line->Level;
4544 auto FirstLine = CurrentLines->size();
4545 if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1))
4546 ++Line->Level;
4548 --Line->Level;
4549 parseStructuralElement();
4550
4551
4552 if (CurrentLines->size() > FirstLine)
4553 (*CurrentLines)[FirstLine].Level = OrigLevel;
4554 Line->Level = OrigLevel;
4555}
4556
4557bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const {
4558 for (const auto &N : Line.Tokens) {
4559 if (N.Tok->MacroCtx)
4560 return true;
4561 for (const UnwrappedLine &Child : N.Children)
4562 if (containsExpansion(Child))
4563 return true;
4564 }
4565 return false;
4566}
4567
4568void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
4569 if (Line->Tokens.empty())
4570 return;
4571 LLVM_DEBUG({
4572 if (!parsingPPDirective()) {
4573 llvm::dbgs() << "Adding unwrapped line:\n";
4574 printDebugInfo(*Line);
4575 }
4576 });
4577
4578
4579
4580
4581
4582 bool ClosesWhitesmithsBlock =
4585
4586
4587
4588
4589 if (!parsingPPDirective() && !InExpansion && containsExpansion(*Line)) {
4590 if (!Reconstruct)
4591 Reconstruct.emplace(Line->Level, Unexpanded);
4592 Reconstruct->addLine(*Line);
4593
4594
4595
4596
4597 CurrentExpandedLines.push_back(std::move(*Line));
4598
4599 if (Reconstruct->finished()) {
4600 UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();
4601 assert(!Reconstructed.Tokens.empty() &&
4602 "Reconstructed must at least contain the macro identifier.");
4603 assert(!parsingPPDirective());
4604 LLVM_DEBUG({
4605 llvm::dbgs() << "Adding unexpanded line:\n";
4606 printDebugInfo(Reconstructed);
4607 });
4608 ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;
4609 Lines.push_back(std::move(Reconstructed));
4610 CurrentExpandedLines.clear();
4611 Reconstruct.reset();
4612 }
4613 } else {
4614
4615
4616 assert(!Reconstruct || (CurrentLines != &Lines) || PPStack.size() > 0);
4617 CurrentLines->push_back(std::move(*Line));
4618 }
4619 Line->Tokens.clear();
4621 Line->FirstStartColumn = 0;
4622 Line->IsContinuation = false;
4623 Line->SeenDecltypeAuto = false;
4624
4625 if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
4626 --Line->Level;
4627 if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {
4628 CurrentLines->append(
4629 std::make_move_iterator(PreprocessorDirectives.begin()),
4630 std::make_move_iterator(PreprocessorDirectives.end()));
4631 PreprocessorDirectives.clear();
4632 }
4633
4634 FormatTok->Previous = nullptr;
4635}
4636
4637bool UnwrappedLineParser::eof() const { return FormatTok->is(tok::eof); }
4638
4639bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
4640 return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
4641 FormatTok.NewlinesBefore > 0;
4642}
4643
4644
4645
4646static bool
4649 const llvm::Regex &CommentPragmasRegex) {
4651 return false;
4652
4653 StringRef IndentContent = FormatTok.TokenText;
4654 if (FormatTok.TokenText.starts_with("//") ||
4655 FormatTok.TokenText.starts_with("/*")) {
4656 IndentContent = FormatTok.TokenText.substr(2);
4657 }
4658 if (CommentPragmasRegex.match(IndentContent))
4659 return false;
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727 const FormatToken *MinColumnToken = Line.Tokens.front().Tok;
4728
4729
4730
4731 const FormatToken *PreviousToken = nullptr;
4733 if (PreviousToken && PreviousToken->is(tok::l_brace) &&
4735 MinColumnToken = PreviousToken;
4736 break;
4737 }
4738 PreviousToken = Node.Tok;
4739
4740
4741 if (Node.Tok->NewlinesBefore > 0)
4742 MinColumnToken = Node.Tok;
4743 }
4744 if (PreviousToken && PreviousToken->is(tok::l_brace))
4745 MinColumnToken = PreviousToken;
4746
4748 MinColumnToken);
4749}
4750
4751void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
4752 bool JustComments = Line->Tokens.empty();
4753 for (FormatToken *Tok : CommentsBeforeNextToken) {
4754
4755
4756
4757
4758
4759
4760
4761
4762 Tok->ContinuesLineCommentSection =
4764 if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection)
4765 addUnwrappedLine();
4766 pushToken(Tok);
4767 }
4768 if (NewlineBeforeNext && JustComments)
4769 addUnwrappedLine();
4770 CommentsBeforeNextToken.clear();
4771}
4772
4773void UnwrappedLineParser::nextToken(int LevelDifference) {
4774 if (eof())
4775 return;
4776 flushComments(isOnNewLine(*FormatTok));
4777 pushToken(FormatTok);
4778 FormatToken *Previous = FormatTok;
4780 readToken(LevelDifference);
4781 else
4782 readTokenWithJavaScriptASI();
4783 FormatTok->Previous = Previous;
4785
4786
4787
4788
4789
4790
4792 FormatTok->Tok.setKind(tok::r_brace);
4793 }
4794}
4795
4796void UnwrappedLineParser::distributeComments(
4797 const ArrayRef<FormatToken *> &Comments, const FormatToken *NextTok) {
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816 if (Comments.empty())
4817 return;
4818 bool ShouldPushCommentsInCurrentLine = true;
4819 bool HasTrailAlignedWithNextToken = false;
4820 unsigned StartOfTrailAlignedWithNextToken = 0;
4821 if (NextTok) {
4822
4823 for (unsigned i = Comments.size() - 1; i > 0; --i) {
4824 if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) {
4825 HasTrailAlignedWithNextToken = true;
4826 StartOfTrailAlignedWithNextToken = i;
4827 }
4828 }
4829 }
4830 for (unsigned i = 0, e = Comments.size(); i < e; ++i) {
4831 FormatToken *FormatTok = Comments[i];
4832 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
4833 FormatTok->ContinuesLineCommentSection = false;
4834 } else {
4836 *FormatTok, *Line, Style, CommentPragmasRegex);
4837 }
4838 if (!FormatTok->ContinuesLineCommentSection &&
4839 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
4840 ShouldPushCommentsInCurrentLine = false;
4841 }
4842 if (ShouldPushCommentsInCurrentLine)
4843 pushToken(FormatTok);
4844 else
4845 CommentsBeforeNextToken.push_back(FormatTok);
4846 }
4847}
4848
4849void UnwrappedLineParser::readToken(int LevelDifference) {
4850 SmallVector<FormatToken *, 1> Comments;
4851 bool PreviousWasComment = false;
4852 bool FirstNonCommentOnLine = false;
4853 do {
4854 FormatTok = Tokens->getNextToken();
4855 assert(FormatTok);
4856 while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
4857 TT_ConflictAlternative)) {
4858 if (FormatTok->is(TT_ConflictStart))
4859 conditionalCompilationStart(false);
4860 else if (FormatTok->is(TT_ConflictAlternative))
4861 conditionalCompilationAlternative();
4862 else if (FormatTok->is(TT_ConflictEnd))
4863 conditionalCompilationEnd();
4864 FormatTok = Tokens->getNextToken();
4865 FormatTok->MustBreakBefore = true;
4866 FormatTok->MustBreakBeforeFinalized = true;
4867 }
4868
4869 auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine,
4870 const FormatToken &Tok,
4871 bool PreviousWasComment) {
4872 auto IsFirstOnLine = [](const FormatToken &Tok) {
4873 return Tok.HasUnescapedNewline || Tok.IsFirst;
4874 };
4875
4876
4877
4878 if (PreviousWasComment)
4879 return FirstNonCommentOnLine || IsFirstOnLine(Tok);
4880 return IsFirstOnLine(Tok);
4881 };
4882
4883 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4884 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4885 PreviousWasComment = FormatTok->is(tok::comment);
4886
4887 while (!Line->InPPDirective && FormatTok->is(tok::hash) &&
4890 FirstNonCommentOnLine) {
4891 distributeComments(Comments, FormatTok);
4892 Comments.clear();
4893
4894
4895 bool SwitchToPreprocessorLines = !Line->Tokens.empty();
4896 ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
4897 assert((LevelDifference >= 0 ||
4898 static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
4899 "LevelDifference makes Line->Level negative");
4900 Line->Level += LevelDifference;
4901
4902
4903
4905 PPBranchLevel > 0) {
4906 Line->Level += PPBranchLevel;
4907 }
4908 assert(Line->Level >= Line->UnbracedBodyLevel);
4909 Line->Level -= Line->UnbracedBodyLevel;
4910 flushComments(isOnNewLine(*FormatTok));
4911 parsePPDirective();
4912 PreviousWasComment = FormatTok->is(tok::comment);
4913 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4914 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4915 }
4916
4917 if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
4918 !Line->InPPDirective) {
4919 continue;
4920 }
4921
4922 if (FormatTok->is(tok::identifier) &&
4923 Macros.defined(FormatTok->TokenText) &&
4924
4925 !Line->InPPDirective) {
4926 FormatToken *ID = FormatTok;
4927 unsigned Position = Tokens->getPosition();
4928
4929
4930
4931 auto PreCall = std::move(Line);
4932 Line.reset(new UnwrappedLine);
4933 bool OldInExpansion = InExpansion;
4934 InExpansion = true;
4935
4936 auto Args = parseMacroCall();
4937 InExpansion = OldInExpansion;
4938 assert(Line->Tokens.front().Tok == ID);
4939
4940 auto UnexpandedLine = std::move(Line);
4941
4942 Line = std::move(PreCall);
4943
4944 LLVM_DEBUG({
4945 llvm::dbgs() << "Macro call: " << ID->TokenText << "(";
4946 if (Args) {
4947 llvm::dbgs() << "(";
4948 for (const auto &Arg : Args.value())
4949 for (const auto &T : Arg)
4950 llvm::dbgs() << T->TokenText << " ";
4951 llvm::dbgs() << ")";
4952 }
4953 llvm::dbgs() << "\n";
4954 });
4955 if (Macros.objectLike(ID->TokenText) && Args &&
4956 !Macros.hasArity(ID->TokenText, Args->size())) {
4957
4958
4959
4960
4961
4962 LLVM_DEBUG(llvm::dbgs()
4963 << "Macro \"" << ID->TokenText
4964 << "\" not overloaded for arity " << Args->size()
4965 << "or not function-like, using object-like overload.");
4966 Args.reset();
4967 UnexpandedLine->Tokens.resize(1);
4968 Tokens->setPosition(Position);
4969 nextToken();
4970 assert(!Args && Macros.objectLike(ID->TokenText));
4971 }
4972 if ((!Args && Macros.objectLike(ID->TokenText)) ||
4973 (Args && Macros.hasArity(ID->TokenText, Args->size()))) {
4974
4975
4976 Unexpanded[ID] = std::move(UnexpandedLine);
4977 SmallVector<FormatToken *, 8> Expansion =
4978 Macros.expand(ID, std::move(Args));
4979 if (!Expansion.empty())
4980 FormatTok = Tokens->insertTokens(Expansion);
4981
4982 LLVM_DEBUG({
4983 llvm::dbgs() << "Expanded: ";
4984 for (const auto &T : Expansion)
4985 llvm::dbgs() << T->TokenText << " ";
4986 llvm::dbgs() << "\n";
4987 });
4988 } else {
4989 LLVM_DEBUG({
4990 llvm::dbgs() << "Did not expand macro \"" << ID->TokenText
4991 << "\", because it was used ";
4992 if (Args)
4993 llvm::dbgs() << "with " << Args->size();
4994 else
4995 llvm::dbgs() << "without";
4996 llvm::dbgs() << " arguments, which doesn't match any definition.\n";
4997 });
4998 Tokens->setPosition(Position);
4999 FormatTok = ID;
5000 }
5001 }
5002
5003 if (FormatTok->isNot(tok::comment)) {
5004 distributeComments(Comments, FormatTok);
5005 Comments.clear();
5006 return;
5007 }
5008
5009 Comments.push_back(FormatTok);
5010 } while (!eof());
5011
5012 distributeComments(Comments, nullptr);
5013 Comments.clear();
5014}
5015
5016namespace {
5017template
5018void pushTokens(Iterator Begin, Iterator End,
5019 SmallVectorImpl<FormatToken *> &Into) {
5020 for (auto I = Begin; I != End; ++I) {
5021 Into.push_back(I->Tok);
5022 for (const auto &Child : I->Children)
5023 pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);
5024 }
5025}
5026}
5027
5028std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
5029UnwrappedLineParser::parseMacroCall() {
5030 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;
5031 assert(Line->Tokens.empty());
5032 nextToken();
5033 if (FormatTok->isNot(tok::l_paren))
5034 return Args;
5035 unsigned Position = Tokens->getPosition();
5036 FormatToken *Tok = FormatTok;
5037 nextToken();
5038 Args.emplace();
5039 auto ArgStart = std::prev(Line->Tokens.end());
5040
5042 do {
5043 switch (FormatTok->Tok.getKind()) {
5044 case tok::l_paren:
5046 nextToken();
5047 break;
5048 case tok::r_paren: {
5051 nextToken();
5052 break;
5053 }
5054 Args->push_back({});
5055 pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());
5056 nextToken();
5057 return Args;
5058 }
5059 case tok::comma: {
5061 nextToken();
5062 break;
5063 }
5064 Args->push_back({});
5065 pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());
5066 nextToken();
5067 ArgStart = std::prev(Line->Tokens.end());
5068 break;
5069 }
5070 default:
5071 nextToken();
5072 break;
5073 }
5074 } while (!eof());
5075 Line->Tokens.resize(1);
5076 Tokens->setPosition(Position);
5077 FormatTok = Tok;
5078 return {};
5079}
5080
5081void UnwrappedLineParser::pushToken(FormatToken *Tok) {
5082 Line->Tokens.push_back(UnwrappedLineNode(Tok));
5083 if (MustBreakBeforeNextToken) {
5084 Line->Tokens.back().Tok->MustBreakBefore = true;
5085 Line->Tokens.back().Tok->MustBreakBeforeFinalized = true;
5086 MustBreakBeforeNextToken = false;
5087 }
5088}
5089
5090}
5091}
enum clang::sema::@1725::IndirectLocalPathEntry::EntryKind Kind
This file contains FormatTokenLexer, which tokenizes a source file into a token stream suitable for C...
This file defines the FormatTokenSource interface, which provides a token stream as well as the abili...
This file contains the declaration of the FormatToken, a wrapper around Token with additional informa...
This file contains the main building blocks of macro support in clang-format.
This file implements a token annotator, i.e.
Defines the clang::TokenKind enum and support functions.
ContinuationIndenter * Indenter
This file contains the declaration of the UnwrappedLineParser, which turns a stream of tokens into Un...
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
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 isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
void setKind(tok::TokenKind K)
tok::ObjCKeywordKind getObjCKeywordID() const
Return the ObjC keyword kind.
tok::TokenKind getKind() const
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
bool isNot(tok::TokenKind K) const
void setIdentifierInfo(IdentifierInfo *II)
CompoundStatementIndenter(UnwrappedLineParser *Parser, const FormatStyle &Style, unsigned &LineLevel)
~CompoundStatementIndenter()
CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel, bool WrapBrace, bool IndentBrace)
virtual FormatToken * peekNextToken(bool SkipComment=false)=0
virtual unsigned getPosition()=0
FormatToken * getNextNonComment()
virtual FormatToken * getPreviousToken()=0
virtual FormatToken * setPosition(unsigned Position)=0
virtual FormatToken * getNextToken()=0
bool objectLike(StringRef Name) const
Returns whetherh there is an object-like overload, i.e.
SmallVector< FormatToken *, 8 > expand(FormatToken *ID, std::optional< ArgsList > OptionalArgs) const
Returns the expanded stream of format tokens for ID, where each element in Args is a positional argum...
bool hasArity(StringRef Name, unsigned Arity) const
Returns whether macro Name provides an overload with the given arity.
bool defined(StringRef Name) const
Returns whether any macro Name is defined, regardless of overloads.
ScopedLineState(UnwrappedLineParser &Parser, bool SwitchToPreprocessorLines=false)
Interface for users of the UnwrappedLineParser to receive the parsed lines.
virtual void finishRun()=0
virtual void consumeUnwrappedLine(const UnwrappedLine &Line)=0
friend class ScopedLineState
friend class CompoundStatementIndenter
UnwrappedLineParser(SourceManager &SourceMgr, const FormatStyle &Style, const AdditionalKeywords &Keywords, unsigned FirstStartColumn, ArrayRef< FormatToken * > Tokens, UnwrappedLineConsumer &Callback, llvm::SpecificBumpPtrAllocator< FormatToken > &Allocator, IdentifierTable &IdentTable)
static bool isCOperatorFollowingVar(tok::TokenKind Kind)
static void hash_combine(std::size_t &seed, const T &v)
static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords, const FormatToken *FormatTok)
std::ostream & operator<<(std::ostream &Stream, const UnwrappedLine &Line)
bool continuesLineComment(const FormatToken &FormatTok, const FormatToken *Previous, const FormatToken *MinColumnToken)
static bool tokenCanStartNewLine(const FormatToken &Tok)
static bool continuesLineCommentSection(const FormatToken &FormatTok, const UnwrappedLine &Line, const FormatStyle &Style, const llvm::Regex &CommentPragmasRegex)
static bool isC78Type(const FormatToken &Tok)
bool isLineComment(const FormatToken &FormatTok)
static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords, const FormatToken *FormatTok)
static bool ShouldBreakBeforeBrace(const FormatStyle &Style, const FormatToken &InitialToken)
LangOptions getFormattingLangOpts(const FormatStyle &Style=getLLVMStyle())
Returns the LangOpts that the formatter expects you to set.
static void markOptionalBraces(FormatToken *LeftBrace)
static bool mustBeJSIdent(const AdditionalKeywords &Keywords, const FormatToken *FormatTok)
static bool isIIFE(const UnwrappedLine &Line, const AdditionalKeywords &Keywords)
static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next, const FormatToken *FuncName)
static bool isGoogScope(const UnwrappedLine &Line)
static FormatToken * getLastNonComment(const UnwrappedLine &Line)
TokenType
Determines the semantic type of a syntactic token, e.g.
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.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
@ 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...
bool isVerilogEnd(const FormatToken &Tok) const
Returns whether Tok is a Verilog keyword that closes a block.
IdentifierInfo * kw_foreach
IdentifierInfo * kw_forever
IdentifierInfo * kw_signals
IdentifierInfo * kw_inside
IdentifierInfo * kw_CF_ENUM
IdentifierInfo * kw_synchronized
IdentifierInfo * kw_randcase
IdentifierInfo * kw_randsequence
IdentifierInfo * kw_always_ff
IdentifierInfo * kw_always_latch
IdentifierInfo * kw_final
IdentifierInfo * kw_assert
bool isVerilogBegin(const FormatToken &Tok) const
Returns whether Tok is a Verilog keyword that opens a block.
IdentifierInfo * kw_initial
IdentifierInfo * kw_priority
IdentifierInfo * kw_qsignals
IdentifierInfo * kw_cover
IdentifierInfo * kw_assume
bool isVerilogStructuredProcedure(const FormatToken &Tok) const
Returns whether Tok is a Verilog keyword that starts a structured procedure like 'always'.
IdentifierInfo * kw_CF_OPTIONS
IdentifierInfo * kw_defset
IdentifierInfo * kw_unique0
IdentifierInfo * kw_interface
IdentifierInfo * kw_yield
IdentifierInfo * kw_CF_CLOSED_ENUM
IdentifierInfo * kw_slots
IdentifierInfo * kw_import
IdentifierInfo * kw_casex
IdentifierInfo * kw_repeat
IdentifierInfo * kw_where
IdentifierInfo * kw_automatic
IdentifierInfo * kw_finally
IdentifierInfo * kw_NS_CLOSED_ENUM
bool isVerilogHierarchy(const FormatToken &Tok) const
Returns whether Tok is a Verilog keyword that opens a module, etc.
IdentifierInfo * kw_async
IdentifierInfo * kw_always_comb
IdentifierInfo * kw_internal
IdentifierInfo * kw_sequence
bool isVerilogPPDirective(const FormatToken &Tok) const
Returns whether Tok is a Verilog preprocessor directive.
IdentifierInfo * kw_casez
IdentifierInfo * kw_throws
IdentifierInfo * kw_NS_ENUM
IdentifierInfo * kw_override
IdentifierInfo * kw___except
IdentifierInfo * kw_table
IdentifierInfo * kw_NS_OPTIONS
IdentifierInfo * kw_abstract
IdentifierInfo * kw_internal_ident_after_define
IdentifierInfo * kw_await
IdentifierInfo * kw_implements
IdentifierInfo * kw_always
IdentifierInfo * kw_verilogHash
IdentifierInfo * kw_instanceof
IdentifierInfo * kw_matches
IdentifierInfo * kw_qslots
IdentifierInfo * kw_function
bool isVerilogIdentifier(const FormatToken &Tok) const
IdentifierInfo * kw_clocking
IdentifierInfo * kw_unique
IdentifierInfo * kw_extends
IdentifierInfo * kw_property
bool AfterClass
Wrap class definitions.
bool AfterCaseLabel
Wrap case labels.
bool AfterStruct
Wrap struct definitions.
bool AfterUnion
Wrap union definitions.
bool AfterEnum
Wrap enum definitions.
bool IndentBraces
Indent the wrapped braces themselves.
bool AfterObjCDeclaration
Wrap ObjC definitions (interfaces, implementations...).
bool BeforeElse
Wrap before else.
bool AfterNamespace
Wrap namespace definitions.
bool BeforeWhile
Wrap before while.
BraceWrappingAfterControlStatementStyle AfterControlStatement
Wrap control statements (if/for/while/switch/..).
bool AfterFunction
Wrap function definitions.
bool BeforeCatch
Wrap before catch.
bool AfterExternBlock
Wrap extern blocks.
The FormatStyle is used to configure the formatting to follow specific guidelines.
@ LK_Java
Should be used for Java.
@ LK_TableGen
Should be used for TableGen code.
@ LK_Proto
Should be used for Protocol Buffers (https://developers.google.com/protocol-buffers/).
@ LK_TextProto
Should be used for Protocol Buffer messages in text format (https://developers.google....
unsigned IndentWidth
The number of columns to use for indentation.
bool IndentCaseLabels
Indent case labels one level from the switch statement.
PPDirectiveIndentStyle IndentPPDirectives
The preprocessor directive indenting style to use.
bool RemoveSemicolon
Remove semicolons after the closing braces of functions and constructors/destructors.
@ RCS_Always
Apply indentation rules and reflow long comments into new lines, trying to obey the ColumnLimit.
@ IEBS_AfterExternBlock
Backwards compatible with AfterExternBlock's indenting.
@ IEBS_Indent
Indents extern blocks.
bool IndentCaseBlocks
Indent case label blocks one level from the case label.
bool InsertBraces
Insert braces after control statements (if, else, for, do, and while) in C++ unless the control state...
RemoveParenthesesStyle RemoveParentheses
Remove redundant parentheses.
LanguageKind Language
Language, this format style is targeted at.
bool RemoveBracesLLVM
Remove optional braces of control statements (if, else, for, and while) in C++ according to the LLVM ...
@ PPDIS_BeforeHash
Indents directives before the hash.
@ PPDIS_None
Does not indent any directives.
bool AllowShortLoopsOnASingleLine
If true, while (true) continue; can be put on a single line.
bool AllowShortEnumsOnASingleLine
Allow short enums on a single line.
NamespaceIndentationKind NamespaceIndentation
The indentation used for namespaces.
BraceBreakingStyle BreakBeforeBraces
The brace breaking style to use.
@ BWACS_Always
Always wrap braces after a control statement.
@ BWACS_Never
Never wrap braces after a control statement.
@ BS_Whitesmiths
Like Allman but always indent braces and line up code with braces.
ReflowCommentsStyle ReflowComments
Comment reformatting style.
bool isJavaScript() const
bool IndentGotoLabels
Indent goto labels.
BraceWrappingFlags BraceWrapping
Control of individual brace wrapping cases.
@ RPS_Leave
Do not remove parentheses.
@ RPS_ReturnStatement
Also remove parentheses enclosing the expression in a return/co_return statement.
bool SkipMacroDefinitionBody
Do not format macro definition body.
@ NI_All
Indent in all namespaces.
@ NI_Inner
Indent only in inner namespaces (nested in other namespaces).
bool IndentAccessModifiers
Specify whether access modifiers should have their own indentation level.
IndentExternBlockStyle IndentExternBlock
IndentExternBlockStyle is the type of indenting of extern blocks.
unsigned ColumnLimit
The column limit.
A wrapper around a Token storing information about the whitespace characters preceding it.
bool Optional
Is optional and can be removed.
bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const
bool isTypeName(const LangOptions &LangOpts) const
bool isCppAlternativeOperatorKeyword() const
StringRef TokenText
The raw text of the token.
FormatToken * getPreviousNonComment() const
Returns the previous token ignoring comments.
unsigned Finalized
If true, this token has been fully formatted (indented and potentially re-formatted inside),...
unsigned NewlinesBefore
The number of newlines immediately before the Token.
void setBlockKind(BraceBlockKind BBK)
bool isStringLiteral() const
bool isBinaryOperator() const
bool is(tok::TokenKind Kind) const
bool hasWhitespaceBefore() const
Returns true if the range of whitespace immediately preceding the Token is not empty.
bool isOneOf(A K1, B K2) const
unsigned ClosesRequiresClause
true if this is the last token within requires clause.
bool isAccessSpecifierKeyword() const
FormatToken * MatchingParen
If this is a bracket, this points to the matching one.
FormatToken * Previous
The previous token in the unwrapped line.
bool endsSequence(A K1, Ts... Tokens) const
true if this token ends a sequence with the given tokens in order, following the Previous pointers,...
void setFinalizedType(TokenType T)
Sets the type and also the finalized flag.
An unwrapped line is a sequence of Token, that we would like to put on a single line if there was no ...
static const size_t kInvalidIndex