21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/Support/Debug.h"
24#include "llvm/Support/raw_os_ostream.h"
25#include "llvm/Support/raw_ostream.h"
29#define DEBUG_TYPE "format-parser"
36void printLine(llvm::raw_ostream &OS,
const UnwrappedLine &
Line,
37 StringRef Prefix =
"",
bool PrintText =
false) {
38 OS << Prefix <<
"Line(" <<
Line.Level <<
", FSC=" <<
Line.FirstStartColumn
39 <<
")" << (
Line.InPPDirective ?
" MACRO" :
"") <<
": ";
41 for (std::list<UnwrappedLineNode>::const_iterator I =
Line.Tokens.begin(),
42 E =
Line.Tokens.end();
48 OS << I->Tok->Tok.getName() <<
"["
49 <<
"T=" << (
unsigned)I->Tok->getType()
50 <<
", OC=" << I->Tok->OriginalColumn <<
", \"" << I->Tok->TokenText
52 for (
const auto *CI = I->Children.begin(), *CE = I->Children.end();
55 printLine(OS, *CI, (Prefix +
" ").str());
63[[maybe_unused]]
static void printDebugInfo(
const UnwrappedLine &
Line) {
64 printLine(llvm::dbgs(),
Line);
67class ScopedDeclarationState {
69 ScopedDeclarationState(UnwrappedLine &
Line, llvm::BitVector &Stack,
70 bool MustBeDeclaration)
72 Line.MustBeDeclaration = MustBeDeclaration;
73 Stack.push_back(MustBeDeclaration);
75 ~ScopedDeclarationState() {
78 Line.MustBeDeclaration = Stack.back();
80 Line.MustBeDeclaration =
true;
85 llvm::BitVector &Stack;
91 llvm::raw_os_ostream OS(Stream);
99 bool SwitchToPreprocessorLines =
false)
100 : Parser(Parser), OriginalLines(Parser.CurrentLines) {
101 if (SwitchToPreprocessorLines)
102 Parser.CurrentLines = &Parser.PreprocessorDirectives;
103 else if (!Parser.Line->Tokens.empty())
104 Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
105 PreBlockLine = std::move(Parser.Line);
106 Parser.Line = std::make_unique<UnwrappedLine>();
107 Parser.Line->Level = PreBlockLine->Level;
108 Parser.Line->PPLevel = PreBlockLine->PPLevel;
109 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
110 Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
111 Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel;
115 if (!Parser.Line->Tokens.empty())
116 Parser.addUnwrappedLine();
117 assert(Parser.Line->Tokens.empty());
118 Parser.Line = std::move(PreBlockLine);
119 if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
120 Parser.AtEndOfPPLine =
true;
121 Parser.CurrentLines = OriginalLines;
127 std::unique_ptr<UnwrappedLine> PreBlockLine;
134 const FormatStyle &Style,
unsigned &LineLevel)
136 Style.BraceWrapping.AfterControlStatement ==
137 FormatStyle::BWACS_Always,
138 Style.BraceWrapping.IndentBraces) {}
140 bool WrapBrace,
bool IndentBrace)
141 : LineLevel(LineLevel), OldLineLevel(LineLevel) {
143 Parser->addUnwrappedLine();
151 unsigned OldLineLevel;
158 llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
161 Style(Style), IsCpp(Style.
isCpp()),
163 CommentPragmasRegex(Style.CommentPragmas), Tokens(
nullptr),
164 Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
165 IncludeGuard(getIncludeGuardState(Style.IndentPPDirectives)),
166 IncludeGuardToken(
nullptr), FirstStartColumn(FirstStartColumn),
167 Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}
169void UnwrappedLineParser::reset() {
171 IncludeGuard = getIncludeGuardState(Style.IndentPPDirectives);
172 IncludeGuardToken =
nullptr;
174 CommentsBeforeNextToken.clear();
176 AtEndOfPPLine =
false;
177 IsDecltypeAutoFunction =
false;
178 PreprocessorDirectives.clear();
179 CurrentLines = &Lines;
180 DeclarationScopeStack.clear();
181 NestedTooDeep.clear();
182 NestedLambdas.clear();
184 Line->FirstStartColumn = FirstStartColumn;
186 if (!Unexpanded.empty())
188 Token->MacroCtx.reset();
189 CurrentExpandedLines.clear();
190 ExpandedLines.clear();
198 Line->FirstStartColumn = FirstStartColumn;
200 LLVM_DEBUG(llvm::dbgs() <<
"----\n");
202 Tokens = &TokenSource;
210 if (IncludeGuard == IG_Found) {
211 for (
auto &Line : Lines)
212 if (Line.InPPDirective && Line.Level > 0)
218 pushToken(FormatTok);
223 if (!ExpandedLines.empty()) {
224 LLVM_DEBUG(llvm::dbgs() <<
"Expanded lines:\n");
225 for (
const auto &Line : Lines) {
226 if (!Line.Tokens.empty()) {
227 auto it = ExpandedLines.find(Line.Tokens.begin()->Tok);
228 if (it != ExpandedLines.end()) {
229 for (
const auto &Expanded : it->second) {
230 LLVM_DEBUG(printDebugInfo(Expanded));
231 Callback.consumeUnwrappedLine(Expanded);
236 LLVM_DEBUG(printDebugInfo(Line));
237 Callback.consumeUnwrappedLine(Line);
239 Callback.finishRun();
242 LLVM_DEBUG(llvm::dbgs() <<
"Unwrapped lines:\n");
244 LLVM_DEBUG(printDebugInfo(Line));
245 Callback.consumeUnwrappedLine(Line);
247 Callback.finishRun();
249 while (!PPLevelBranchIndex.empty() &&
250 PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {
251 PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);
252 PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);
254 if (!PPLevelBranchIndex.empty()) {
255 ++PPLevelBranchIndex.back();
256 assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());
257 assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
259 }
while (!PPLevelBranchIndex.empty());
262void UnwrappedLineParser::parseFile() {
265 bool MustBeDeclaration = !
Line->InPPDirective && !Style.isJavaScript();
266 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
268 if (Style.isTextProto() || (Style.isJson() && FormatTok->
IsFirst))
282 if (Style.isTextProto() && !CommentsBeforeNextToken.empty())
288void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {
298 parseCSharpGenericTypeConstraint();
307void UnwrappedLineParser::parseCSharpAttribute() {
308 int UnpairedSquareBrackets = 1;
310 switch (FormatTok->Tok.getKind()) {
313 --UnpairedSquareBrackets;
314 if (UnpairedSquareBrackets == 0) {
320 ++UnpairedSquareBrackets;
330bool UnwrappedLineParser::precededByCommentOrPPDirective()
const {
331 if (!Lines.empty() && Lines.back().InPPDirective)
345bool UnwrappedLineParser::parseLevel(
const FormatToken *OpeningBrace,
348 const bool InRequiresExpression =
349 OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
350 const bool IsPrecededByCommentOrPPDirective =
351 !Style.RemoveBracesLLVM || precededByCommentOrPPDirective();
353 bool HasDoWhile =
false;
354 bool HasLabel =
false;
355 unsigned StatementCount = 0;
356 bool SwitchLabelEncountered =
false;
359 if (FormatTok->isAttribute()) {
361 if (FormatTok->is(tok::l_paren))
366 if (FormatTok->is(TT_MacroBlockBegin))
368 else if (FormatTok->is(TT_MacroBlockEnd))
371 auto ParseDefault = [
this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
372 &HasLabel, &StatementCount] {
373 parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,
374 HasDoWhile ?
nullptr : &HasDoWhile,
375 HasLabel ?
nullptr : &HasLabel);
377 assert(StatementCount > 0 &&
"StatementCount overflow!");
386 if (InRequiresExpression) {
387 FormatTok->setFinalizedType(TT_CompoundRequirementLBrace);
388 }
else if (FormatTok->Previous &&
389 FormatTok->Previous->ClosesRequiresClause) {
395 if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {
396 if (tryToParseBracedList())
398 FormatTok->setFinalizedType(TT_BlockLBrace);
402 assert(StatementCount > 0 &&
"StatementCount overflow!");
407 if (!Style.RemoveBracesLLVM || Line->InPPDirective ||
408 OpeningBrace->isNoneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
411 if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||
412 HasDoWhile || IsPrecededByCommentOrPPDirective ||
413 precededByCommentOrPPDirective()) {
417 if (
Next->is(tok::comment) &&
Next->NewlinesBefore == 0)
420 *IfLeftBrace = IfLBrace;
426 case tok::kw_default: {
427 unsigned StoredPosition = Tokens->getPosition();
428 auto *
Next = Tokens->getNextNonComment();
429 FormatTok = Tokens->setPosition(StoredPosition);
430 if (
Next->isNoneOf(tok::colon, tok::arrow)) {
433 parseStructuralElement();
440 if (Style.Language == FormatStyle::LK_Proto || Style.isVerilog() ||
441 (Style.isJavaScript() && Line->MustBeDeclaration)) {
449 if (!SwitchLabelEncountered &&
450 (Style.IndentCaseLabels ||
451 (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||
452 (Line->InPPDirective && Line->Level == 1))) {
455 SwitchLabelEncountered =
true;
456 parseStructuralElement();
459 if (Style.isCSharp()) {
461 parseCSharpAttribute();
464 if (handleCppAttributes())
476void UnwrappedLineParser::calculateBraceTypes(
bool ExpectClassBody) {
481 unsigned StoredPosition = Tokens->getPosition();
491 SmallVector<StackEntry, 8> LBraceStack;
492 assert(
Tok->is(tok::l_brace));
495 auto *NextTok = Tokens->getNextNonComment();
497 if (!Line->InMacroBody && !Style.isTableGen()) {
499 while (NextTok->is(tok::hash)) {
500 NextTok = Tokens->getNextToken();
501 if (NextTok->isOneOf(tok::pp_not_keyword, tok::pp_define))
504 NextTok = Tokens->getNextToken();
505 }
while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));
507 while (NextTok->is(tok::comment))
508 NextTok = Tokens->getNextToken();
512 switch (
Tok->Tok.getKind()) {
514 if (Style.isJavaScript() && PrevTok) {
515 if (PrevTok->isOneOf(tok::colon, tok::less)) {
526 }
else if (PrevTok->is(tok::r_paren)) {
533 LBraceStack.push_back({
Tok, PrevTok});
536 if (LBraceStack.empty())
538 if (
auto *LBrace = LBraceStack.back().Tok; LBrace->is(
BK_Unknown)) {
539 bool ProbablyBracedList =
false;
540 if (Style.Language == FormatStyle::LK_Proto) {
541 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
542 }
else if (LBrace->isNot(TT_EnumLBrace)) {
545 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
546 NextTok->OriginalColumn == 0;
556 ProbablyBracedList = LBrace->is(TT_BracedListLBrace);
558 ProbablyBracedList = ProbablyBracedList ||
559 (Style.isJavaScript() &&
560 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
563 ProbablyBracedList ||
564 (IsCpp && (PrevTok->Tok.isLiteral() ||
565 NextTok->isOneOf(tok::l_paren, tok::arrow)));
572 ProbablyBracedList ||
573 NextTok->isOneOf(tok::comma, tok::period, tok::colon,
574 tok::r_paren, tok::r_square, tok::ellipsis);
579 ProbablyBracedList ||
580 (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&
581 LBraceStack.back().PrevTok->isOneOf(tok::identifier,
585 ProbablyBracedList ||
586 (NextTok->is(tok::identifier) &&
587 PrevTok->isNoneOf(tok::semi, tok::r_brace, tok::l_brace));
589 ProbablyBracedList = ProbablyBracedList ||
590 (NextTok->is(tok::semi) &&
591 (!ExpectClassBody || LBraceStack.size() != 1));
594 ProbablyBracedList ||
595 (NextTok->isBinaryOperator() && !NextIsObjCMethod);
597 if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
600 NextTok = Tokens->getNextToken();
601 ProbablyBracedList = NextTok->isNot(tok::l_square);
605 if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
606 !FormatTok->Previous && NextTok->is(tok::eof) &&
610 PrevTok->isNoneOf(tok::semi,
BK_Block, tok::colon)) {
611 ProbablyBracedList =
true;
615 Tok->setBlockKind(BlockKind);
616 LBrace->setBlockKind(BlockKind);
618 LBraceStack.pop_back();
620 case tok::identifier:
621 if (
Tok->isNot(TT_StatementMacro))
632 if (!LBraceStack.empty() && LBraceStack.back().Tok->is(
BK_Unknown))
633 LBraceStack.back().Tok->setBlockKind(
BK_Block);
641 }
while (
Tok->isNot(tok::eof) && !LBraceStack.empty());
644 for (
const auto &Entry : LBraceStack)
648 FormatTok = Tokens->setPosition(StoredPosition);
652void UnwrappedLineParser::setPreviousRBraceType(
TokenType Type) {
653 if (
auto Prev = FormatTok->getPreviousNonComment();
654 Prev && Prev->is(tok::r_brace)) {
655 Prev->setFinalizedType(
Type);
662 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
665size_t UnwrappedLineParser::computePPHash()
const {
667 for (
const auto &i : PPStack) {
678bool UnwrappedLineParser::mightFitOnOneLine(
680 const auto ColumnLimit = Style.ColumnLimit;
681 if (ColumnLimit == 0)
684 auto &Tokens = ParsedLine.Tokens;
685 assert(!Tokens.empty());
687 const auto *LastToken = Tokens.back().Tok;
690 SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());
693 for (
const auto &Token : Tokens) {
695 auto &SavedToken = SavedTokens[Index++];
697 SavedToken.Tok->copyFrom(*Token.Tok);
698 SavedToken.Children = std::move(Token.Children);
701 AnnotatedLine
Line(ParsedLine);
702 assert(Line.Last == LastToken);
704 TokenAnnotator Annotator(Style, Keywords);
705 Annotator.annotate(Line);
706 Annotator.calculateFormattingInformation(Line);
708 auto Length = LastToken->TotalLength;
710 assert(OpeningBrace != Tokens.front().Tok);
711 if (
auto Prev = OpeningBrace->Previous;
712 Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
713 Length -= ColumnLimit;
715 Length -= OpeningBrace->TokenText.size() + 1;
718 if (
const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
719 assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
720 Length -= FirstToken->TokenText.size() + 1;
724 for (
auto &Token : Tokens) {
725 const auto &SavedToken = SavedTokens[Index++];
726 Token.Tok->copyFrom(*SavedToken.Tok);
727 Token.Children = std::move(SavedToken.Children);
728 delete SavedToken.Tok;
732 assert(!Line.InMacroBody);
733 assert(!Line.InPPDirective);
734 return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
737FormatToken *UnwrappedLineParser::parseBlock(
bool MustBeDeclaration,
738 unsigned AddLevels,
bool MunchSemi,
741 bool UnindentWhitesmithsBraces) {
742 auto HandleVerilogBlockLabel = [
this]() {
744 if (Style.isVerilog() && FormatTok->is(tok::colon)) {
746 if (Keywords.isVerilogIdentifier(*FormatTok))
753 const bool VerilogHierarchy =
754 Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);
755 assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
756 (Style.isVerilog() &&
757 (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
758 "'{' or macro block token expected");
760 const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
761 auto Index = CurrentLines->size();
762 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
767 if (!VerilogHierarchy && AddLevels > 0 &&
768 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
772 size_t PPStartHash = computePPHash();
774 const unsigned InitialLevel = Line->Level;
775 if (VerilogHierarchy) {
776 AddLevels += parseVerilogHierarchyHeader();
778 nextToken(AddLevels);
779 HandleVerilogBlockLabel();
783 if (Line->Level > 300)
786 if (MacroBlock && FormatTok->is(tok::l_paren))
789 size_t NbPreprocessorDirectives =
790 !parsingPPDirective() ? PreprocessorDirectives.size() : 0;
792 size_t OpeningLineIndex =
793 CurrentLines->empty()
795 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
800 if (UnindentWhitesmithsBraces)
803 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
805 if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)
806 Line->Level += AddLevels;
809 const bool SimpleBlock = parseLevel(
Tok, IfKind, &IfLBrace);
814 if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)
815 : FormatTok->isNot(tok::r_brace)) {
816 Line->Level = InitialLevel;
817 FormatTok->setBlockKind(BK_Block);
821 if (FormatTok->is(tok::r_brace)) {
822 FormatTok->setBlockKind(BK_Block);
823 if (Tok->is(TT_NamespaceLBrace))
824 FormatTok->setFinalizedType(TT_NamespaceRBrace);
827 const bool IsFunctionRBrace =
828 FormatTok->is(tok::r_brace) &&
Tok->is(TT_FunctionLBrace);
830 auto RemoveBraces = [=]()
mutable {
833 assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
834 assert(FormatTok->is(tok::r_brace));
835 const bool WrappedOpeningBrace = !Tok->Previous;
836 if (WrappedOpeningBrace && FollowedByComment)
838 const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
839 if (KeepBraces && !HasRequiredIfBraces)
841 if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
842 const FormatToken *Previous = Tokens->getPreviousToken();
844 if (Previous->is(tok::r_brace) && !Previous->Optional)
847 assert(!CurrentLines->empty());
848 auto &LastLine = CurrentLines->back();
849 if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
851 if (
Tok->is(TT_ElseLBrace))
853 if (WrappedOpeningBrace) {
858 return mightFitOnOneLine((*CurrentLines)[Index],
Tok);
860 if (RemoveBraces()) {
861 Tok->MatchingParen = FormatTok;
862 FormatTok->MatchingParen =
Tok;
865 size_t PPEndHash = computePPHash();
868 nextToken(-AddLevels);
873 if (Style.RemoveSemicolon && IsFunctionRBrace) {
874 while (FormatTok->is(tok::semi)) {
875 FormatTok->Optional =
true;
880 HandleVerilogBlockLabel();
882 if (MacroBlock && FormatTok->is(tok::l_paren))
885 Line->Level = InitialLevel;
887 if (FormatTok->is(tok::kw_noexcept)) {
892 if (FormatTok->is(tok::arrow)) {
896 parseStructuralElement();
899 if (MunchSemi && FormatTok->is(tok::semi))
902 if (PPStartHash == PPEndHash) {
903 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
906 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
907 CurrentLines->size() - 1;
917 if (
Line.Tokens.size() < 4)
919 auto I =
Line.Tokens.begin();
920 if (I->Tok->TokenText !=
"goog")
923 if (I->Tok->isNot(tok::period))
926 if (I->Tok->TokenText !=
"scope")
929 return I->Tok->is(tok::l_paren);
938 if (
Line.Tokens.size() < 3)
940 auto I =
Line.Tokens.begin();
941 if (I->Tok->isNot(tok::l_paren))
947 return I->Tok->is(tok::l_paren);
952 const bool IsJavaRecord) {
954 return Style.BraceWrapping.AfterClass;
957 if (InitialToken.
is(TT_NamespaceMacro))
958 Kind = tok::kw_namespace;
961 case tok::kw_namespace:
962 return Style.BraceWrapping.AfterNamespace;
964 return Style.BraceWrapping.AfterClass;
966 return Style.BraceWrapping.AfterUnion;
968 return Style.BraceWrapping.AfterStruct;
970 return Style.BraceWrapping.AfterEnum;
976void UnwrappedLineParser::parseChildBlock() {
977 assert(FormatTok->is(tok::l_brace));
978 FormatTok->setBlockKind(BK_Block);
982 bool SkipIndent = (Style.isJavaScript() &&
983 (isGoogScope(*
Line) || isIIFE(*
Line, Keywords)));
984 ScopedLineState LineState(*
this);
985 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
987 Line->Level += SkipIndent ? 0 : 1;
988 parseLevel(OpeningBrace);
989 flushComments(isOnNewLine(*FormatTok));
990 Line->Level -= SkipIndent ? 0 : 1;
995void UnwrappedLineParser::parsePPDirective() {
996 assert(FormatTok->is(tok::hash) &&
"'#' expected");
997 ScopedMacroState MacroState(*
Line, Tokens, FormatTok);
1001 if (!FormatTok->Tok.getIdentifierInfo()) {
1006 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
1007 case tok::pp_define:
1014 case tok::pp_ifndef:
1018 case tok::pp_elifdef:
1019 case tok::pp_elifndef:
1026 case tok::pp_pragma:
1030 case tok::pp_warning:
1032 if (!
eof() && Style.isCpp())
1033 FormatTok->setFinalizedType(TT_AfterPPDirective);
1041void UnwrappedLineParser::conditionalCompilationCondition(
bool Unreachable) {
1042 size_t Line = CurrentLines->size();
1043 if (CurrentLines == &PreprocessorDirectives)
1044 Line += Lines.size();
1047 (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) {
1048 PPStack.push_back({PP_Unreachable,
Line});
1050 PPStack.push_back({PP_Conditional,
Line});
1054void UnwrappedLineParser::conditionalCompilationStart(
bool Unreachable) {
1056 assert(PPBranchLevel >= 0 && PPBranchLevel <= (
int)PPLevelBranchIndex.size());
1057 if (PPBranchLevel == (
int)PPLevelBranchIndex.size()) {
1058 PPLevelBranchIndex.push_back(0);
1059 PPLevelBranchCount.push_back(0);
1061 PPChainBranchIndex.push(Unreachable ? -1 : 0);
1062 bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
1063 conditionalCompilationCondition(Unreachable ||
Skip);
1066void UnwrappedLineParser::conditionalCompilationAlternative() {
1067 if (!PPStack.empty())
1069 assert(PPBranchLevel < (
int)PPLevelBranchIndex.size());
1070 if (!PPChainBranchIndex.empty())
1071 ++PPChainBranchIndex.top();
1072 conditionalCompilationCondition(
1073 PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
1074 PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());
1077void UnwrappedLineParser::conditionalCompilationEnd() {
1078 assert(PPBranchLevel < (
int)PPLevelBranchIndex.size());
1079 if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
1080 if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel])
1081 PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;
1084 if (PPBranchLevel > -1)
1086 if (!PPChainBranchIndex.empty())
1087 PPChainBranchIndex.pop();
1088 if (!PPStack.empty())
1092void UnwrappedLineParser::parsePPIf(
bool IfDef) {
1093 bool IfNDef = FormatTok->is(tok::pp_ifndef);
1095 bool Unreachable =
false;
1096 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText ==
"0"))
1098 if (IfDef && !IfNDef && FormatTok->TokenText ==
"SWIG")
1100 conditionalCompilationStart(Unreachable);
1104 bool MaybeIncludeGuard = IfNDef;
1105 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1106 for (
auto &
Line : Lines) {
1107 if (
Line.Tokens.front().Tok->isNot(tok::comment)) {
1108 MaybeIncludeGuard =
false;
1109 IncludeGuard = IG_Rejected;
1117 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1118 IncludeGuard = IG_IfNdefed;
1119 IncludeGuardToken = IfCondition;
1123void UnwrappedLineParser::parsePPElse() {
1125 if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
1126 IncludeGuard = IG_Rejected;
1128 assert(PPBranchLevel >= -1);
1129 if (PPBranchLevel == -1)
1130 conditionalCompilationStart(
true);
1131 conditionalCompilationAlternative();
1137void UnwrappedLineParser::parsePPEndIf() {
1138 conditionalCompilationEnd();
1142 if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&
1143 getIncludeGuardState(Style.IndentPPDirectives) == IG_Inited) {
1144 IncludeGuard = IG_Found;
1148void UnwrappedLineParser::parsePPDefine() {
1151 if (!FormatTok->Tok.getIdentifierInfo()) {
1152 IncludeGuard = IG_Rejected;
1153 IncludeGuardToken =
nullptr;
1158 bool MaybeIncludeGuard =
false;
1159 if (IncludeGuard == IG_IfNdefed &&
1160 IncludeGuardToken->TokenText == FormatTok->TokenText) {
1161 IncludeGuard = IG_Defined;
1162 IncludeGuardToken =
nullptr;
1163 for (
auto &
Line : Lines) {
1164 if (
Line.Tokens.front().Tok->isNoneOf(tok::comment, tok::hash)) {
1165 IncludeGuard = IG_Rejected;
1169 MaybeIncludeGuard = IncludeGuard == IG_Defined;
1177 FormatTok->Tok.setKind(tok::identifier);
1178 FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);
1182 if (MaybeIncludeGuard && !
eof())
1183 IncludeGuard = IG_Rejected;
1185 if (FormatTok->is(tok::l_paren) && !FormatTok->hasWhitespaceBefore())
1187 if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
1188 Line->Level += PPBranchLevel + 1;
1192 Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
1193 assert((
int)
Line->PPLevel >= 0);
1198 Line->InMacroBody =
true;
1200 if (!Style.SkipMacroDefinitionBody) {
1210 for (
auto *Comment : CommentsBeforeNextToken)
1211 Comment->Finalized =
true;
1214 FormatTok->Finalized =
true;
1215 FormatTok = Tokens->getNextToken();
1221void UnwrappedLineParser::parsePPPragma() {
1222 Line->InPragmaDirective =
true;
1226void UnwrappedLineParser::parsePPUnknown() {
1229 if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
1230 Line->Level += PPBranchLevel + 1;
1240 return Tok.isNoneOf(tok::semi, tok::l_brace,
1243 tok::period, tok::periodstar, tok::arrow, tok::arrowstar,
1244 tok::less, tok::greater, tok::slash, tok::percent,
1245 tok::lessless, tok::greatergreater, tok::equal,
1246 tok::plusequal, tok::minusequal, tok::starequal,
1247 tok::slashequal, tok::percentequal, tok::ampequal,
1248 tok::pipeequal, tok::caretequal, tok::greatergreaterequal,
1261 return FormatTok->
is(tok::identifier) &&
1276 FormatTok->
isOneOf(tok::kw_true, tok::kw_false) ||
1287 tok::kw_if, tok::kw_else,
1289 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
1291 tok::kw_switch, tok::kw_case,
1293 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.
kw_finally,
1295 tok::kw_const, tok::kw_class, Keywords.
kw_var, Keywords.
kw_let,
1303 return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
1304 tok::kw_unsigned, tok::kw_float, tok::kw_double,
1321 if (FuncName->
isNot(tok::identifier))
1329 Tok->isNoneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
1333 if (
Next->isNot(tok::star) && !
Next->Tok.getIdentifierInfo())
1337 if (!
Tok ||
Tok->isNot(tok::r_paren))
1341 if (!
Tok ||
Tok->isNot(tok::identifier))
1344 return Tok->Previous &&
Tok->Previous->isOneOf(tok::l_paren, tok::comma);
1347bool UnwrappedLineParser::parseModuleImport() {
1348 assert(FormatTok->is(Keywords.kw_import) &&
"'import' expected");
1350 if (
auto Token = Tokens->peekNextToken(
true);
1352 Token->
isNoneOf(tok::colon, tok::less, tok::string_literal)) {
1358 if (FormatTok->is(tok::colon)) {
1359 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1362 else if (FormatTok->is(tok::less)) {
1364 while (FormatTok->isNoneOf(tok::semi, tok::greater) && !
eof()) {
1367 if (FormatTok->isNot(tok::comment) &&
1368 !FormatTok->TokenText.starts_with(
"//")) {
1369 FormatTok->setFinalizedType(TT_ImplicitStringLiteral);
1374 if (FormatTok->is(tok::semi)) {
1392void UnwrappedLineParser::readTokenWithJavaScriptASI() {
1398 CommentsBeforeNextToken.empty()
1399 ?
Next->NewlinesBefore == 0
1400 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
1405 bool PreviousStartsTemplateExpr =
1407 if (PreviousMustBeValue ||
Previous->is(tok::r_paren)) {
1410 bool HasAt = llvm::any_of(
Line->Tokens, [](UnwrappedLineNode &LineNode) {
1411 return LineNode.Tok->is(tok::at);
1416 if (
Next->is(tok::exclaim) && PreviousMustBeValue)
1417 return addUnwrappedLine();
1419 bool NextEndsTemplateExpr =
1420 Next->is(TT_TemplateString) &&
Next->TokenText.starts_with(
"}");
1421 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
1422 (PreviousMustBeValue ||
1423 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
1424 tok::minusminus))) {
1425 return addUnwrappedLine();
1427 if ((PreviousMustBeValue ||
Previous->is(tok::r_paren)) &&
1429 return addUnwrappedLine();
1433void UnwrappedLineParser::parseStructuralElement(
1434 const FormatToken *OpeningBrace, IfStmtKind *IfKind,
1435 FormatToken **IfLeftBrace,
bool *HasDoWhile,
bool *HasLabel) {
1436 if (Style.isTableGen() && FormatTok->is(tok::pp_include)) {
1438 if (FormatTok->is(tok::string_literal))
1445 while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
1447 }
else if (Style.isVerilog()) {
1448 if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {
1449 parseForOrWhileLoop(
false);
1452 if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {
1453 parseForOrWhileLoop();
1456 if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
1457 Keywords.kw_assume, Keywords.kw_cover)) {
1458 parseIfThenElse(IfKind,
false,
true);
1464 if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
1465 Keywords.kw_unique0)) {
1467 }
else if (FormatTok->is(tok::l_paren) &&
1468 Tokens->peekNextToken()->is(tok::star)) {
1477 if (FormatTok->isAccessSpecifierKeyword()) {
1478 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
1481 parseAccessSpecifier();
1484 switch (FormatTok->Tok.getKind()) {
1487 if (FormatTok->is(tok::l_brace)) {
1488 FormatTok->setFinalizedType(TT_InlineASMBrace);
1490 while (FormatTok && !
eof()) {
1491 if (FormatTok->is(tok::r_brace)) {
1492 FormatTok->setFinalizedType(TT_InlineASMBrace);
1497 FormatTok->Finalized =
true;
1502 case tok::kw_namespace:
1506 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1517 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1521 parseForOrWhileLoop();
1524 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1532 case tok::kw_switch:
1533 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1539 case tok::kw_default: {
1541 if (Style.isVerilog())
1543 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1549 if (FormatTok->is(tok::colon)) {
1550 FormatTok->setFinalizedType(TT_CaseLabelColon);
1554 if (FormatTok->is(tok::arrow)) {
1555 FormatTok->setFinalizedType(TT_CaseLabelArrow);
1556 Default->setFinalizedType(TT_SwitchExpressionLabel);
1565 if (Style.Language == FormatStyle::LK_Proto) {
1569 if (Style.isVerilog()) {
1574 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1583 if (FormatTok->is(tok::kw_case))
1588 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1594 case tok::kw_extern:
1595 if (Style.isVerilog()) {
1598 parseVerilogExtern();
1602 if (FormatTok->is(tok::string_literal)) {
1604 if (FormatTok->is(tok::l_brace)) {
1605 if (Style.BraceWrapping.AfterExternBlock)
1609 unsigned AddLevels =
1610 (Style.IndentExternBlock == FormatStyle::IEBS_Indent) ||
1611 (Style.BraceWrapping.AfterExternBlock &&
1612 Style.IndentExternBlock ==
1613 FormatStyle::IEBS_AfterExternBlock)
1616 parseBlock(
true, AddLevels);
1622 case tok::kw_export:
1623 if (Style.isJavaScript()) {
1624 parseJavaScriptEs6ImportExport();
1627 if (Style.isVerilog()) {
1628 parseVerilogExtern();
1633 if (FormatTok->is(tok::kw_namespace)) {
1637 if (FormatTok->is(tok::l_brace)) {
1638 parseCppExportBlock();
1641 if (FormatTok->is(Keywords.kw_import) && parseModuleImport())
1645 case tok::kw_inline:
1647 if (FormatTok->is(tok::kw_namespace)) {
1652 case tok::identifier:
1653 if (FormatTok->is(TT_ForEachMacro)) {
1654 parseForOrWhileLoop();
1657 if (FormatTok->is(TT_MacroBlockBegin)) {
1658 parseBlock(
false, 1u,
1662 if (FormatTok->is(Keywords.kw_import)) {
1663 if (Style.isJavaScript()) {
1664 parseJavaScriptEs6ImportExport();
1667 if (Style.Language == FormatStyle::LK_Proto) {
1669 if (FormatTok->is(tok::kw_public))
1671 if (FormatTok->isNot(tok::string_literal))
1674 if (FormatTok->is(tok::semi))
1679 if (Style.isVerilog()) {
1680 parseVerilogExtern();
1683 if (IsCpp && parseModuleImport())
1686 if (IsCpp && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
1687 Keywords.kw_slots, Keywords.kw_qslots)) {
1689 if (FormatTok->is(tok::colon)) {
1695 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
1696 parseStatementMacro();
1699 if (IsCpp && FormatTok->is(TT_NamespaceMacro)) {
1707 if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&
1708 Tokens->peekNextToken()->is(tok::colon) && !
Line->MustBeDeclaration) {
1710 if (!
Line->InMacroBody || CurrentLines->size() > 1)
1711 Line->Tokens.begin()->Tok->MustBreakBefore =
true;
1712 FormatTok->setFinalizedType(TT_GotoLabelColon);
1713 parseLabel(!Style.IndentGotoLabels);
1718 if (Style.isJava() && FormatTok->is(Keywords.kw_record)) {
1719 parseRecord(
false,
true);
1729 bool SeenEqual =
false;
1730 for (
const bool InRequiresExpression =
1731 OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
1732 TT_CompoundRequirementLBrace);
1735 switch (FormatTok->Tok.getKind()) {
1738 if (FormatTok->is(tok::l_brace)) {
1743 if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) {
1747 switch (
bool IsAutoRelease =
false; FormatTok->Tok.getObjCKeywordID()) {
1748 case tok::objc_public:
1749 case tok::objc_protected:
1750 case tok::objc_package:
1751 case tok::objc_private:
1752 return parseAccessSpecifier();
1753 case tok::objc_interface:
1754 case tok::objc_implementation:
1755 return parseObjCInterfaceOrImplementation();
1756 case tok::objc_protocol:
1757 if (parseObjCProtocol())
1762 case tok::objc_optional:
1763 case tok::objc_required:
1767 case tok::objc_autoreleasepool:
1768 IsAutoRelease =
true;
1770 case tok::objc_synchronized:
1772 if (!IsAutoRelease && FormatTok->is(tok::l_paren)) {
1776 if (FormatTok->is(tok::l_brace)) {
1777 if (Style.BraceWrapping.AfterControlStatement ==
1778 FormatStyle::BWACS_Always) {
1794 case tok::kw_requires: {
1796 bool ParsedClause = parseRequires(SeenEqual);
1817 if (!IsCpp && !Style.isVerilog()) {
1822 case tok::kw_typedef:
1824 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1825 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
1826 Keywords.kw_CF_CLOSED_ENUM,
1827 Keywords.kw_NS_CLOSED_ENUM)) {
1832 if (Style.isVerilog()) {
1837 if (Style.isTableGen()) {
1844 case tok::kw_struct:
1846 if (parseStructLike())
1849 case tok::kw_decltype:
1851 if (FormatTok->is(tok::l_paren)) {
1853 if (FormatTok->Previous &&
1854 FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
1856 Line->SeenDecltypeAuto =
true;
1863 if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class))
1865 if (Style.isJavaScript() && FormatTok &&
1866 FormatTok->Tok.getIdentifierInfo()) {
1879 case tok::l_paren: {
1886 Tokens->peekNextToken(
true),
1893 case tok::kw_operator:
1895 if (FormatTok->isBinaryOperator())
1899 const auto *Prev = FormatTok->getPreviousNonComment();
1901 if (Prev && Prev->is(tok::identifier))
1904 if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {
1907 while (FormatTok->is(tok::star))
1911 if (FormatTok->is(tok::l_paren))
1914 if (FormatTok->is(tok::l_brace))
1919 if (InRequiresExpression)
1920 FormatTok->setFinalizedType(TT_BracedListLBrace);
1921 if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
1922 IsDecltypeAutoFunction =
Line->SeenDecltypeAuto;
1927 if (Style.isJava() &&
1928 Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
1931 if (Style.BraceWrapping.AfterControlStatement ==
1932 FormatStyle::BWACS_Always) {
1935 }
else if (Style.BraceWrapping.AfterFunction) {
1939 FormatTok->setFinalizedType(TT_FunctionLBrace);
1941 IsDecltypeAutoFunction =
false;
1949 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1955 if (Style.BraceWrapping.AfterFunction)
1959 case tok::identifier: {
1960 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&
1961 Line->MustBeDeclaration) {
1963 parseCSharpGenericTypeConstraint();
1966 if (FormatTok->is(TT_MacroBlockEnd)) {
1975 size_t TokenCount =
Line->Tokens.size();
1976 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&
1979 Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {
1980 tryToParseJSFunction();
1983 if ((Style.isJavaScript() || Style.isJava()) &&
1984 FormatTok->is(Keywords.kw_interface)) {
1985 if (Style.isJavaScript()) {
1990 unsigned StoredPosition = Tokens->getPosition();
1992 FormatTok = Tokens->setPosition(StoredPosition);
2003 if (Style.isVerilog()) {
2004 if (FormatTok->is(Keywords.kw_table)) {
2005 parseVerilogTable();
2008 if (Keywords.isVerilogBegin(*FormatTok) ||
2009 Keywords.isVerilogHierarchy(*FormatTok)) {
2016 if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
2017 if (parseStructLike())
2022 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
2023 parseStatementMacro();
2028 StringRef
Text = FormatTok->TokenText;
2035 if (Style.isJavaScript())
2038 auto OneTokenSoFar = [&]() {
2039 auto I =
Line->Tokens.begin(), E =
Line->Tokens.end();
2040 while (I != E && I->Tok->is(tok::comment))
2042 if (Style.isVerilog())
2043 while (I != E && I->Tok->is(tok::hash))
2045 return I != E && (++I == E);
2047 if (OneTokenSoFar()) {
2050 bool FunctionLike = FormatTok->is(tok::l_paren);
2054 bool FollowedByNewline =
2055 CommentsBeforeNextToken.empty()
2056 ? FormatTok->NewlinesBefore > 0
2057 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
2059 if (FollowedByNewline &&
2060 (
Text.size() >= 5 ||
2061 (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
2063 if (PreviousToken->isNot(TT_UntouchableMacroFunc))
2064 PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
2072 if ((Style.isJavaScript() || Style.isCSharp()) &&
2073 FormatTok->is(TT_FatArrow)) {
2074 tryToParseChildBlock();
2080 if (FormatTok->is(tok::l_brace)) {
2084 if (Style.isCSharp())
2085 FormatTok->setBlockKind(BK_BracedInit);
2088 if (Style.isTableGen() &&
2089 Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {
2090 FormatTok->setFinalizedType(TT_FunctionLBrace);
2091 parseBlock(
false, 1u,
2098 }
else if (Style.Language == FormatStyle::LK_Proto &&
2099 FormatTok->is(tok::less)) {
2101 parseBracedList(
true);
2108 if (Style.isCSharp() &&
2109 (Tokens->peekNextToken()->isAccessSpecifierKeyword() ||
2116 case tok::kw_switch:
2124 if (Style.Language == FormatStyle::LK_Proto) {
2129 if (Style.isVerilog()) {
2134 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2141 case tok::kw_default:
2143 if (Style.isVerilog()) {
2144 if (FormatTok->is(tok::colon)) {
2148 if (FormatTok->is(Keywords.kw_clocking)) {
2154 parseVerilogCaseLabel();
2160 if (Style.isVerilog()) {
2161 parseVerilogCaseLabel();
2167 if (FormatTok->is(tok::l_brace))
2168 FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
2177bool UnwrappedLineParser::tryToParsePropertyAccessor() {
2178 assert(FormatTok->is(tok::l_brace));
2179 if (!Style.isCSharp())
2182 if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))
2190 unsigned int StoredPosition = Tokens->getPosition();
2196 bool HasSpecialAccessor =
false;
2197 bool IsTrivialPropertyAccessor =
true;
2200 if (
const bool IsAccessorKeyword =
2201 Tok->
isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set);
2202 IsAccessorKeyword ||
Tok->isAccessSpecifierKeyword() ||
2203 Tok->
isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {
2204 if (IsAccessorKeyword)
2205 HasSpecialAccessor =
true;
2206 else if (
Tok->
is(tok::l_square))
2208 Tok = Tokens->getNextToken();
2212 IsTrivialPropertyAccessor =
false;
2217 Tokens->setPosition(StoredPosition);
2223 Tokens->setPosition(StoredPosition);
2224 if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)
2228 switch (FormatTok->Tok.getKind()) {
2231 if (FormatTok->is(tok::equal)) {
2232 while (!
eof() && FormatTok->isNot(tok::semi))
2245 if (FormatTok->is(TT_FatArrow)) {
2249 }
while (!
eof() && FormatTok->isNot(tok::semi));
2258 if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,
2260 !IsTrivialPropertyAccessor) {
2272bool UnwrappedLineParser::tryToParseLambda() {
2273 assert(FormatTok->is(tok::l_square));
2279 if (!tryToParseLambdaIntroducer())
2283 bool InTemplateParameterList =
false;
2285 while (FormatTok->isNot(tok::l_brace)) {
2286 if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {
2290 switch (FormatTok->Tok.getKind()) {
2294 parseParens(TT_PointerOrReference);
2300 assert(FormatTok->Previous);
2301 if (FormatTok->Previous->is(tok::r_square))
2302 InTemplateParameterList =
true;
2307 case tok::kw_struct:
2309 case tok::kw_template:
2310 case tok::kw_typename:
2314 case tok::kw_constexpr:
2315 case tok::kw_consteval:
2318 case tok::identifier:
2319 case tok::numeric_constant:
2320 case tok::coloncolon:
2321 case tok::kw_mutable:
2322 case tok::kw_noexcept:
2323 case tok::kw_static:
2348 case tok::equalequal:
2349 case tok::exclaimequal:
2350 case tok::greaterequal:
2351 case tok::lessequal:
2357 if (Arrow || InTemplateParameterList) {
2366 case tok::kw_requires:
2367 parseRequiresClause();
2370 if (!InTemplateParameterList)
2379 FormatTok->setFinalizedType(TT_LambdaLBrace);
2380 LSquare.setFinalizedType(TT_LambdaLSquare);
2383 Arrow->setFinalizedType(TT_LambdaArrow);
2385 NestedLambdas.push_back(
Line->SeenDecltypeAuto);
2387 assert(!NestedLambdas.empty());
2388 NestedLambdas.pop_back();
2393bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
2398 const auto *PrevPrev =
Previous->getPreviousNonComment();
2399 if (
Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts))
2407 if (!PrevPrev || PrevPrev->isNoneOf(tok::greater, tok::r_paren))
2411 Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
2412 tok::kw_co_return)) {
2416 if (LeftSquare->isCppStructuredBinding(IsCpp))
2418 if (FormatTok->is(tok::l_square) ||
tok::isLiteral(FormatTok->Tok.getKind()))
2420 if (FormatTok->is(tok::r_square)) {
2422 if (
Next->is(tok::greater))
2429void UnwrappedLineParser::tryToParseJSFunction() {
2430 assert(FormatTok->is(Keywords.kw_function));
2431 if (FormatTok->is(Keywords.kw_async))
2437 if (FormatTok->is(tok::star)) {
2438 FormatTok->setFinalizedType(TT_OverloadedOperator);
2443 if (FormatTok->is(tok::identifier))
2446 if (FormatTok->isNot(tok::l_paren))
2452 if (FormatTok->is(tok::colon)) {
2458 if (FormatTok->is(tok::l_brace))
2459 tryToParseBracedList();
2461 while (FormatTok->isNoneOf(tok::l_brace, tok::semi) && !
eof())
2465 if (FormatTok->is(tok::semi))
2471bool UnwrappedLineParser::tryToParseBracedList() {
2472 if (FormatTok->is(BK_Unknown))
2473 calculateBraceTypes();
2474 assert(FormatTok->isNot(BK_Unknown));
2475 if (FormatTok->is(BK_Block))
2482bool UnwrappedLineParser::tryToParseChildBlock() {
2483 assert(Style.isJavaScript() || Style.isCSharp());
2484 assert(FormatTok->is(TT_FatArrow));
2489 if (FormatTok->isNot(tok::l_brace))
2495bool UnwrappedLineParser::parseBracedList(
bool IsAngleBracket,
bool IsEnum) {
2496 assert(!IsAngleBracket || !IsEnum);
2497 bool HasError =
false;
2502 if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
2503 tryToParseChildBlock()) {
2506 if (Style.isJavaScript()) {
2507 if (FormatTok->is(Keywords.kw_function)) {
2508 tryToParseJSFunction();
2511 if (FormatTok->is(tok::l_brace)) {
2513 if (tryToParseBracedList())
2518 if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
2520 FormatTok->setBlockKind(BK_Block);
2521 if (!Style.AllowShortEnumsOnASingleLine)
2527 switch (FormatTok->Tok.getKind()) {
2529 if (Style.isCSharp())
2538 if (Style.isJavaScript()) {
2539 if (FormatTok->is(tok::l_brace))
2547 FormatTok->setBlockKind(BK_BracedInit);
2548 if (!IsAngleBracket) {
2549 auto *Prev = FormatTok->Previous;
2550 if (Prev && Prev->is(tok::greater))
2551 Prev->setFinalizedType(TT_TemplateCloser);
2559 parseBracedList(
true);
2566 if (Style.isJavaScript()) {
2577 if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
2580 case tok::kw_requires:
2581 parseRequiresExpression();
2596bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType,
2598 assert(FormatTok->is(tok::l_paren) &&
"'(' expected.");
2599 auto *LParen = FormatTok;
2600 auto *Prev = FormatTok->Previous;
2601 bool SeenComma =
false;
2602 bool SeenEqual =
false;
2603 bool MightBeFoldExpr =
false;
2605 const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
2606 if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
2609 switch (FormatTok->Tok.getKind()) {
2611 if (parseParens(AmpAmpTokenType, InMacroCall))
2613 if (Style.isJava() && FormatTok->is(tok::l_brace))
2616 case tok::r_paren: {
2617 auto *RParen = FormatTok;
2620 auto OptionalParens = [&] {
2621 if (Style.RemoveParentheses == FormatStyle::RPS_Leave ||
2622 MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
2623 Line->InMacroBody || RParen->getPreviousNonComment() == LParen) {
2626 const bool DoubleParens =
2627 Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);
2629 const auto *PrevPrev = Prev->getPreviousNonComment();
2630 const bool Excluded =
2632 (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2634 (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2635 PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2639 const bool CommaSeparated =
2640 Prev->isOneOf(tok::l_paren, tok::comma) &&
2641 FormatTok->isOneOf(tok::comma, tok::r_paren);
2642 if (CommaSeparated &&
2644 !Prev->endsSequence(tok::comma, tok::ellipsis) &&
2646 !(FormatTok->is(tok::comma) &&
2647 Tokens->peekNextToken()->is(tok::ellipsis))) {
2650 const bool ReturnParens =
2651 Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
2652 ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2653 (!NestedLambdas.empty() && !NestedLambdas.back())) &&
2654 Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
2655 FormatTok->is(tok::semi);
2661 if (OptionalParens()) {
2662 LParen->Optional =
true;
2663 RParen->Optional =
true;
2664 }
else if (Prev->is(TT_TypenameMacro)) {
2665 LParen->setFinalizedType(TT_TypeDeclarationParen);
2666 RParen->setFinalizedType(TT_TypeDeclarationParen);
2667 }
else if (Prev->is(tok::greater) && RParen->Previous == LParen) {
2668 Prev->setFinalizedType(TT_TemplateCloser);
2669 }
else if (FormatTok->is(tok::l_brace) && Prev->is(tok::amp) &&
2671 FormatTok->setBlockKind(BK_BracedInit);
2683 if (!tryToParseBracedList())
2688 if (FormatTok->is(tok::l_brace)) {
2698 MightBeFoldExpr =
true;
2703 if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
2704 tryToParseChildBlock();
2709 if (Style.isJavaScript())
2714 case tok::identifier:
2715 if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))
2716 tryToParseJSFunction();
2720 case tok::kw_switch:
2726 case tok::kw_requires:
2727 parseRequiresExpression();
2730 if (AmpAmpTokenType != TT_Unknown)
2731 FormatTok->setFinalizedType(AmpAmpTokenType);
2743 assert(FormatTok->is(tok::l_square) &&
"'[' expected.");
2744 if (tryToParseLambda())
2748 switch (FormatTok->Tok.getKind()) {
2761 case tok::l_brace: {
2762 if (!tryToParseBracedList())
2769 if (FormatTok->is(tok::l_brace)) {
2781void UnwrappedLineParser::keepAncestorBraces() {
2782 if (!Style.RemoveBracesLLVM)
2785 const int MaxNestingLevels = 2;
2786 const int Size = NestedTooDeep.size();
2787 if (Size >= MaxNestingLevels)
2788 NestedTooDeep[
Size - MaxNestingLevels] =
true;
2789 NestedTooDeep.push_back(
false);
2793 for (
const auto &
Token : llvm::reverse(
Line.Tokens))
2800void UnwrappedLineParser::parseUnbracedBody(
bool CheckEOF) {
2803 if (Style.InsertBraces && !
Line->InPPDirective && !
Line->Tokens.empty() &&
2804 PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
2805 Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never
2806 ? getLastNonComment(*
Line)
2809 if (
Tok->BraceCount < 0) {
2810 assert(
Tok->BraceCount == -1);
2813 Tok->BraceCount = -1;
2819 ++
Line->UnbracedBodyLevel;
2820 parseStructuralElement();
2821 --
Line->UnbracedBodyLevel;
2824 assert(!
Line->InPPDirective);
2826 for (
const auto &L : llvm::reverse(*CurrentLines)) {
2828 Tok = L.Tokens.back().Tok;
2836 if (CheckEOF &&
eof())
2846 assert(LeftBrace->
is(tok::l_brace));
2854 assert(RightBrace->
is(tok::r_brace));
2862void UnwrappedLineParser::handleAttributes() {
2864 if (FormatTok->isAttribute())
2866 else if (FormatTok->is(tok::l_square))
2867 handleCppAttributes();
2870bool UnwrappedLineParser::handleCppAttributes() {
2872 assert(FormatTok->is(tok::l_square));
2873 if (!tryToParseSimpleAttribute())
2880bool UnwrappedLineParser::isBlockBegin(
const FormatToken &
Tok)
const {
2883 return Style.isVerilog() ? Keywords.isVerilogBegin(
Tok)
2884 :
Tok.
is(tok::l_brace);
2887FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
2889 bool IsVerilogAssert) {
2890 assert((FormatTok->is(tok::kw_if) ||
2891 (Style.isVerilog() &&
2892 FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
2893 Keywords.kw_assume, Keywords.kw_cover))) &&
2897 if (IsVerilogAssert) {
2899 if (FormatTok->is(Keywords.kw_verilogHash)) {
2901 if (FormatTok->is(tok::numeric_constant))
2903 }
else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,
2904 Keywords.kw_sequence)) {
2910 if (Style.isTableGen()) {
2911 while (!
eof() && FormatTok->isNot(Keywords.kw_then)) {
2918 if (FormatTok->is(tok::exclaim))
2921 bool KeepIfBraces =
true;
2922 if (FormatTok->is(tok::kw_consteval)) {
2925 KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;
2926 if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
2928 if (FormatTok->is(tok::l_paren)) {
2929 FormatTok->setFinalizedType(TT_ConditionLParen);
2935 if (IsVerilogAssert && FormatTok->is(tok::semi)) {
2941 bool NeedsUnwrappedLine =
false;
2942 keepAncestorBraces();
2945 IfStmtKind IfBlockKind = IfStmtKind::NotIf;
2947 if (isBlockBegin(*FormatTok)) {
2948 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
2949 IfLeftBrace = FormatTok;
2950 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
2951 parseBlock(
false, 1u,
2952 true, KeepIfBraces, &IfBlockKind);
2953 setPreviousRBraceType(TT_ControlStatementRBrace);
2954 if (Style.BraceWrapping.BeforeElse)
2957 NeedsUnwrappedLine =
true;
2958 }
else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {
2961 parseUnbracedBody();
2964 if (Style.RemoveBracesLLVM) {
2965 assert(!NestedTooDeep.empty());
2966 KeepIfBraces = KeepIfBraces ||
2967 (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
2968 NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
2969 IfBlockKind == IfStmtKind::IfElseIf;
2972 bool KeepElseBraces = KeepIfBraces;
2974 IfStmtKind
Kind = IfStmtKind::IfOnly;
2976 if (FormatTok->is(tok::kw_else)) {
2977 if (Style.RemoveBracesLLVM) {
2978 NestedTooDeep.back() =
false;
2979 Kind = IfStmtKind::IfElse;
2983 if (isBlockBegin(*FormatTok)) {
2984 const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
2985 FormatTok->setFinalizedType(TT_ElseLBrace);
2986 ElseLeftBrace = FormatTok;
2987 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
2988 IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
2990 parseBlock(
false, 1u,
2991 true, KeepElseBraces, &ElseBlockKind);
2992 setPreviousRBraceType(TT_ElseRBrace);
2993 if (FormatTok->is(tok::kw_else)) {
2994 KeepElseBraces = KeepElseBraces ||
2995 ElseBlockKind == IfStmtKind::IfOnly ||
2996 ElseBlockKind == IfStmtKind::IfElseIf;
2997 }
else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
2998 KeepElseBraces =
true;
2999 assert(ElseLeftBrace->MatchingParen);
3003 }
else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {
3006 const bool IsPrecededByComment =
Previous->is(tok::comment);
3007 if (IsPrecededByComment) {
3011 bool TooDeep =
true;
3012 if (Style.RemoveBracesLLVM) {
3013 Kind = IfStmtKind::IfElseIf;
3014 TooDeep = NestedTooDeep.pop_back_val();
3016 ElseLeftBrace = parseIfThenElse(
nullptr, KeepIfBraces);
3017 if (Style.RemoveBracesLLVM)
3018 NestedTooDeep.push_back(TooDeep);
3019 if (IsPrecededByComment)
3022 parseUnbracedBody(
true);
3025 KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
3026 if (NeedsUnwrappedLine)
3030 if (!Style.RemoveBracesLLVM)
3033 assert(!NestedTooDeep.empty());
3034 KeepElseBraces = KeepElseBraces ||
3035 (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
3036 NestedTooDeep.back();
3038 NestedTooDeep.pop_back();
3040 if (!KeepIfBraces && !KeepElseBraces) {
3043 }
else if (IfLeftBrace) {
3044 FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
3046 assert(IfRightBrace->MatchingParen == IfLeftBrace);
3047 assert(!IfLeftBrace->Optional);
3048 assert(!IfRightBrace->Optional);
3049 IfLeftBrace->MatchingParen =
nullptr;
3050 IfRightBrace->MatchingParen =
nullptr;
3060void UnwrappedLineParser::parseTryCatch() {
3061 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) &&
"'try' expected");
3063 bool NeedsUnwrappedLine =
false;
3064 bool HasCtorInitializer =
false;
3065 if (FormatTok->is(tok::colon)) {
3066 auto *Colon = FormatTok;
3069 if (FormatTok->is(tok::identifier)) {
3070 HasCtorInitializer =
true;
3071 Colon->setFinalizedType(TT_CtorInitializerColon);
3076 while (FormatTok->is(tok::comma))
3079 while (FormatTok->is(tok::identifier)) {
3081 if (FormatTok->is(tok::l_paren)) {
3083 }
else if (FormatTok->is(tok::l_brace)) {
3090 while (FormatTok->is(tok::comma))
3095 if (Style.isJava() && FormatTok->is(tok::l_paren))
3098 keepAncestorBraces();
3100 if (FormatTok->is(tok::l_brace)) {
3101 if (HasCtorInitializer)
3102 FormatTok->setFinalizedType(TT_FunctionLBrace);
3103 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3105 if (Style.BraceWrapping.BeforeCatch)
3108 NeedsUnwrappedLine =
true;
3109 }
else if (FormatTok->isNot(tok::kw_catch)) {
3115 parseStructuralElement();
3118 for (
bool SeenCatch =
false;;) {
3119 if (FormatTok->is(tok::at))
3121 if (FormatTok->isNoneOf(tok::kw_catch, Keywords.kw___except,
3122 tok::kw___finally, tok::objc_catch,
3123 tok::objc_finally) &&
3124 !((Style.isJava() || Style.isJavaScript()) &&
3125 FormatTok->is(Keywords.kw_finally))) {
3128 if (FormatTok->is(tok::kw_catch))
3131 while (FormatTok->isNot(tok::l_brace)) {
3132 if (FormatTok->is(tok::l_paren)) {
3136 if (FormatTok->isOneOf(tok::semi, tok::r_brace) ||
eof()) {
3137 if (Style.RemoveBracesLLVM)
3138 NestedTooDeep.pop_back();
3144 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3147 NeedsUnwrappedLine =
false;
3148 Line->MustBeDeclaration =
false;
3149 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3151 if (Style.BraceWrapping.BeforeCatch)
3154 NeedsUnwrappedLine =
true;
3157 if (Style.RemoveBracesLLVM)
3158 NestedTooDeep.pop_back();
3160 if (NeedsUnwrappedLine)
3164void UnwrappedLineParser::parseNamespaceOrExportBlock(
unsigned AddLevels) {
3165 bool ManageWhitesmithsBraces =
3166 AddLevels == 0u && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
3170 if (ManageWhitesmithsBraces)
3175 parseBlock(
true, AddLevels,
true,
3176 true,
nullptr, ManageWhitesmithsBraces);
3178 addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
3180 if (ManageWhitesmithsBraces)
3184void UnwrappedLineParser::parseNamespace() {
3185 assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
3186 "'namespace' expected");
3190 if (InitialToken.is(TT_NamespaceMacro)) {
3193 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
3194 tok::l_square, tok::period, tok::l_paren) ||
3195 (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
3196 if (FormatTok->is(tok::l_square))
3198 else if (FormatTok->is(tok::l_paren))
3204 if (FormatTok->is(tok::l_brace)) {
3205 FormatTok->setFinalizedType(TT_NamespaceLBrace);
3210 unsigned AddLevels =
3211 Style.NamespaceIndentation == FormatStyle::NI_All ||
3212 (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
3213 DeclarationScopeStack.size() > 1)
3216 parseNamespaceOrExportBlock(AddLevels);
3221void UnwrappedLineParser::parseCppExportBlock() {
3222 parseNamespaceOrExportBlock(Style.IndentExportBlock ? 1 : 0);
3225void UnwrappedLineParser::parseNew() {
3226 assert(FormatTok->is(tok::kw_new) &&
"'new' expected");
3229 if (Style.isCSharp()) {
3232 if (FormatTok->is(tok::l_paren))
3236 if (FormatTok->is(tok::l_brace))
3239 if (FormatTok->isOneOf(tok::semi, tok::comma))
3246 if (!Style.isJava())
3252 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
3256 if (FormatTok->is(tok::l_paren)) {
3260 if (FormatTok->is(tok::l_brace))
3268void UnwrappedLineParser::parseLoopBody(
bool KeepBraces,
bool WrapRightBrace) {
3269 keepAncestorBraces();
3271 if (isBlockBegin(*FormatTok)) {
3272 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3274 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3275 parseBlock(
false, 1u,
3277 setPreviousRBraceType(TT_ControlStatementRBrace);
3279 assert(!NestedTooDeep.empty());
3280 if (!NestedTooDeep.back())
3286 parseUnbracedBody();
3290 NestedTooDeep.pop_back();
3293void UnwrappedLineParser::parseForOrWhileLoop(
bool HasParens) {
3294 assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||
3295 (Style.isVerilog() &&
3296 FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,
3297 Keywords.kw_always_ff, Keywords.kw_always_latch,
3298 Keywords.kw_final, Keywords.kw_initial,
3299 Keywords.kw_foreach, Keywords.kw_forever,
3300 Keywords.kw_repeat))) &&
3301 "'for', 'while' or foreach macro expected");
3302 const bool KeepBraces = !Style.RemoveBracesLLVM ||
3303 FormatTok->isNoneOf(tok::kw_for, tok::kw_while);
3307 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
3309 if (IsCpp && FormatTok->is(tok::kw_co_await))
3311 if (HasParens && FormatTok->is(tok::l_paren)) {
3315 if (Style.isVerilog())
3316 FormatTok->setFinalizedType(TT_ConditionLParen);
3320 if (Style.isVerilog()) {
3322 parseVerilogSensitivityList();
3323 }
else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&
3324 Tokens->getPreviousToken()->is(tok::r_paren)) {
3331 parseLoopBody(KeepBraces,
true);
3334void UnwrappedLineParser::parseDoWhile() {
3335 assert(FormatTok->is(tok::kw_do) &&
"'do' expected");
3338 parseLoopBody(
true, Style.BraceWrapping.BeforeWhile);
3341 if (FormatTok->isNot(tok::kw_while)) {
3346 FormatTok->setFinalizedType(TT_DoWhile);
3350 if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)
3354 parseStructuralElement();
3357void UnwrappedLineParser::parseLabel(
bool LeftAlignLabel) {
3359 unsigned OldLineLevel =
Line->Level;
3363 else if (
Line->Level > 1 || (!
Line->InPPDirective &&
Line->Level > 0))
3366 if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
3367 FormatTok->is(tok::l_brace)) {
3369 CompoundStatementIndenter Indenter(
this,
Line->Level,
3370 Style.BraceWrapping.AfterCaseLabel,
3371 Style.BraceWrapping.IndentBraces);
3373 if (FormatTok->is(tok::kw_break)) {
3374 if (Style.BraceWrapping.AfterControlStatement ==
3375 FormatStyle::BWACS_Always) {
3377 if (!Style.IndentCaseBlocks &&
3378 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
3382 parseStructuralElement();
3386 if (FormatTok->is(tok::semi))
3390 Line->Level = OldLineLevel;
3391 if (FormatTok->isNot(tok::l_brace)) {
3392 parseStructuralElement();
3397void UnwrappedLineParser::parseCaseLabel() {
3398 assert(FormatTok->is(tok::kw_case) &&
"'case' expected");
3399 auto *Case = FormatTok;
3404 if (FormatTok->is(tok::colon)) {
3405 FormatTok->setFinalizedType(TT_CaseLabelColon);
3408 if (Style.isJava() && FormatTok->is(tok::arrow)) {
3409 FormatTok->setFinalizedType(TT_CaseLabelArrow);
3410 Case->setFinalizedType(TT_SwitchExpressionLabel);
3417void UnwrappedLineParser::parseSwitch(
bool IsExpr) {
3418 assert(FormatTok->is(tok::kw_switch) &&
"'switch' expected");
3420 if (FormatTok->is(tok::l_paren))
3423 keepAncestorBraces();
3425 if (FormatTok->is(tok::l_brace)) {
3426 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3427 FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
3428 : TT_ControlStatementLBrace);
3433 setPreviousRBraceType(TT_ControlStatementRBrace);
3439 parseStructuralElement();
3443 if (Style.RemoveBracesLLVM)
3444 NestedTooDeep.pop_back();
3447void UnwrappedLineParser::parseAccessSpecifier() {
3450 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
3453 if (FormatTok->is(tok::colon))
3461bool UnwrappedLineParser::parseRequires(
bool SeenEqual) {
3462 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3466 switch (Tokens->peekNextToken(
true)->Tok.getKind()) {
3469 parseRequiresExpression();
3476 parseRequiresClause();
3487 auto *PreviousNonComment = FormatTok->getPreviousNonComment();
3489 if (!PreviousNonComment ||
3490 PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
3493 parseRequiresClause();
3497 switch (PreviousNonComment->Tok.getKind()) {
3500 case tok::kw_noexcept:
3505 parseRequiresClause();
3514 auto PrevPrev = PreviousNonComment->getPreviousNonComment();
3515 if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {
3516 parseRequiresClause();
3522 if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
3524 parseRequiresClause();
3528 parseRequiresExpression();
3538 unsigned StoredPosition = Tokens->getPosition();
3541 auto PeekNext = [&Lookahead, &NextToken,
this] {
3543 NextToken = Tokens->getNextToken();
3546 bool FoundType =
false;
3547 bool LastWasColonColon =
false;
3550 for (; Lookahead < 50; PeekNext()) {
3551 switch (NextToken->Tok.getKind()) {
3552 case tok::kw_volatile:
3555 if (OpenAngles == 0) {
3556 FormatTok = Tokens->setPosition(StoredPosition);
3557 parseRequiresExpression();
3565 case tok::coloncolon:
3566 LastWasColonColon =
true;
3568 case tok::kw_decltype:
3569 case tok::identifier:
3570 if (FoundType && !LastWasColonColon && OpenAngles == 0) {
3571 FormatTok = Tokens->setPosition(StoredPosition);
3572 parseRequiresExpression();
3576 LastWasColonColon =
false;
3585 if (NextToken->isTypeName(LangOpts)) {
3586 FormatTok = Tokens->setPosition(StoredPosition);
3587 parseRequiresExpression();
3594 FormatTok = Tokens->setPosition(StoredPosition);
3595 parseRequiresClause();
3604void UnwrappedLineParser::parseRequiresClause() {
3605 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3610 bool InRequiresExpression =
3611 !FormatTok->Previous ||
3612 FormatTok->Previous->is(TT_RequiresExpressionLBrace);
3614 FormatTok->setFinalizedType(InRequiresExpression
3615 ? TT_RequiresClauseInARequiresExpression
3616 : TT_RequiresClause);
3621 parseConstraintExpression();
3623 if (!InRequiresExpression && FormatTok->Previous)
3624 FormatTok->Previous->ClosesRequiresClause =
true;
3632void UnwrappedLineParser::parseRequiresExpression() {
3633 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3635 FormatTok->setFinalizedType(TT_RequiresExpression);
3638 if (FormatTok->is(tok::l_paren)) {
3639 FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
3643 if (FormatTok->is(tok::l_brace)) {
3644 FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
3653void UnwrappedLineParser::parseConstraintExpression() {
3660 bool LambdaNextTimeAllowed =
true;
3670 bool TopLevelParensAllowed =
true;
3673 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed,
false);
3675 switch (FormatTok->Tok.getKind()) {
3676 case tok::kw_requires:
3677 parseRequiresExpression();
3681 if (!TopLevelParensAllowed)
3683 parseParens(TT_BinaryOperator);
3684 TopLevelParensAllowed =
false;
3688 if (!LambdaThisTimeAllowed || !tryToParseLambda())
3695 case tok::kw_struct:
3705 FormatTok->setFinalizedType(TT_BinaryOperator);
3707 LambdaNextTimeAllowed =
true;
3708 TopLevelParensAllowed =
true;
3713 LambdaNextTimeAllowed = LambdaThisTimeAllowed;
3717 case tok::kw_sizeof:
3719 case tok::greaterequal:
3720 case tok::greatergreater:
3722 case tok::lessequal:
3724 case tok::equalequal:
3726 case tok::exclaimequal:
3731 LambdaNextTimeAllowed =
true;
3732 TopLevelParensAllowed =
true;
3737 case tok::numeric_constant:
3738 case tok::coloncolon:
3741 TopLevelParensAllowed =
false;
3746 case tok::kw_static_cast:
3747 case tok::kw_const_cast:
3748 case tok::kw_reinterpret_cast:
3749 case tok::kw_dynamic_cast:
3751 if (FormatTok->isNot(tok::less))
3755 parseBracedList(
true);
3759 if (!FormatTok->Tok.getIdentifierInfo()) {
3769 assert(FormatTok->Previous);
3770 switch (FormatTok->Previous->Tok.getKind()) {
3771 case tok::coloncolon:
3775 case tok::kw_requires:
3784 if (FormatTok->is(tok::less)) {
3786 parseBracedList(
true);
3788 TopLevelParensAllowed =
false;
3794bool UnwrappedLineParser::parseEnum() {
3798 if (FormatTok->is(tok::kw_enum))
3804 if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
3808 if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))
3813 if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
3815 while (FormatTok->is(tok::l_square))
3816 if (!handleCppAttributes())
3820 while (FormatTok->Tok.getIdentifierInfo() ||
3821 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
3822 tok::greater, tok::comma, tok::question,
3824 if (Style.isVerilog()) {
3825 FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
3828 while (FormatTok->is(tok::l_square))
3834 if (FormatTok->is(tok::l_paren))
3836 if (FormatTok->is(tok::identifier)) {
3840 if (IsCpp && FormatTok->is(tok::identifier))
3846 if (FormatTok->isNot(tok::l_brace))
3848 FormatTok->setFinalizedType(TT_EnumLBrace);
3849 FormatTok->setBlockKind(BK_Block);
3851 if (Style.isJava()) {
3853 parseJavaEnumBody();
3856 if (Style.Language == FormatStyle::LK_Proto) {
3861 if (!Style.AllowShortEnumsOnASingleLine &&
3867 if (!Style.AllowShortEnumsOnASingleLine) {
3871 bool HasError = !parseBracedList(
false,
true);
3872 if (!Style.AllowShortEnumsOnASingleLine)
3875 if (FormatTok->is(tok::semi))
3879 setPreviousRBraceType(TT_EnumRBrace);
3887bool UnwrappedLineParser::parseStructLike() {
3892 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) {
3893 if (FormatTok->is(tok::semi))
3904class ScopedTokenPosition {
3905 unsigned StoredPosition;
3906 FormatTokenSource *Tokens;
3909 ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
3910 assert(Tokens &&
"Tokens expected to not be null");
3911 StoredPosition = Tokens->getPosition();
3914 ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
3920bool UnwrappedLineParser::tryToParseSimpleAttribute() {
3921 ScopedTokenPosition AutoPosition(Tokens);
3929 if (
Tok->
is(tok::r_square))
3931 Tok = Tokens->getNextToken();
3933 if (
Tok->
is(tok::eof))
3935 Tok = Tokens->getNextToken();
3938 Tok = Tokens->getNextToken();
3939 if (
Tok->
is(tok::semi))
3944void UnwrappedLineParser::parseJavaEnumBody() {
3945 assert(FormatTok->is(tok::l_brace));
3951 unsigned StoredPosition = Tokens->getPosition();
3952 bool IsSimple =
true;
3955 if (
Tok->
is(tok::r_brace))
3963 Tok = Tokens->getNextToken();
3965 FormatTok = Tokens->setPosition(StoredPosition);
3982 if (FormatTok->is(tok::l_brace)) {
3984 parseBlock(
true, 1u,
3986 }
else if (FormatTok->is(tok::l_paren)) {
3988 }
else if (FormatTok->is(tok::comma)) {
3991 }
else if (FormatTok->is(tok::semi)) {
3995 }
else if (FormatTok->is(tok::r_brace)) {
4004 parseLevel(OpeningBrace);
4010void UnwrappedLineParser::parseRecord(
bool ParseAsExpr,
bool IsJavaRecord) {
4011 assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record));
4016 IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok :
nullptr;
4017 bool IsDerived =
false;
4019 return Tok->
is(tok::identifier) &&
Tok->TokenText !=
Tok->TokenText.upper();
4023 bool JSPastExtendsOrImplements =
false;
4027 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
4028 tok::kw_alignas, tok::l_square) ||
4029 FormatTok->isAttribute() ||
4030 ((Style.isJava() || Style.isJavaScript()) &&
4031 FormatTok->isOneOf(tok::period, tok::comma))) {
4032 if (Style.isJavaScript() &&
4033 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
4034 JSPastExtendsOrImplements =
true;
4039 if (FormatTok->is(tok::l_brace)) {
4040 tryToParseBracedList();
4044 if (FormatTok->is(tok::l_square) && handleCppAttributes())
4048 switch (FormatTok->Tok.getKind()) {
4051 if (IsJavaRecord || !IsNonMacroIdentifier(
Previous) ||
4053 Previous->Previous == &InitialToken) {
4057 case tok::coloncolon:
4061 if (JSPastExtendsOrImplements || ClassName ||
4072 auto IsListInitialization = [&] {
4073 if (!ClassName || IsDerived || JSPastExtendsOrImplements)
4075 assert(FormatTok->is(tok::l_brace));
4076 const auto *Prev = FormatTok->getPreviousNonComment();
4078 return Prev != ClassName && Prev->is(tok::identifier) &&
4079 Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
4082 if (FormatTok->isOneOf(tok::colon, tok::less)) {
4083 int AngleNestingLevel = 0;
4085 if (FormatTok->is(tok::less))
4086 ++AngleNestingLevel;
4087 else if (FormatTok->is(tok::greater))
4088 --AngleNestingLevel;
4090 if (AngleNestingLevel == 0) {
4091 if (FormatTok->is(tok::colon)) {
4093 }
else if (!IsDerived && FormatTok->is(tok::identifier) &&
4094 FormatTok->Previous->is(tok::coloncolon)) {
4095 ClassName = FormatTok;
4096 }
else if (FormatTok->is(tok::l_paren) &&
4097 IsNonMacroIdentifier(FormatTok->Previous)) {
4101 if (FormatTok->is(tok::l_brace)) {
4102 if (AngleNestingLevel == 0 && IsListInitialization())
4104 calculateBraceTypes(
true);
4105 if (!tryToParseBracedList())
4108 if (FormatTok->is(tok::l_square)) {
4111 !
Previous->isTypeOrIdentifier(LangOpts))) {
4114 if (!tryToParseLambda())
4121 if (FormatTok->is(tok::semi))
4123 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {
4126 parseCSharpGenericTypeConstraint();
4133 auto GetBraceTypes =
4134 [](
const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {
4135 switch (RecordTok.Tok.getKind()) {
4137 return {TT_ClassLBrace, TT_ClassRBrace};
4138 case tok::kw_struct:
4139 return {TT_StructLBrace, TT_StructRBrace};
4141 return {TT_UnionLBrace, TT_UnionRBrace};
4144 return {TT_RecordLBrace, TT_RecordRBrace};
4147 if (FormatTok->is(tok::l_brace)) {
4148 if (IsListInitialization())
4151 ClassName->setFinalizedType(TT_ClassHeadName);
4152 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
4153 FormatTok->setFinalizedType(OpenBraceType);
4160 unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;
4161 parseBlock(
true, AddLevels,
false);
4163 setPreviousRBraceType(ClosingBraceType);
4170void UnwrappedLineParser::parseObjCMethod() {
4171 assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
4172 "'(' or identifier expected.");
4174 if (FormatTok->is(tok::semi)) {
4178 }
else if (FormatTok->is(tok::l_brace)) {
4179 if (Style.BraceWrapping.AfterFunction)
4190void UnwrappedLineParser::parseObjCProtocolList() {
4191 assert(FormatTok->is(tok::less) &&
"'<' expected.");
4195 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4197 }
while (!
eof() && FormatTok->isNot(tok::greater));
4201void UnwrappedLineParser::parseObjCUntilAtEnd() {
4203 if (FormatTok->is(tok::objc_end)) {
4208 if (FormatTok->is(tok::l_brace)) {
4212 }
else if (FormatTok->is(tok::r_brace)) {
4216 }
else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
4220 parseStructuralElement();
4225void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
4226 assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation));
4232 if (FormatTok->is(tok::less))
4233 parseObjCLightweightGenerics();
4234 if (FormatTok->is(tok::colon)) {
4238 if (FormatTok->is(tok::less))
4239 parseObjCLightweightGenerics();
4240 }
else if (FormatTok->is(tok::l_paren)) {
4245 if (FormatTok->is(tok::less))
4246 parseObjCProtocolList();
4248 if (FormatTok->is(tok::l_brace)) {
4249 if (Style.BraceWrapping.AfterObjCDeclaration)
4258 parseObjCUntilAtEnd();
4261void UnwrappedLineParser::parseObjCLightweightGenerics() {
4262 assert(FormatTok->is(tok::less));
4270 unsigned NumOpenAngles = 1;
4274 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4276 if (FormatTok->is(tok::less)) {
4278 }
else if (FormatTok->is(tok::greater)) {
4279 assert(NumOpenAngles > 0 &&
"'>' makes NumOpenAngles negative");
4282 }
while (!
eof() && NumOpenAngles != 0);
4288bool UnwrappedLineParser::parseObjCProtocol() {
4289 assert(FormatTok->is(tok::objc_protocol));
4292 if (FormatTok->is(tok::l_paren)) {
4304 if (FormatTok->is(tok::less))
4305 parseObjCProtocolList();
4308 if (FormatTok->is(tok::semi)) {
4315 parseObjCUntilAtEnd();
4319void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
4320 bool IsImport = FormatTok->is(Keywords.kw_import);
4321 assert(IsImport || FormatTok->is(tok::kw_export));
4325 if (FormatTok->is(tok::kw_default))
4331 if (FormatTok->is(Keywords.kw_async))
4333 if (FormatTok->is(Keywords.kw_function)) {
4342 if (!IsImport && FormatTok->isNoneOf(tok::l_brace, tok::star) &&
4343 !FormatTok->isStringLiteral() &&
4344 !(FormatTok->is(Keywords.kw_type) &&
4345 Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {
4350 if (FormatTok->is(tok::semi))
4352 if (
Line->Tokens.empty()) {
4357 if (FormatTok->is(tok::l_brace)) {
4358 FormatTok->setBlockKind(BK_Block);
4367void UnwrappedLineParser::parseStatementMacro() {
4369 if (FormatTok->is(tok::l_paren))
4371 if (FormatTok->is(tok::semi))
4376void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
4379 if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
4380 tok::coloncolon, tok::hash) ||
4381 Keywords.isVerilogIdentifier(*FormatTok)) {
4383 }
else if (FormatTok->is(tok::l_square)) {
4391void UnwrappedLineParser::parseVerilogSensitivityList() {
4392 if (FormatTok->isNot(tok::at))
4396 if (FormatTok->is(tok::at))
4398 switch (FormatTok->Tok.getKind()) {
4406 parseVerilogHierarchyIdentifier();
4411unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
4412 unsigned AddLevels = 0;
4414 if (FormatTok->is(Keywords.kw_clocking)) {
4416 if (Keywords.isVerilogIdentifier(*FormatTok))
4418 parseVerilogSensitivityList();
4419 if (FormatTok->is(tok::semi))
4421 }
else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
4422 Keywords.kw_casez, Keywords.kw_randcase,
4423 Keywords.kw_randsequence)) {
4424 if (Style.IndentCaseLabels)
4427 if (FormatTok->is(tok::l_paren)) {
4428 FormatTok->setFinalizedType(TT_ConditionLParen);
4431 if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
4440 if (FormatTok->is(tok::l_square)) {
4441 auto Prev = FormatTok->getPreviousNonComment();
4442 if (Prev && Keywords.isVerilogIdentifier(*Prev))
4443 Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
4445 }
else if (Keywords.isVerilogIdentifier(*FormatTok) ||
4446 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
4447 Keywords.kw_automatic, tok::kw_static)) {
4454 auto NewLine = [
this]() {
4456 Line->IsContinuation =
true;
4460 while (FormatTok->is(Keywords.kw_import)) {
4463 parseVerilogHierarchyIdentifier();
4464 if (FormatTok->is(tok::semi))
4469 if (FormatTok->is(Keywords.kw_verilogHash)) {
4472 if (FormatTok->is(tok::l_paren)) {
4473 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4477 if (FormatTok->is(tok::l_paren)) {
4479 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4484 if (FormatTok->is(Keywords.kw_extends)) {
4487 parseVerilogHierarchyIdentifier();
4488 if (FormatTok->is(tok::l_paren))
4491 if (FormatTok->is(Keywords.kw_implements)) {
4495 parseVerilogHierarchyIdentifier();
4496 }
while (FormatTok->is(tok::comma));
4500 if (FormatTok->is(tok::at)) {
4502 parseVerilogSensitivityList();
4505 if (FormatTok->is(tok::semi))
4513void UnwrappedLineParser::parseVerilogTable() {
4514 assert(FormatTok->is(Keywords.kw_table));
4518 auto InitialLevel =
Line->Level++;
4519 while (!
eof() && !Keywords.isVerilogEnd(*FormatTok)) {
4522 if (
Tok->
is(tok::semi))
4524 else if (
Tok->
isOneOf(tok::star, tok::colon, tok::question, tok::minus))
4525 Tok->setFinalizedType(TT_VerilogTableItem);
4527 Line->Level = InitialLevel;
4532void UnwrappedLineParser::parseVerilogCaseLabel() {
4538 auto OrigLevel =
Line->Level;
4539 auto FirstLine = CurrentLines->size();
4540 if (
Line->Level == 0 || (
Line->InPPDirective &&
Line->Level <= 1))
4542 else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
4544 parseStructuralElement();
4547 if (CurrentLines->size() > FirstLine)
4548 (*CurrentLines)[FirstLine].Level = OrigLevel;
4549 Line->Level = OrigLevel;
4552void UnwrappedLineParser::parseVerilogExtern() {
4554 FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
4557 if (FormatTok->is(tok::string_literal))
4559 if (FormatTok->isOneOf(Keywords.kw_context, Keywords.kw_pure))
4561 if (Keywords.isVerilogIdentifier(*FormatTok))
4563 if (FormatTok->is(tok::equal))
4565 if (Keywords.isVerilogHierarchy(*FormatTok))
4566 parseVerilogHierarchyHeader();
4569bool UnwrappedLineParser::containsExpansion(
const UnwrappedLine &
Line)
const {
4570 for (
const auto &N :
Line.Tokens) {
4571 if (N.Tok->MacroCtx)
4573 for (
const UnwrappedLine &Child : N.Children)
4574 if (containsExpansion(Child))
4580void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
4581 if (
Line->Tokens.empty())
4584 if (!parsingPPDirective()) {
4585 llvm::dbgs() <<
"Adding unwrapped line:\n";
4586 printDebugInfo(*
Line);
4594 bool ClosesWhitesmithsBlock =
4595 Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
4596 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
4601 if (!parsingPPDirective() && !InExpansion && containsExpansion(*
Line)) {
4603 Reconstruct.emplace(
Line->Level, Unexpanded);
4604 Reconstruct->addLine(*
Line);
4609 CurrentExpandedLines.push_back(std::move(*
Line));
4611 if (Reconstruct->finished()) {
4612 UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();
4613 assert(!Reconstructed.Tokens.empty() &&
4614 "Reconstructed must at least contain the macro identifier.");
4615 assert(!parsingPPDirective());
4617 llvm::dbgs() <<
"Adding unexpanded line:\n";
4618 printDebugInfo(Reconstructed);
4620 ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;
4621 Lines.push_back(std::move(Reconstructed));
4622 CurrentExpandedLines.clear();
4623 Reconstruct.reset();
4628 assert(!Reconstruct || (CurrentLines != &Lines) || !PPStack.empty());
4629 CurrentLines->push_back(std::move(*
Line));
4631 Line->Tokens.clear();
4632 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
4633 Line->FirstStartColumn = 0;
4634 Line->IsContinuation =
false;
4635 Line->SeenDecltypeAuto =
false;
4637 if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
4639 if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {
4640 CurrentLines->append(
4641 std::make_move_iterator(PreprocessorDirectives.begin()),
4642 std::make_move_iterator(PreprocessorDirectives.end()));
4643 PreprocessorDirectives.clear();
4646 FormatTok->Previous =
nullptr;
4649bool UnwrappedLineParser::eof()
const {
return FormatTok->is(tok::eof); }
4651bool UnwrappedLineParser::isOnNewLine(
const FormatToken &FormatTok) {
4652 return (
Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
4653 FormatTok.NewlinesBefore > 0;
4661 const llvm::Regex &CommentPragmasRegex) {
4662 if (
Line.Tokens.empty() || Style.ReflowComments != FormatStyle::RCS_Always)
4665 StringRef IndentContent = FormatTok.
TokenText;
4666 if (FormatTok.
TokenText.starts_with(
"//") ||
4667 FormatTok.
TokenText.starts_with(
"/*")) {
4668 IndentContent = FormatTok.
TokenText.substr(2);
4670 if (CommentPragmasRegex.match(IndentContent))
4745 if (PreviousToken && PreviousToken->
is(tok::l_brace) &&
4747 MinColumnToken = PreviousToken;
4750 PreviousToken = Node.
Tok;
4754 MinColumnToken = Node.
Tok;
4756 if (PreviousToken && PreviousToken->
is(tok::l_brace))
4757 MinColumnToken = PreviousToken;
4763void UnwrappedLineParser::flushComments(
bool NewlineBeforeNext) {
4764 bool JustComments =
Line->Tokens.empty();
4774 Tok->ContinuesLineCommentSection =
4775 continuesLineCommentSection(*
Tok, *
Line, Style, CommentPragmasRegex);
4776 if (isOnNewLine(*
Tok) && JustComments && !
Tok->ContinuesLineCommentSection)
4780 if (NewlineBeforeNext && JustComments)
4782 CommentsBeforeNextToken.clear();
4785void UnwrappedLineParser::nextToken(
int LevelDifference) {
4788 flushComments(isOnNewLine(*FormatTok));
4789 pushToken(FormatTok);
4791 if (!Style.isJavaScript())
4792 readToken(LevelDifference);
4794 readTokenWithJavaScriptASI();
4796 if (Style.isVerilog()) {
4803 if (Keywords.isVerilogEnd(*FormatTok))
4804 FormatTok->Tok.setKind(tok::r_brace);
4808void UnwrappedLineParser::distributeComments(
4828 if (Comments.empty())
4830 bool ShouldPushCommentsInCurrentLine =
true;
4831 bool HasTrailAlignedWithNextToken =
false;
4832 unsigned StartOfTrailAlignedWithNextToken = 0;
4835 for (
unsigned i = Comments.size() - 1; i > 0; --i) {
4837 HasTrailAlignedWithNextToken =
true;
4838 StartOfTrailAlignedWithNextToken = i;
4842 for (
unsigned i = 0, e = Comments.size(); i < e; ++i) {
4844 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
4845 FormatTok->ContinuesLineCommentSection =
false;
4848 *FormatTok, *
Line, Style, CommentPragmasRegex);
4850 if (!FormatTok->ContinuesLineCommentSection &&
4851 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
4852 ShouldPushCommentsInCurrentLine =
false;
4854 if (ShouldPushCommentsInCurrentLine)
4855 pushToken(FormatTok);
4857 CommentsBeforeNextToken.push_back(FormatTok);
4861void UnwrappedLineParser::readToken(
int LevelDifference) {
4863 bool PreviousWasComment =
false;
4864 bool FirstNonCommentOnLine =
false;
4866 FormatTok = Tokens->getNextToken();
4868 while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
4869 TT_ConflictAlternative)) {
4870 if (FormatTok->is(TT_ConflictStart))
4871 conditionalCompilationStart(
false);
4872 else if (FormatTok->is(TT_ConflictAlternative))
4873 conditionalCompilationAlternative();
4874 else if (FormatTok->is(TT_ConflictEnd))
4875 conditionalCompilationEnd();
4876 FormatTok = Tokens->getNextToken();
4877 FormatTok->MustBreakBefore =
true;
4878 FormatTok->MustBreakBeforeFinalized =
true;
4881 auto IsFirstNonCommentOnLine = [](
bool FirstNonCommentOnLine,
4883 bool PreviousWasComment) {
4885 return Tok.HasUnescapedNewline ||
Tok.IsFirst;
4890 if (PreviousWasComment)
4891 return FirstNonCommentOnLine || IsFirstOnLine(
Tok);
4892 return IsFirstOnLine(
Tok);
4895 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4896 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4897 PreviousWasComment = FormatTok->is(tok::comment);
4899 while (!
Line->InPPDirective && FormatTok->is(tok::hash) &&
4900 FirstNonCommentOnLine) {
4903 const auto *
Next = Tokens->peekNextToken();
4904 if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*
Next)) ||
4905 (Style.isTableGen() &&
4906 Next->isNoneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef,
4907 tok::pp_ifndef, tok::pp_endif))) {
4910 distributeComments(Comments, FormatTok);
4914 bool SwitchToPreprocessorLines = !
Line->Tokens.empty();
4915 ScopedLineState BlockState(*
this, SwitchToPreprocessorLines);
4916 assert((LevelDifference >= 0 ||
4917 static_cast<unsigned>(-LevelDifference) <=
Line->Level) &&
4918 "LevelDifference makes Line->Level negative");
4919 Line->Level += LevelDifference;
4923 if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
4924 PPBranchLevel > 0) {
4925 Line->Level += PPBranchLevel;
4927 assert(
Line->Level >=
Line->UnbracedBodyLevel);
4928 Line->Level -=
Line->UnbracedBodyLevel;
4929 flushComments(isOnNewLine(*FormatTok));
4931 PreviousWasComment = FormatTok->is(tok::comment);
4932 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4933 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4936 if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
4937 !
Line->InPPDirective) {
4941 if (FormatTok->is(tok::identifier) &&
4942 Macros.defined(FormatTok->TokenText) &&
4944 !
Line->InPPDirective) {
4946 unsigned Position = Tokens->getPosition();
4950 auto PreCall = std::move(
Line);
4951 Line.reset(
new UnwrappedLine);
4952 bool OldInExpansion = InExpansion;
4955 auto Args = parseMacroCall();
4956 InExpansion = OldInExpansion;
4957 assert(
Line->Tokens.front().Tok == ID);
4959 auto UnexpandedLine = std::move(
Line);
4961 Line = std::move(PreCall);
4964 llvm::dbgs() <<
"Macro call: " <<
ID->TokenText <<
"(";
4966 llvm::dbgs() <<
"(";
4967 for (
const auto &Arg : Args.value())
4968 for (
const auto &
T : Arg)
4969 llvm::dbgs() <<
T->TokenText <<
" ";
4970 llvm::dbgs() <<
")";
4972 llvm::dbgs() <<
"\n";
4974 if (
Macros.objectLike(
ID->TokenText) && Args &&
4975 !
Macros.hasArity(
ID->TokenText, Args->size())) {
4981 LLVM_DEBUG(llvm::dbgs()
4982 <<
"Macro \"" <<
ID->TokenText
4983 <<
"\" not overloaded for arity " << Args->size()
4984 <<
"or not function-like, using object-like overload.");
4986 UnexpandedLine->Tokens.resize(1);
4987 Tokens->setPosition(Position);
4989 assert(!Args &&
Macros.objectLike(
ID->TokenText));
4991 if ((!Args &&
Macros.objectLike(
ID->TokenText)) ||
4992 (Args &&
Macros.hasArity(
ID->TokenText, Args->size()))) {
4995 Unexpanded[
ID] = std::move(UnexpandedLine);
4997 Macros.expand(ID, std::move(Args));
4998 if (!Expansion.empty())
4999 FormatTok = Tokens->insertTokens(Expansion);
5002 llvm::dbgs() <<
"Expanded: ";
5003 for (
const auto &
T : Expansion)
5004 llvm::dbgs() <<
T->TokenText <<
" ";
5005 llvm::dbgs() <<
"\n";
5009 llvm::dbgs() <<
"Did not expand macro \"" <<
ID->TokenText
5010 <<
"\", because it was used ";
5012 llvm::dbgs() <<
"with " << Args->size();
5014 llvm::dbgs() <<
"without";
5015 llvm::dbgs() <<
" arguments, which doesn't match any definition.\n";
5017 Tokens->setPosition(Position);
5022 if (FormatTok->isNot(tok::comment)) {
5023 distributeComments(Comments, FormatTok);
5028 Comments.push_back(FormatTok);
5031 distributeComments(Comments,
nullptr);
5036template <
typename Iterator>
5037void pushTokens(Iterator Begin, Iterator End,
5039 for (
auto I = Begin; I != End; ++I) {
5040 Into.push_back(I->Tok);
5041 for (
const auto &Child : I->Children)
5042 pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);
5047std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
5048UnwrappedLineParser::parseMacroCall() {
5049 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;
5050 assert(
Line->Tokens.empty());
5052 if (FormatTok->isNot(tok::l_paren))
5054 unsigned Position = Tokens->getPosition();
5058 auto ArgStart = std::prev(
Line->Tokens.end());
5062 switch (FormatTok->Tok.getKind()) {
5067 case tok::r_paren: {
5073 Args->push_back({});
5074 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5083 Args->push_back({});
5084 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5086 ArgStart = std::prev(
Line->Tokens.end());
5094 Line->Tokens.resize(1);
5095 Tokens->setPosition(Position);
5101 Line->Tokens.push_back(UnwrappedLineNode(
Tok));
5102 if (AtEndOfPPLine) {
5103 auto &
Tok = *
Line->Tokens.back().Tok;
5104 Tok.MustBreakBefore =
true;
5105 Tok.MustBreakBeforeFinalized =
true;
5106 Tok.FirstAfterPPLine =
true;
5107 AtEndOfPPLine =
false;
This file contains the main building blocks of macro support in clang-format.
static bool HasAttribute(const QualType &T)
This file implements a token annotator, i.e.
Defines the clang::TokenKind enum and support functions.
This file contains the declaration of the UnwrappedLineParser, which turns a stream of tokens into Un...
Implements an efficient mapping from strings to IdentifierInfo nodes.
Parser - This implements a parser for the C family of languages.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isOneOf(Ts... Ks) const
bool isNot(tok::TokenKind K) const
bool isNoneOf(Ts... Ks) const
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.
bool isLineComment(const FormatToken &FormatTok)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
std::vector< std::string > Macros
A list of macros of the form <definition>=<expansion> .
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
const FunctionProtoType * T
@ Type
The name was classified as a type.
bool continuesLineComment(const FormatToken &FormatTok, const FormatToken *Previous, const FormatToken *MinColumnToken)
@ Parens
New-expression has a C++98 paren-delimited initializer.
Encapsulates keywords that are context sensitive or for languages not properly supported by Clang's l...
IdentifierInfo * kw_instanceof
IdentifierInfo * kw_implements
IdentifierInfo * kw_override
IdentifierInfo * kw_await
IdentifierInfo * kw_extends
IdentifierInfo * kw_async
IdentifierInfo * kw_abstract
IdentifierInfo * kw_interface
IdentifierInfo * kw_function
IdentifierInfo * kw_yield
IdentifierInfo * kw_where
IdentifierInfo * kw_throws
IdentifierInfo * kw_import
IdentifierInfo * kw_finally
Represents a complete lambda introducer.