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);
765 const bool IsWhitesmiths =
766 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
770 if (!VerilogHierarchy && AddLevels > 0 && IsWhitesmiths)
773 size_t PPStartHash = computePPHash();
775 const unsigned InitialLevel = Line->Level;
776 if (VerilogHierarchy) {
777 AddLevels += parseVerilogHierarchyHeader();
779 nextToken(AddLevels);
780 HandleVerilogBlockLabel();
784 if (Line->Level > 300)
787 if (MacroBlock && FormatTok->is(tok::l_paren))
790 size_t NbPreprocessorDirectives =
791 !parsingPPDirective() ? PreprocessorDirectives.size() : 0;
793 size_t OpeningLineIndex =
794 CurrentLines->empty()
796 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
801 if (UnindentWhitesmithsBraces)
804 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
810 Line->Level += AddLevels - (IsWhitesmiths ? 1 : 0);
813 const bool SimpleBlock = parseLevel(
Tok, IfKind, &IfLBrace);
818 if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)
819 : FormatTok->isNot(tok::r_brace)) {
820 Line->Level = InitialLevel;
821 FormatTok->setBlockKind(BK_Block);
825 if (FormatTok->is(tok::r_brace)) {
826 FormatTok->setBlockKind(BK_Block);
827 if (Tok->is(TT_NamespaceLBrace))
828 FormatTok->setFinalizedType(TT_NamespaceRBrace);
831 const bool IsFunctionRBrace =
832 FormatTok->is(tok::r_brace) &&
Tok->is(TT_FunctionLBrace);
834 auto RemoveBraces = [=]()
mutable {
837 assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
838 assert(FormatTok->is(tok::r_brace));
839 const bool WrappedOpeningBrace = !Tok->Previous;
840 if (WrappedOpeningBrace && FollowedByComment)
842 const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
843 if (KeepBraces && !HasRequiredIfBraces)
845 if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
846 const FormatToken *Previous = Tokens->getPreviousToken();
848 if (Previous->is(tok::r_brace) && !Previous->Optional)
851 assert(!CurrentLines->empty());
852 auto &LastLine = CurrentLines->back();
853 if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
855 if (
Tok->is(TT_ElseLBrace))
857 if (WrappedOpeningBrace) {
862 return mightFitOnOneLine((*CurrentLines)[Index],
Tok);
864 if (RemoveBraces()) {
865 Tok->MatchingParen = FormatTok;
866 FormatTok->MatchingParen =
Tok;
869 size_t PPEndHash = computePPHash();
872 nextToken(-AddLevels);
877 if (Style.RemoveSemicolon && IsFunctionRBrace) {
878 while (FormatTok->is(tok::semi)) {
879 FormatTok->Optional =
true;
884 HandleVerilogBlockLabel();
886 if (MacroBlock && FormatTok->is(tok::l_paren))
889 Line->Level = InitialLevel;
891 if (FormatTok->is(tok::kw_noexcept)) {
896 if (FormatTok->is(tok::arrow)) {
900 parseStructuralElement();
903 if (MunchSemi && FormatTok->is(tok::semi))
906 if (PPStartHash == PPEndHash) {
907 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
910 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
911 CurrentLines->size() - 1;
921 if (
Line.Tokens.size() < 4)
923 auto I =
Line.Tokens.begin();
924 if (I->Tok->TokenText !=
"goog")
927 if (I->Tok->isNot(tok::period))
930 if (I->Tok->TokenText !=
"scope")
933 return I->Tok->is(tok::l_paren);
942 if (
Line.Tokens.size() < 3)
944 auto I =
Line.Tokens.begin();
945 if (I->Tok->isNot(tok::l_paren))
951 return I->Tok->is(tok::l_paren);
956 const bool IsJavaRecord) {
958 return Style.BraceWrapping.AfterClass;
961 if (InitialToken.
is(TT_NamespaceMacro))
962 Kind = tok::kw_namespace;
965 case tok::kw_namespace:
966 return Style.BraceWrapping.AfterNamespace;
968 return Style.BraceWrapping.AfterClass;
970 return Style.BraceWrapping.AfterUnion;
972 return Style.BraceWrapping.AfterStruct;
974 return Style.BraceWrapping.AfterEnum;
980void UnwrappedLineParser::parseChildBlock() {
981 assert(FormatTok->is(tok::l_brace));
982 FormatTok->setBlockKind(BK_Block);
986 bool SkipIndent = (Style.isJavaScript() &&
987 (isGoogScope(*
Line) || isIIFE(*
Line, Keywords)));
988 ScopedLineState LineState(*
this);
989 ScopedDeclarationState DeclarationState(*
Line, DeclarationScopeStack,
991 Line->Level += SkipIndent ? 0 : 1;
992 parseLevel(OpeningBrace);
993 flushComments(isOnNewLine(*FormatTok));
994 Line->Level -= SkipIndent ? 0 : 1;
999void UnwrappedLineParser::parsePPDirective() {
1000 assert(FormatTok->is(tok::hash) &&
"'#' expected");
1001 ScopedMacroState MacroState(*
Line, Tokens, FormatTok);
1005 if (!FormatTok->Tok.getIdentifierInfo()) {
1010 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
1011 case tok::pp_define:
1018 case tok::pp_ifndef:
1022 case tok::pp_elifdef:
1023 case tok::pp_elifndef:
1030 case tok::pp_pragma:
1034 case tok::pp_warning:
1036 if (!
eof() && Style.isCpp())
1037 FormatTok->setFinalizedType(TT_AfterPPDirective);
1045void UnwrappedLineParser::conditionalCompilationCondition(
bool Unreachable) {
1046 size_t Line = CurrentLines->size();
1047 if (CurrentLines == &PreprocessorDirectives)
1048 Line += Lines.size();
1051 (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) {
1052 PPStack.push_back({PP_Unreachable,
Line});
1054 PPStack.push_back({PP_Conditional,
Line});
1058void UnwrappedLineParser::conditionalCompilationStart(
bool Unreachable) {
1060 assert(PPBranchLevel >= 0 && PPBranchLevel <= (
int)PPLevelBranchIndex.size());
1061 if (PPBranchLevel == (
int)PPLevelBranchIndex.size()) {
1062 PPLevelBranchIndex.push_back(0);
1063 PPLevelBranchCount.push_back(0);
1065 PPChainBranchIndex.push(Unreachable ? -1 : 0);
1066 bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
1067 conditionalCompilationCondition(Unreachable ||
Skip);
1070void UnwrappedLineParser::conditionalCompilationAlternative() {
1071 if (!PPStack.empty())
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());
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;
1088 if (PPBranchLevel > -1)
1090 if (!PPChainBranchIndex.empty())
1091 PPChainBranchIndex.pop();
1092 if (!PPStack.empty())
1096void UnwrappedLineParser::parsePPIf(
bool IfDef) {
1097 bool IfNDef = FormatTok->is(tok::pp_ifndef);
1099 bool Unreachable =
false;
1100 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText ==
"0"))
1102 if (IfDef && !IfNDef && FormatTok->TokenText ==
"SWIG")
1104 conditionalCompilationStart(Unreachable);
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;
1121 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1122 IncludeGuard = IG_IfNdefed;
1123 IncludeGuardToken = IfCondition;
1127void UnwrappedLineParser::parsePPElse() {
1129 if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
1130 IncludeGuard = IG_Rejected;
1132 assert(PPBranchLevel >= -1);
1133 if (PPBranchLevel == -1)
1134 conditionalCompilationStart(
true);
1135 conditionalCompilationAlternative();
1141void UnwrappedLineParser::parsePPEndIf() {
1142 conditionalCompilationEnd();
1146 if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&
1147 getIncludeGuardState(Style.IndentPPDirectives) == IG_Inited) {
1148 IncludeGuard = IG_Found;
1152void UnwrappedLineParser::parsePPDefine() {
1155 if (!FormatTok->Tok.getIdentifierInfo()) {
1156 IncludeGuard = IG_Rejected;
1157 IncludeGuardToken =
nullptr;
1162 bool MaybeIncludeGuard =
false;
1163 if (IncludeGuard == IG_IfNdefed &&
1164 IncludeGuardToken->TokenText == FormatTok->TokenText) {
1165 IncludeGuard = IG_Defined;
1166 IncludeGuardToken =
nullptr;
1167 for (
auto &
Line : Lines) {
1168 if (
Line.Tokens.front().Tok->isNoneOf(tok::comment, tok::hash)) {
1169 IncludeGuard = IG_Rejected;
1173 MaybeIncludeGuard = IncludeGuard == IG_Defined;
1181 FormatTok->Tok.setKind(tok::identifier);
1182 FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);
1186 if (MaybeIncludeGuard && !
eof())
1187 IncludeGuard = IG_Rejected;
1189 if (FormatTok->is(tok::l_paren) && !FormatTok->hasWhitespaceBefore())
1191 if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
1192 Line->Level += PPBranchLevel + 1;
1196 Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
1197 assert((
int)
Line->PPLevel >= 0);
1202 Line->InMacroBody =
true;
1204 if (!Style.SkipMacroDefinitionBody) {
1214 for (
auto *Comment : CommentsBeforeNextToken)
1215 Comment->Finalized =
true;
1218 FormatTok->Finalized =
true;
1219 FormatTok = Tokens->getNextToken();
1225void UnwrappedLineParser::parsePPPragma() {
1226 Line->InPragmaDirective =
true;
1230void UnwrappedLineParser::parsePPUnknown() {
1233 if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
1234 Line->Level += PPBranchLevel + 1;
1244 return Tok.isNoneOf(tok::semi, tok::l_brace,
1247 tok::period, tok::periodstar, tok::arrow, tok::arrowstar,
1248 tok::less, tok::greater, tok::slash, tok::percent,
1249 tok::lessless, tok::greatergreater, tok::equal,
1250 tok::plusequal, tok::minusequal, tok::starequal,
1251 tok::slashequal, tok::percentequal, tok::ampequal,
1252 tok::pipeequal, tok::caretequal, tok::greatergreaterequal,
1265 return FormatTok->
is(tok::identifier) &&
1280 FormatTok->
isOneOf(tok::kw_true, tok::kw_false) ||
1291 tok::kw_if, tok::kw_else,
1293 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
1295 tok::kw_switch, tok::kw_case,
1297 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.
kw_finally,
1299 tok::kw_const, tok::kw_class, Keywords.
kw_var, Keywords.
kw_let,
1307 return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
1308 tok::kw_unsigned, tok::kw_float, tok::kw_double,
1325 if (FuncName->
isNot(tok::identifier))
1333 Tok->isNoneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
1337 if (
Next->isNot(tok::star) && !
Next->Tok.getIdentifierInfo())
1341 if (!
Tok ||
Tok->isNot(tok::r_paren))
1345 if (!
Tok ||
Tok->isNot(tok::identifier))
1348 return Tok->Previous &&
Tok->Previous->isOneOf(tok::l_paren, tok::comma);
1351bool UnwrappedLineParser::parseModuleImport() {
1352 assert(FormatTok->is(Keywords.kw_import) &&
"'import' expected");
1354 if (
auto Token = Tokens->peekNextToken(
true);
1356 Token->
isNoneOf(tok::colon, tok::less, tok::string_literal)) {
1362 if (FormatTok->is(tok::colon)) {
1363 FormatTok->setFinalizedType(TT_ModulePartitionColon);
1366 else if (FormatTok->is(tok::less)) {
1368 while (FormatTok->isNoneOf(tok::semi, tok::greater) && !
eof()) {
1371 if (FormatTok->isNot(tok::comment) &&
1372 !FormatTok->TokenText.starts_with(
"//")) {
1373 FormatTok->setFinalizedType(TT_ImplicitStringLiteral);
1378 if (FormatTok->is(tok::semi)) {
1396void UnwrappedLineParser::readTokenWithJavaScriptASI() {
1402 CommentsBeforeNextToken.empty()
1403 ?
Next->NewlinesBefore == 0
1404 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
1409 bool PreviousStartsTemplateExpr =
1411 if (PreviousMustBeValue ||
Previous->is(tok::r_paren)) {
1414 bool HasAt = llvm::any_of(
Line->Tokens, [](UnwrappedLineNode &LineNode) {
1415 return LineNode.Tok->is(tok::at);
1420 if (
Next->is(tok::exclaim) && PreviousMustBeValue)
1421 return addUnwrappedLine();
1423 bool NextEndsTemplateExpr =
1424 Next->is(TT_TemplateString) &&
Next->TokenText.starts_with(
"}");
1425 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
1426 (PreviousMustBeValue ||
1427 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
1428 tok::minusminus))) {
1429 return addUnwrappedLine();
1431 if ((PreviousMustBeValue ||
Previous->is(tok::r_paren)) &&
1433 return addUnwrappedLine();
1437void UnwrappedLineParser::parseStructuralElement(
1438 const FormatToken *OpeningBrace, IfStmtKind *IfKind,
1439 FormatToken **IfLeftBrace,
bool *HasDoWhile,
bool *HasLabel) {
1440 if (Style.isTableGen() && FormatTok->is(tok::pp_include)) {
1442 if (FormatTok->is(tok::string_literal))
1449 while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
1451 }
else if (Style.isVerilog()) {
1452 if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {
1453 parseForOrWhileLoop(
false);
1456 if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {
1457 parseForOrWhileLoop();
1460 if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
1461 Keywords.kw_assume, Keywords.kw_cover)) {
1462 parseIfThenElse(IfKind,
false,
true);
1468 if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
1469 Keywords.kw_unique0)) {
1471 }
else if (FormatTok->is(tok::l_paren) &&
1472 Tokens->peekNextToken()->is(tok::star)) {
1481 if (FormatTok->isAccessSpecifierKeyword()) {
1482 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
1485 parseAccessSpecifier();
1488 switch (FormatTok->Tok.getKind()) {
1491 if (FormatTok->is(tok::l_brace)) {
1492 FormatTok->setFinalizedType(TT_InlineASMBrace);
1494 while (FormatTok && !
eof()) {
1495 if (FormatTok->is(tok::r_brace)) {
1496 FormatTok->setFinalizedType(TT_InlineASMBrace);
1501 FormatTok->Finalized =
true;
1506 case tok::kw_namespace:
1510 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1521 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1525 parseForOrWhileLoop();
1528 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1536 case tok::kw_switch:
1537 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1543 case tok::kw_default: {
1545 if (Style.isVerilog())
1547 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1553 if (FormatTok->is(tok::colon)) {
1554 FormatTok->setFinalizedType(TT_CaseLabelColon);
1558 if (FormatTok->is(tok::arrow)) {
1559 FormatTok->setFinalizedType(TT_CaseLabelArrow);
1560 Default->setFinalizedType(TT_SwitchExpressionLabel);
1569 if (Style.Language == FormatStyle::LK_Proto) {
1573 if (Style.isVerilog()) {
1578 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1587 if (FormatTok->is(tok::kw_case))
1592 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1598 case tok::kw_extern:
1599 if (Style.isVerilog()) {
1602 parseVerilogExtern();
1606 if (FormatTok->is(tok::string_literal)) {
1608 if (FormatTok->is(tok::l_brace)) {
1609 if (Style.BraceWrapping.AfterExternBlock)
1613 unsigned AddLevels =
1614 (Style.IndentExternBlock == FormatStyle::IEBS_Indent) ||
1615 (Style.BraceWrapping.AfterExternBlock &&
1616 Style.IndentExternBlock ==
1617 FormatStyle::IEBS_AfterExternBlock)
1620 parseBlock(
true, AddLevels);
1626 case tok::kw_export:
1627 if (Style.isJavaScript()) {
1628 parseJavaScriptEs6ImportExport();
1631 if (Style.isVerilog()) {
1632 parseVerilogExtern();
1637 if (FormatTok->is(tok::kw_namespace)) {
1641 if (FormatTok->is(tok::l_brace)) {
1642 parseCppExportBlock();
1645 if (FormatTok->is(Keywords.kw_import) && parseModuleImport())
1649 case tok::kw_inline:
1651 if (FormatTok->is(tok::kw_namespace)) {
1656 case tok::identifier:
1657 if (FormatTok->is(TT_ForEachMacro)) {
1658 parseForOrWhileLoop();
1661 if (FormatTok->is(TT_MacroBlockBegin)) {
1662 parseBlock(
false, 1u,
1666 if (FormatTok->is(Keywords.kw_import)) {
1667 if (Style.isJavaScript()) {
1668 parseJavaScriptEs6ImportExport();
1671 if (Style.Language == FormatStyle::LK_Proto) {
1673 if (FormatTok->is(tok::kw_public))
1675 if (FormatTok->isNot(tok::string_literal))
1678 if (FormatTok->is(tok::semi))
1683 if (Style.isVerilog()) {
1684 parseVerilogExtern();
1687 if (IsCpp && parseModuleImport())
1690 if (IsCpp && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
1691 Keywords.kw_slots, Keywords.kw_qslots)) {
1693 if (FormatTok->is(tok::colon)) {
1699 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
1700 parseStatementMacro();
1703 if (IsCpp && FormatTok->is(TT_NamespaceMacro)) {
1711 if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&
1712 Tokens->peekNextToken()->is(tok::colon) && !
Line->MustBeDeclaration) {
1714 if (!
Line->InMacroBody || CurrentLines->size() > 1)
1715 Line->Tokens.begin()->Tok->MustBreakBefore =
true;
1716 FormatTok->setFinalizedType(TT_GotoLabelColon);
1717 parseLabel(!Style.IndentGotoLabels);
1722 if (Style.isJava() && FormatTok->is(Keywords.kw_record)) {
1723 parseRecord(
false,
true);
1733 bool SeenEqual =
false;
1734 for (
const bool InRequiresExpression =
1735 OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
1736 TT_CompoundRequirementLBrace);
1739 switch (FormatTok->Tok.getKind()) {
1742 if (FormatTok->is(tok::l_brace)) {
1747 if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) {
1751 switch (
bool IsAutoRelease =
false; FormatTok->Tok.getObjCKeywordID()) {
1752 case tok::objc_public:
1753 case tok::objc_protected:
1754 case tok::objc_package:
1755 case tok::objc_private:
1756 return parseAccessSpecifier();
1757 case tok::objc_interface:
1758 case tok::objc_implementation:
1759 return parseObjCInterfaceOrImplementation();
1760 case tok::objc_protocol:
1761 if (parseObjCProtocol())
1766 case tok::objc_optional:
1767 case tok::objc_required:
1771 case tok::objc_autoreleasepool:
1772 IsAutoRelease =
true;
1774 case tok::objc_synchronized:
1776 if (!IsAutoRelease && FormatTok->is(tok::l_paren)) {
1780 if (FormatTok->is(tok::l_brace)) {
1781 if (Style.BraceWrapping.AfterControlStatement ==
1782 FormatStyle::BWACS_Always) {
1798 case tok::kw_requires: {
1800 bool ParsedClause = parseRequires(SeenEqual);
1821 if (!IsCpp && !Style.isVerilog()) {
1826 case tok::kw_typedef:
1828 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1829 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
1830 Keywords.kw_CF_CLOSED_ENUM,
1831 Keywords.kw_NS_CLOSED_ENUM)) {
1836 if (Style.isVerilog()) {
1841 if (Style.isTableGen()) {
1848 case tok::kw_struct:
1850 if (parseStructLike())
1853 case tok::kw_decltype:
1855 if (FormatTok->is(tok::l_paren)) {
1857 if (FormatTok->Previous &&
1858 FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
1860 Line->SeenDecltypeAuto =
true;
1867 if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class))
1869 if (Style.isJavaScript() && FormatTok &&
1870 FormatTok->Tok.getIdentifierInfo()) {
1883 case tok::l_paren: {
1890 Tokens->peekNextToken(
true),
1897 case tok::kw_operator:
1899 if (FormatTok->isBinaryOperator())
1903 const auto *Prev = FormatTok->getPreviousNonComment();
1905 if (Prev && Prev->is(tok::identifier))
1908 if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {
1911 while (FormatTok->is(tok::star))
1915 if (FormatTok->is(tok::l_paren))
1918 if (FormatTok->is(tok::l_brace))
1923 if (InRequiresExpression)
1924 FormatTok->setFinalizedType(TT_BracedListLBrace);
1925 if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
1926 IsDecltypeAutoFunction =
Line->SeenDecltypeAuto;
1931 if (Style.isJava() &&
1932 Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
1935 if (Style.BraceWrapping.AfterControlStatement ==
1936 FormatStyle::BWACS_Always) {
1939 }
else if (Style.BraceWrapping.AfterFunction) {
1943 FormatTok->setFinalizedType(TT_FunctionLBrace);
1945 IsDecltypeAutoFunction =
false;
1953 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
1959 if (Style.BraceWrapping.AfterFunction)
1963 case tok::identifier: {
1964 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&
1965 Line->MustBeDeclaration) {
1967 parseCSharpGenericTypeConstraint();
1970 if (FormatTok->is(TT_MacroBlockEnd)) {
1979 size_t TokenCount =
Line->Tokens.size();
1980 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&
1983 Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {
1984 tryToParseJSFunction();
1987 if ((Style.isJavaScript() || Style.isJava()) &&
1988 FormatTok->is(Keywords.kw_interface)) {
1989 if (Style.isJavaScript()) {
1994 unsigned StoredPosition = Tokens->getPosition();
1996 FormatTok = Tokens->setPosition(StoredPosition);
2007 if (Style.isVerilog()) {
2008 if (FormatTok->is(Keywords.kw_table)) {
2009 parseVerilogTable();
2012 if (Keywords.isVerilogBegin(*FormatTok) ||
2013 Keywords.isVerilogHierarchy(*FormatTok)) {
2020 if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
2021 if (parseStructLike())
2026 if (IsCpp && FormatTok->is(TT_StatementMacro)) {
2027 parseStatementMacro();
2032 StringRef
Text = FormatTok->TokenText;
2039 if (Style.isJavaScript())
2042 auto OneTokenSoFar = [&]() {
2043 auto I =
Line->Tokens.begin(), E =
Line->Tokens.end();
2044 while (I != E && I->Tok->is(tok::comment))
2046 if (Style.isVerilog())
2047 while (I != E && I->Tok->is(tok::hash))
2049 return I != E && (++I == E);
2051 if (OneTokenSoFar()) {
2054 bool FunctionLike = FormatTok->is(tok::l_paren);
2058 bool FollowedByNewline =
2059 CommentsBeforeNextToken.empty()
2060 ? FormatTok->NewlinesBefore > 0
2061 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
2063 if (FollowedByNewline &&
2064 (
Text.size() >= 5 ||
2065 (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
2067 if (PreviousToken->isNot(TT_UntouchableMacroFunc))
2068 PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
2076 if ((Style.isJavaScript() || Style.isCSharp()) &&
2077 FormatTok->is(TT_FatArrow)) {
2078 tryToParseChildBlock();
2084 if (FormatTok->is(tok::l_brace)) {
2088 if (Style.isCSharp())
2089 FormatTok->setBlockKind(BK_BracedInit);
2092 if (Style.isTableGen() &&
2093 Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {
2094 FormatTok->setFinalizedType(TT_FunctionLBrace);
2095 parseBlock(
false, 1u,
2102 }
else if (Style.Language == FormatStyle::LK_Proto &&
2103 FormatTok->is(tok::less)) {
2105 parseBracedList(
true);
2112 if (Style.isCSharp() &&
2113 (Tokens->peekNextToken()->isAccessSpecifierKeyword() ||
2120 case tok::kw_switch:
2128 if (Style.Language == FormatStyle::LK_Proto) {
2133 if (Style.isVerilog()) {
2138 if (Style.isJavaScript() &&
Line->MustBeDeclaration) {
2145 case tok::kw_default:
2147 if (Style.isVerilog()) {
2148 if (FormatTok->is(tok::colon)) {
2152 if (FormatTok->is(Keywords.kw_clocking)) {
2158 parseVerilogCaseLabel();
2164 if (Style.isVerilog()) {
2165 parseVerilogCaseLabel();
2171 if (FormatTok->is(tok::l_brace))
2172 FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
2181bool UnwrappedLineParser::tryToParsePropertyAccessor() {
2182 assert(FormatTok->is(tok::l_brace));
2183 if (!Style.isCSharp())
2186 if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))
2194 unsigned int StoredPosition = Tokens->getPosition();
2200 bool HasSpecialAccessor =
false;
2201 bool IsTrivialPropertyAccessor =
true;
2204 if (
const bool IsAccessorKeyword =
2205 Tok->
isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set);
2206 IsAccessorKeyword ||
Tok->isAccessSpecifierKeyword() ||
2207 Tok->
isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {
2208 if (IsAccessorKeyword)
2209 HasSpecialAccessor =
true;
2210 else if (
Tok->
is(tok::l_square))
2212 Tok = Tokens->getNextToken();
2216 IsTrivialPropertyAccessor =
false;
2221 Tokens->setPosition(StoredPosition);
2227 Tokens->setPosition(StoredPosition);
2228 if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)
2232 switch (FormatTok->Tok.getKind()) {
2235 if (FormatTok->is(tok::equal)) {
2236 while (!
eof() && FormatTok->isNot(tok::semi))
2249 if (FormatTok->is(TT_FatArrow)) {
2253 }
while (!
eof() && FormatTok->isNot(tok::semi));
2262 if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,
2264 !IsTrivialPropertyAccessor) {
2276bool UnwrappedLineParser::tryToParseLambda() {
2277 assert(FormatTok->is(tok::l_square));
2283 if (!tryToParseLambdaIntroducer())
2287 bool InTemplateParameterList =
false;
2289 while (FormatTok->isNot(tok::l_brace)) {
2290 if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {
2294 switch (FormatTok->Tok.getKind()) {
2298 parseParens(TT_PointerOrReference);
2304 assert(FormatTok->Previous);
2305 if (FormatTok->Previous->is(tok::r_square))
2306 InTemplateParameterList =
true;
2311 case tok::kw_struct:
2313 case tok::kw_template:
2314 case tok::kw_typename:
2318 case tok::kw_constexpr:
2319 case tok::kw_consteval:
2322 case tok::identifier:
2323 case tok::numeric_constant:
2324 case tok::coloncolon:
2325 case tok::kw_mutable:
2326 case tok::kw_noexcept:
2327 case tok::kw_static:
2352 case tok::equalequal:
2353 case tok::exclaimequal:
2354 case tok::greaterequal:
2355 case tok::lessequal:
2361 if (Arrow || InTemplateParameterList) {
2370 case tok::kw_requires:
2371 parseRequiresClause();
2374 if (!InTemplateParameterList)
2383 FormatTok->setFinalizedType(TT_LambdaLBrace);
2384 LSquare.setFinalizedType(TT_LambdaLSquare);
2387 Arrow->setFinalizedType(TT_LambdaArrow);
2389 NestedLambdas.push_back(
Line->SeenDecltypeAuto);
2391 assert(!NestedLambdas.empty());
2392 NestedLambdas.pop_back();
2397bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
2402 const auto *PrevPrev =
Previous->getPreviousNonComment();
2403 if (
Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts))
2411 if (!PrevPrev || PrevPrev->isNoneOf(tok::greater, tok::r_paren))
2415 Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
2416 tok::kw_co_return)) {
2420 if (LeftSquare->isCppStructuredBinding(IsCpp))
2422 if (FormatTok->is(tok::l_square) ||
tok::isLiteral(FormatTok->Tok.getKind()))
2424 if (FormatTok->is(tok::r_square)) {
2426 if (
Next->is(tok::greater))
2433void UnwrappedLineParser::tryToParseJSFunction() {
2434 assert(FormatTok->is(Keywords.kw_function));
2435 if (FormatTok->is(Keywords.kw_async))
2441 if (FormatTok->is(tok::star)) {
2442 FormatTok->setFinalizedType(TT_OverloadedOperator);
2447 if (FormatTok->is(tok::identifier))
2450 if (FormatTok->isNot(tok::l_paren))
2456 if (FormatTok->is(tok::colon)) {
2462 if (FormatTok->is(tok::l_brace))
2463 tryToParseBracedList();
2465 while (FormatTok->isNoneOf(tok::l_brace, tok::semi) && !
eof())
2469 if (FormatTok->is(tok::semi))
2475bool UnwrappedLineParser::tryToParseBracedList() {
2476 if (FormatTok->is(BK_Unknown))
2477 calculateBraceTypes();
2478 assert(FormatTok->isNot(BK_Unknown));
2479 if (FormatTok->is(BK_Block))
2486bool UnwrappedLineParser::tryToParseChildBlock() {
2487 assert(Style.isJavaScript() || Style.isCSharp());
2488 assert(FormatTok->is(TT_FatArrow));
2493 if (FormatTok->isNot(tok::l_brace))
2499bool UnwrappedLineParser::parseBracedList(
bool IsAngleBracket,
bool IsEnum) {
2500 assert(!IsAngleBracket || !IsEnum);
2501 bool HasError =
false;
2506 if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
2507 tryToParseChildBlock()) {
2510 if (Style.isJavaScript()) {
2511 if (FormatTok->is(Keywords.kw_function)) {
2512 tryToParseJSFunction();
2515 if (FormatTok->is(tok::l_brace)) {
2517 if (tryToParseBracedList())
2522 if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
2524 FormatTok->setBlockKind(BK_Block);
2525 if (!Style.AllowShortEnumsOnASingleLine)
2531 switch (FormatTok->Tok.getKind()) {
2533 if (Style.isCSharp())
2542 if (Style.isJavaScript()) {
2543 if (FormatTok->is(tok::l_brace))
2551 FormatTok->setBlockKind(BK_BracedInit);
2552 if (!IsAngleBracket) {
2553 auto *Prev = FormatTok->Previous;
2554 if (Prev && Prev->is(tok::greater))
2555 Prev->setFinalizedType(TT_TemplateCloser);
2563 parseBracedList(
true);
2570 if (Style.isJavaScript()) {
2581 if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
2584 case tok::kw_requires:
2585 parseRequiresExpression();
2600bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType,
2602 assert(FormatTok->is(tok::l_paren) &&
"'(' expected.");
2603 auto *LParen = FormatTok;
2604 auto *Prev = FormatTok->Previous;
2605 bool SeenComma =
false;
2606 bool SeenEqual =
false;
2607 bool MightBeFoldExpr =
false;
2609 const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
2610 if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
2613 switch (FormatTok->Tok.getKind()) {
2615 if (parseParens(AmpAmpTokenType, InMacroCall))
2617 if (Style.isJava() && FormatTok->is(tok::l_brace))
2620 case tok::r_paren: {
2621 auto *RParen = FormatTok;
2624 auto OptionalParens = [&] {
2625 if (Style.RemoveParentheses == FormatStyle::RPS_Leave ||
2626 MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
2627 Line->InMacroBody || RParen->getPreviousNonComment() == LParen) {
2630 const bool DoubleParens =
2631 Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);
2633 const auto *PrevPrev = Prev->getPreviousNonComment();
2634 const bool Excluded =
2636 (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2638 (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2639 PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2643 const bool CommaSeparated =
2644 Prev->isOneOf(tok::l_paren, tok::comma) &&
2645 FormatTok->isOneOf(tok::comma, tok::r_paren);
2646 if (CommaSeparated &&
2648 !Prev->endsSequence(tok::comma, tok::ellipsis) &&
2650 !(FormatTok->is(tok::comma) &&
2651 Tokens->peekNextToken()->is(tok::ellipsis))) {
2654 const bool ReturnParens =
2655 Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
2656 ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2657 (!NestedLambdas.empty() && !NestedLambdas.back())) &&
2658 Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
2659 FormatTok->is(tok::semi);
2665 if (OptionalParens()) {
2666 LParen->Optional =
true;
2667 RParen->Optional =
true;
2668 }
else if (Prev->is(TT_TypenameMacro)) {
2669 LParen->setFinalizedType(TT_TypeDeclarationParen);
2670 RParen->setFinalizedType(TT_TypeDeclarationParen);
2671 }
else if (Prev->is(tok::greater) && RParen->Previous == LParen) {
2672 Prev->setFinalizedType(TT_TemplateCloser);
2673 }
else if (FormatTok->is(tok::l_brace) && Prev->is(tok::amp) &&
2675 FormatTok->setBlockKind(BK_BracedInit);
2687 if (!tryToParseBracedList())
2692 if (FormatTok->is(tok::l_brace)) {
2702 MightBeFoldExpr =
true;
2707 if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
2708 tryToParseChildBlock();
2713 if (Style.isJavaScript())
2718 case tok::identifier:
2719 if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))
2720 tryToParseJSFunction();
2724 case tok::kw_switch:
2730 case tok::kw_requires:
2731 parseRequiresExpression();
2734 if (AmpAmpTokenType != TT_Unknown)
2735 FormatTok->setFinalizedType(AmpAmpTokenType);
2747 assert(FormatTok->is(tok::l_square) &&
"'[' expected.");
2748 if (tryToParseLambda())
2752 switch (FormatTok->Tok.getKind()) {
2765 case tok::l_brace: {
2766 if (!tryToParseBracedList())
2773 if (FormatTok->is(tok::l_brace)) {
2785void UnwrappedLineParser::keepAncestorBraces() {
2786 if (!Style.RemoveBracesLLVM)
2789 const int MaxNestingLevels = 2;
2790 const int Size = NestedTooDeep.size();
2791 if (Size >= MaxNestingLevels)
2792 NestedTooDeep[
Size - MaxNestingLevels] =
true;
2793 NestedTooDeep.push_back(
false);
2797 for (
const auto &
Token : llvm::reverse(
Line.Tokens))
2804void UnwrappedLineParser::parseUnbracedBody(
bool CheckEOF) {
2807 if (Style.InsertBraces && !
Line->InPPDirective && !
Line->Tokens.empty() &&
2808 PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
2809 Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never
2810 ? getLastNonComment(*
Line)
2813 if (
Tok->BraceCount < 0) {
2814 assert(
Tok->BraceCount == -1);
2817 Tok->BraceCount = -1;
2823 ++
Line->UnbracedBodyLevel;
2824 parseStructuralElement();
2825 --
Line->UnbracedBodyLevel;
2828 assert(!
Line->InPPDirective);
2830 for (
const auto &L : llvm::reverse(*CurrentLines)) {
2832 Tok = L.Tokens.back().Tok;
2840 if (CheckEOF &&
eof())
2850 assert(LeftBrace->
is(tok::l_brace));
2858 assert(RightBrace->
is(tok::r_brace));
2866void UnwrappedLineParser::handleAttributes() {
2868 if (FormatTok->isAttribute())
2870 else if (FormatTok->is(tok::l_square))
2871 handleCppAttributes();
2874bool UnwrappedLineParser::handleCppAttributes() {
2876 assert(FormatTok->is(tok::l_square));
2877 if (!tryToParseSimpleAttribute())
2884bool UnwrappedLineParser::isBlockBegin(
const FormatToken &
Tok)
const {
2887 return Style.isVerilog() ? Keywords.isVerilogBegin(
Tok)
2888 :
Tok.
is(tok::l_brace);
2891FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
2893 bool IsVerilogAssert) {
2894 assert((FormatTok->is(tok::kw_if) ||
2895 (Style.isVerilog() &&
2896 FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
2897 Keywords.kw_assume, Keywords.kw_cover))) &&
2901 if (IsVerilogAssert) {
2903 if (FormatTok->is(Keywords.kw_verilogHash)) {
2905 if (FormatTok->is(tok::numeric_constant))
2907 }
else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,
2908 Keywords.kw_sequence)) {
2914 if (Style.isTableGen()) {
2915 while (!
eof() && FormatTok->isNot(Keywords.kw_then)) {
2922 if (FormatTok->is(tok::exclaim))
2925 bool KeepIfBraces =
true;
2926 if (FormatTok->is(tok::kw_consteval)) {
2929 KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;
2930 if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
2932 if (FormatTok->is(tok::l_paren)) {
2933 FormatTok->setFinalizedType(TT_ConditionLParen);
2939 if (IsVerilogAssert && FormatTok->is(tok::semi)) {
2945 bool NeedsUnwrappedLine =
false;
2946 keepAncestorBraces();
2949 IfStmtKind IfBlockKind = IfStmtKind::NotIf;
2951 if (isBlockBegin(*FormatTok)) {
2952 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
2953 IfLeftBrace = FormatTok;
2954 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
2955 parseBlock(
false, 1u,
2956 true, KeepIfBraces, &IfBlockKind);
2957 setPreviousRBraceType(TT_ControlStatementRBrace);
2958 if (Style.BraceWrapping.BeforeElse)
2961 NeedsUnwrappedLine =
true;
2962 }
else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {
2965 parseUnbracedBody();
2968 if (Style.RemoveBracesLLVM) {
2969 assert(!NestedTooDeep.empty());
2970 KeepIfBraces = KeepIfBraces ||
2971 (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
2972 NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
2973 IfBlockKind == IfStmtKind::IfElseIf;
2976 bool KeepElseBraces = KeepIfBraces;
2978 IfStmtKind
Kind = IfStmtKind::IfOnly;
2980 if (FormatTok->is(tok::kw_else)) {
2981 if (Style.RemoveBracesLLVM) {
2982 NestedTooDeep.back() =
false;
2983 Kind = IfStmtKind::IfElse;
2987 if (isBlockBegin(*FormatTok)) {
2988 const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
2989 FormatTok->setFinalizedType(TT_ElseLBrace);
2990 ElseLeftBrace = FormatTok;
2991 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
2992 IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
2994 parseBlock(
false, 1u,
2995 true, KeepElseBraces, &ElseBlockKind);
2996 setPreviousRBraceType(TT_ElseRBrace);
2997 if (FormatTok->is(tok::kw_else)) {
2998 KeepElseBraces = KeepElseBraces ||
2999 ElseBlockKind == IfStmtKind::IfOnly ||
3000 ElseBlockKind == IfStmtKind::IfElseIf;
3001 }
else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
3002 KeepElseBraces =
true;
3003 assert(ElseLeftBrace->MatchingParen);
3007 }
else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {
3010 const bool IsPrecededByComment =
Previous->is(tok::comment);
3011 if (IsPrecededByComment) {
3015 bool TooDeep =
true;
3016 if (Style.RemoveBracesLLVM) {
3017 Kind = IfStmtKind::IfElseIf;
3018 TooDeep = NestedTooDeep.pop_back_val();
3020 ElseLeftBrace = parseIfThenElse(
nullptr, KeepIfBraces);
3021 if (Style.RemoveBracesLLVM)
3022 NestedTooDeep.push_back(TooDeep);
3023 if (IsPrecededByComment)
3026 parseUnbracedBody(
true);
3029 KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
3030 if (NeedsUnwrappedLine)
3034 if (!Style.RemoveBracesLLVM)
3037 assert(!NestedTooDeep.empty());
3038 KeepElseBraces = KeepElseBraces ||
3039 (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
3040 NestedTooDeep.back();
3042 NestedTooDeep.pop_back();
3044 if (!KeepIfBraces && !KeepElseBraces) {
3047 }
else if (IfLeftBrace) {
3048 FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
3050 assert(IfRightBrace->MatchingParen == IfLeftBrace);
3051 assert(!IfLeftBrace->Optional);
3052 assert(!IfRightBrace->Optional);
3053 IfLeftBrace->MatchingParen =
nullptr;
3054 IfRightBrace->MatchingParen =
nullptr;
3064void UnwrappedLineParser::parseTryCatch() {
3065 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) &&
"'try' expected");
3067 bool NeedsUnwrappedLine =
false;
3068 bool HasCtorInitializer =
false;
3069 if (FormatTok->is(tok::colon)) {
3070 auto *Colon = FormatTok;
3073 if (FormatTok->is(tok::identifier)) {
3074 HasCtorInitializer =
true;
3075 Colon->setFinalizedType(TT_CtorInitializerColon);
3080 while (FormatTok->is(tok::comma))
3083 while (FormatTok->is(tok::identifier)) {
3085 if (FormatTok->is(tok::l_paren)) {
3087 }
else if (FormatTok->is(tok::l_brace)) {
3094 while (FormatTok->is(tok::comma))
3099 if (Style.isJava() && FormatTok->is(tok::l_paren))
3102 keepAncestorBraces();
3104 if (FormatTok->is(tok::l_brace)) {
3105 if (HasCtorInitializer)
3106 FormatTok->setFinalizedType(TT_FunctionLBrace);
3107 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3109 if (Style.BraceWrapping.BeforeCatch)
3112 NeedsUnwrappedLine =
true;
3113 }
else if (FormatTok->isNot(tok::kw_catch)) {
3119 parseStructuralElement();
3122 for (
bool SeenCatch =
false;;) {
3123 if (FormatTok->is(tok::at))
3125 if (FormatTok->isNoneOf(tok::kw_catch, Keywords.kw___except,
3126 tok::kw___finally, tok::objc_catch,
3127 tok::objc_finally) &&
3128 !((Style.isJava() || Style.isJavaScript()) &&
3129 FormatTok->is(Keywords.kw_finally))) {
3132 if (FormatTok->is(tok::kw_catch))
3135 while (FormatTok->isNot(tok::l_brace)) {
3136 if (FormatTok->is(tok::l_paren)) {
3140 if (FormatTok->isOneOf(tok::semi, tok::r_brace) ||
eof()) {
3141 if (Style.RemoveBracesLLVM)
3142 NestedTooDeep.pop_back();
3148 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3151 NeedsUnwrappedLine =
false;
3152 Line->MustBeDeclaration =
false;
3153 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3155 if (Style.BraceWrapping.BeforeCatch)
3158 NeedsUnwrappedLine =
true;
3161 if (Style.RemoveBracesLLVM)
3162 NestedTooDeep.pop_back();
3164 if (NeedsUnwrappedLine)
3168void UnwrappedLineParser::parseNamespaceOrExportBlock(
unsigned AddLevels) {
3169 bool ManageWhitesmithsBraces =
3170 AddLevels == 0u && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
3174 if (ManageWhitesmithsBraces)
3179 parseBlock(
true, AddLevels,
true,
3180 true,
nullptr, ManageWhitesmithsBraces);
3182 addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
3184 if (ManageWhitesmithsBraces)
3188void UnwrappedLineParser::parseNamespace() {
3189 assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
3190 "'namespace' expected");
3194 if (InitialToken.is(TT_NamespaceMacro)) {
3197 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
3198 tok::l_square, tok::period, tok::l_paren) ||
3199 (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
3200 if (FormatTok->is(tok::l_square))
3202 else if (FormatTok->is(tok::l_paren))
3208 if (FormatTok->is(tok::l_brace)) {
3209 FormatTok->setFinalizedType(TT_NamespaceLBrace);
3214 unsigned AddLevels =
3215 Style.NamespaceIndentation == FormatStyle::NI_All ||
3216 (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
3217 DeclarationScopeStack.size() > 1)
3220 parseNamespaceOrExportBlock(AddLevels);
3225void UnwrappedLineParser::parseCppExportBlock() {
3226 parseNamespaceOrExportBlock(Style.IndentExportBlock ? 1 : 0);
3229void UnwrappedLineParser::parseNew() {
3230 assert(FormatTok->is(tok::kw_new) &&
"'new' expected");
3233 if (Style.isCSharp()) {
3236 if (FormatTok->is(tok::l_paren))
3240 if (FormatTok->is(tok::l_brace))
3243 if (FormatTok->isOneOf(tok::semi, tok::comma))
3250 if (!Style.isJava())
3256 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
3260 if (FormatTok->is(tok::l_paren)) {
3264 if (FormatTok->is(tok::l_brace))
3272void UnwrappedLineParser::parseLoopBody(
bool KeepBraces,
bool WrapRightBrace) {
3273 keepAncestorBraces();
3275 if (isBlockBegin(*FormatTok)) {
3276 FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3278 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3279 parseBlock(
false, 1u,
3281 setPreviousRBraceType(TT_ControlStatementRBrace);
3283 assert(!NestedTooDeep.empty());
3284 if (!NestedTooDeep.back())
3290 parseUnbracedBody();
3294 NestedTooDeep.pop_back();
3297void UnwrappedLineParser::parseForOrWhileLoop(
bool HasParens) {
3298 assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||
3299 (Style.isVerilog() &&
3300 FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,
3301 Keywords.kw_always_ff, Keywords.kw_always_latch,
3302 Keywords.kw_final, Keywords.kw_initial,
3303 Keywords.kw_foreach, Keywords.kw_forever,
3304 Keywords.kw_repeat))) &&
3305 "'for', 'while' or foreach macro expected");
3306 const bool KeepBraces = !Style.RemoveBracesLLVM ||
3307 FormatTok->isNoneOf(tok::kw_for, tok::kw_while);
3311 if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
3313 if (IsCpp && FormatTok->is(tok::kw_co_await))
3315 if (HasParens && FormatTok->is(tok::l_paren)) {
3319 if (Style.isVerilog())
3320 FormatTok->setFinalizedType(TT_ConditionLParen);
3324 if (Style.isVerilog()) {
3326 parseVerilogSensitivityList();
3327 }
else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&
3328 Tokens->getPreviousToken()->is(tok::r_paren)) {
3335 parseLoopBody(KeepBraces,
true);
3338void UnwrappedLineParser::parseDoWhile() {
3339 assert(FormatTok->is(tok::kw_do) &&
"'do' expected");
3342 parseLoopBody(
true, Style.BraceWrapping.BeforeWhile);
3345 if (FormatTok->isNot(tok::kw_while)) {
3350 FormatTok->setFinalizedType(TT_DoWhile);
3354 if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)
3358 parseStructuralElement();
3361void UnwrappedLineParser::parseLabel(
bool LeftAlignLabel) {
3363 unsigned OldLineLevel =
Line->Level;
3367 else if (
Line->Level > 1 || (!
Line->InPPDirective &&
Line->Level > 0))
3370 if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
3371 FormatTok->is(tok::l_brace)) {
3373 CompoundStatementIndenter Indenter(
this,
Line->Level,
3374 Style.BraceWrapping.AfterCaseLabel,
3375 Style.BraceWrapping.IndentBraces);
3377 if (FormatTok->is(tok::kw_break)) {
3378 if (Style.BraceWrapping.AfterControlStatement ==
3379 FormatStyle::BWACS_Always) {
3381 if (!Style.IndentCaseBlocks &&
3382 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
3386 parseStructuralElement();
3390 if (FormatTok->is(tok::semi))
3394 Line->Level = OldLineLevel;
3395 if (FormatTok->isNot(tok::l_brace)) {
3396 parseStructuralElement();
3401void UnwrappedLineParser::parseCaseLabel() {
3402 assert(FormatTok->is(tok::kw_case) &&
"'case' expected");
3403 auto *Case = FormatTok;
3408 if (FormatTok->is(tok::colon)) {
3409 FormatTok->setFinalizedType(TT_CaseLabelColon);
3412 if (Style.isJava() && FormatTok->is(tok::arrow)) {
3413 FormatTok->setFinalizedType(TT_CaseLabelArrow);
3414 Case->setFinalizedType(TT_SwitchExpressionLabel);
3421void UnwrappedLineParser::parseSwitch(
bool IsExpr) {
3422 assert(FormatTok->is(tok::kw_switch) &&
"'switch' expected");
3424 if (FormatTok->is(tok::l_paren))
3427 keepAncestorBraces();
3429 if (FormatTok->is(tok::l_brace)) {
3430 CompoundStatementIndenter Indenter(
this, Style,
Line->Level);
3431 FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
3432 : TT_ControlStatementLBrace);
3437 setPreviousRBraceType(TT_ControlStatementRBrace);
3443 parseStructuralElement();
3447 if (Style.RemoveBracesLLVM)
3448 NestedTooDeep.pop_back();
3451void UnwrappedLineParser::parseAccessSpecifier() {
3454 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
3457 if (FormatTok->is(tok::colon))
3465bool UnwrappedLineParser::parseRequires(
bool SeenEqual) {
3466 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3470 switch (Tokens->peekNextToken(
true)->Tok.getKind()) {
3473 parseRequiresExpression();
3480 parseRequiresClause();
3491 auto *PreviousNonComment = FormatTok->getPreviousNonComment();
3493 if (!PreviousNonComment ||
3494 PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
3497 parseRequiresClause();
3501 switch (PreviousNonComment->Tok.getKind()) {
3504 case tok::kw_noexcept:
3509 parseRequiresClause();
3518 auto PrevPrev = PreviousNonComment->getPreviousNonComment();
3519 if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {
3520 parseRequiresClause();
3526 if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
3528 parseRequiresClause();
3532 parseRequiresExpression();
3542 unsigned StoredPosition = Tokens->getPosition();
3545 auto PeekNext = [&Lookahead, &NextToken,
this] {
3547 NextToken = Tokens->getNextToken();
3550 bool FoundType =
false;
3551 bool LastWasColonColon =
false;
3554 for (; Lookahead < 50; PeekNext()) {
3555 switch (NextToken->Tok.getKind()) {
3556 case tok::kw_volatile:
3559 if (OpenAngles == 0) {
3560 FormatTok = Tokens->setPosition(StoredPosition);
3561 parseRequiresExpression();
3569 case tok::coloncolon:
3570 LastWasColonColon =
true;
3572 case tok::kw_decltype:
3573 case tok::identifier:
3574 if (FoundType && !LastWasColonColon && OpenAngles == 0) {
3575 FormatTok = Tokens->setPosition(StoredPosition);
3576 parseRequiresExpression();
3580 LastWasColonColon =
false;
3589 if (NextToken->isTypeName(LangOpts)) {
3590 FormatTok = Tokens->setPosition(StoredPosition);
3591 parseRequiresExpression();
3598 FormatTok = Tokens->setPosition(StoredPosition);
3599 parseRequiresClause();
3608void UnwrappedLineParser::parseRequiresClause() {
3609 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3614 bool InRequiresExpression =
3615 !FormatTok->Previous ||
3616 FormatTok->Previous->is(TT_RequiresExpressionLBrace);
3618 FormatTok->setFinalizedType(InRequiresExpression
3619 ? TT_RequiresClauseInARequiresExpression
3620 : TT_RequiresClause);
3625 parseConstraintExpression();
3627 if (!InRequiresExpression && FormatTok->Previous)
3628 FormatTok->Previous->ClosesRequiresClause =
true;
3636void UnwrappedLineParser::parseRequiresExpression() {
3637 assert(FormatTok->is(tok::kw_requires) &&
"'requires' expected");
3639 FormatTok->setFinalizedType(TT_RequiresExpression);
3642 if (FormatTok->is(tok::l_paren)) {
3643 FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
3647 if (FormatTok->is(tok::l_brace)) {
3648 FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
3657void UnwrappedLineParser::parseConstraintExpression() {
3664 bool LambdaNextTimeAllowed =
true;
3674 bool TopLevelParensAllowed =
true;
3677 bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed,
false);
3679 switch (FormatTok->Tok.getKind()) {
3680 case tok::kw_requires:
3681 parseRequiresExpression();
3685 if (!TopLevelParensAllowed)
3687 parseParens(TT_BinaryOperator);
3688 TopLevelParensAllowed =
false;
3692 if (!LambdaThisTimeAllowed || !tryToParseLambda())
3699 case tok::kw_struct:
3709 FormatTok->setFinalizedType(TT_BinaryOperator);
3711 LambdaNextTimeAllowed =
true;
3712 TopLevelParensAllowed =
true;
3717 LambdaNextTimeAllowed = LambdaThisTimeAllowed;
3721 case tok::kw_sizeof:
3723 case tok::greaterequal:
3724 case tok::greatergreater:
3726 case tok::lessequal:
3728 case tok::equalequal:
3730 case tok::exclaimequal:
3735 LambdaNextTimeAllowed =
true;
3736 TopLevelParensAllowed =
true;
3741 case tok::numeric_constant:
3742 case tok::coloncolon:
3745 TopLevelParensAllowed =
false;
3750 case tok::kw_static_cast:
3751 case tok::kw_const_cast:
3752 case tok::kw_reinterpret_cast:
3753 case tok::kw_dynamic_cast:
3755 if (FormatTok->isNot(tok::less))
3759 parseBracedList(
true);
3763 if (!FormatTok->Tok.getIdentifierInfo()) {
3773 assert(FormatTok->Previous);
3774 switch (FormatTok->Previous->Tok.getKind()) {
3775 case tok::coloncolon:
3779 case tok::kw_requires:
3788 if (FormatTok->is(tok::less)) {
3790 parseBracedList(
true);
3792 TopLevelParensAllowed =
false;
3798bool UnwrappedLineParser::parseEnum() {
3802 if (FormatTok->is(tok::kw_enum))
3808 if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
3812 if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))
3817 if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
3819 while (FormatTok->is(tok::l_square))
3820 if (!handleCppAttributes())
3824 while (FormatTok->Tok.getIdentifierInfo() ||
3825 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
3826 tok::greater, tok::comma, tok::question,
3828 if (Style.isVerilog()) {
3829 FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
3832 while (FormatTok->is(tok::l_square))
3838 if (FormatTok->is(tok::l_paren))
3840 if (FormatTok->is(tok::identifier)) {
3844 if (IsCpp && FormatTok->is(tok::identifier))
3850 if (FormatTok->isNot(tok::l_brace))
3852 FormatTok->setFinalizedType(TT_EnumLBrace);
3853 FormatTok->setBlockKind(BK_Block);
3855 if (Style.isJava()) {
3857 parseJavaEnumBody();
3860 if (Style.Language == FormatStyle::LK_Proto) {
3865 if (!Style.AllowShortEnumsOnASingleLine &&
3871 if (!Style.AllowShortEnumsOnASingleLine) {
3875 bool HasError = !parseBracedList(
false,
true);
3876 if (!Style.AllowShortEnumsOnASingleLine)
3879 if (FormatTok->is(tok::semi))
3883 setPreviousRBraceType(TT_EnumRBrace);
3891bool UnwrappedLineParser::parseStructLike() {
3896 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) {
3897 if (FormatTok->is(tok::semi))
3908class ScopedTokenPosition {
3909 unsigned StoredPosition;
3910 FormatTokenSource *Tokens;
3913 ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
3914 assert(Tokens &&
"Tokens expected to not be null");
3915 StoredPosition = Tokens->getPosition();
3918 ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
3924bool UnwrappedLineParser::tryToParseSimpleAttribute() {
3925 ScopedTokenPosition AutoPosition(Tokens);
3933 if (
Tok->
is(tok::r_square))
3935 Tok = Tokens->getNextToken();
3937 if (
Tok->
is(tok::eof))
3939 Tok = Tokens->getNextToken();
3942 Tok = Tokens->getNextToken();
3943 if (
Tok->
is(tok::semi))
3948void UnwrappedLineParser::parseJavaEnumBody() {
3949 assert(FormatTok->is(tok::l_brace));
3955 unsigned StoredPosition = Tokens->getPosition();
3956 bool IsSimple =
true;
3959 if (
Tok->
is(tok::r_brace))
3967 Tok = Tokens->getNextToken();
3969 FormatTok = Tokens->setPosition(StoredPosition);
3986 if (FormatTok->is(tok::l_brace)) {
3988 parseBlock(
true, 1u,
3990 }
else if (FormatTok->is(tok::l_paren)) {
3992 }
else if (FormatTok->is(tok::comma)) {
3995 }
else if (FormatTok->is(tok::semi)) {
3999 }
else if (FormatTok->is(tok::r_brace)) {
4008 parseLevel(OpeningBrace);
4014void UnwrappedLineParser::parseRecord(
bool ParseAsExpr,
bool IsJavaRecord) {
4015 assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record));
4020 IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok :
nullptr;
4021 bool IsDerived =
false;
4023 return Tok->
is(tok::identifier) &&
Tok->TokenText !=
Tok->TokenText.upper();
4027 bool JSPastExtendsOrImplements =
false;
4031 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
4032 tok::kw_alignas, tok::l_square) ||
4033 FormatTok->isAttribute() ||
4034 ((Style.isJava() || Style.isJavaScript()) &&
4035 FormatTok->isOneOf(tok::period, tok::comma))) {
4036 if (Style.isJavaScript() &&
4037 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
4038 JSPastExtendsOrImplements =
true;
4043 if (FormatTok->is(tok::l_brace)) {
4044 tryToParseBracedList();
4048 if (FormatTok->is(tok::l_square) && handleCppAttributes())
4052 switch (FormatTok->Tok.getKind()) {
4055 if (IsJavaRecord || !IsNonMacroIdentifier(
Previous) ||
4057 Previous->Previous == &InitialToken) {
4061 case tok::coloncolon:
4065 if (JSPastExtendsOrImplements || ClassName ||
4076 auto IsListInitialization = [&] {
4077 if (!ClassName || IsDerived || JSPastExtendsOrImplements)
4079 assert(FormatTok->is(tok::l_brace));
4080 const auto *Prev = FormatTok->getPreviousNonComment();
4082 return Prev != ClassName && Prev->is(tok::identifier) &&
4083 Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
4086 if (FormatTok->isOneOf(tok::colon, tok::less)) {
4087 int AngleNestingLevel = 0;
4089 if (FormatTok->is(tok::less))
4090 ++AngleNestingLevel;
4091 else if (FormatTok->is(tok::greater))
4092 --AngleNestingLevel;
4094 if (AngleNestingLevel == 0) {
4095 if (FormatTok->is(tok::colon)) {
4097 }
else if (!IsDerived && FormatTok->is(tok::identifier) &&
4098 FormatTok->Previous->is(tok::coloncolon)) {
4099 ClassName = FormatTok;
4100 }
else if (FormatTok->is(tok::l_paren) &&
4101 IsNonMacroIdentifier(FormatTok->Previous)) {
4105 if (FormatTok->is(tok::l_brace)) {
4106 if (AngleNestingLevel == 0 && IsListInitialization())
4108 calculateBraceTypes(
true);
4109 if (!tryToParseBracedList())
4112 if (FormatTok->is(tok::l_square)) {
4115 !
Previous->isTypeOrIdentifier(LangOpts))) {
4118 if (!tryToParseLambda())
4125 if (FormatTok->is(tok::semi))
4127 if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {
4130 parseCSharpGenericTypeConstraint();
4137 auto GetBraceTypes =
4138 [](
const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {
4139 switch (RecordTok.Tok.getKind()) {
4141 return {TT_ClassLBrace, TT_ClassRBrace};
4142 case tok::kw_struct:
4143 return {TT_StructLBrace, TT_StructRBrace};
4145 return {TT_UnionLBrace, TT_UnionRBrace};
4148 return {TT_RecordLBrace, TT_RecordRBrace};
4151 if (FormatTok->is(tok::l_brace)) {
4152 if (IsListInitialization())
4155 ClassName->setFinalizedType(TT_ClassHeadName);
4156 auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
4157 FormatTok->setFinalizedType(OpenBraceType);
4164 unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;
4165 parseBlock(
true, AddLevels,
false);
4167 setPreviousRBraceType(ClosingBraceType);
4174void UnwrappedLineParser::parseObjCMethod() {
4175 assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
4176 "'(' or identifier expected.");
4178 if (FormatTok->is(tok::semi)) {
4182 }
else if (FormatTok->is(tok::l_brace)) {
4183 if (Style.BraceWrapping.AfterFunction)
4194void UnwrappedLineParser::parseObjCProtocolList() {
4195 assert(FormatTok->is(tok::less) &&
"'<' expected.");
4199 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4201 }
while (!
eof() && FormatTok->isNot(tok::greater));
4205void UnwrappedLineParser::parseObjCUntilAtEnd() {
4207 if (FormatTok->is(tok::objc_end)) {
4212 if (FormatTok->is(tok::l_brace)) {
4216 }
else if (FormatTok->is(tok::r_brace)) {
4220 }
else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
4224 parseStructuralElement();
4229void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
4230 assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation));
4236 if (FormatTok->is(tok::less))
4237 parseObjCLightweightGenerics();
4238 if (FormatTok->is(tok::colon)) {
4242 if (FormatTok->is(tok::less))
4243 parseObjCLightweightGenerics();
4244 }
else if (FormatTok->is(tok::l_paren)) {
4249 if (FormatTok->is(tok::less))
4250 parseObjCProtocolList();
4252 if (FormatTok->is(tok::l_brace)) {
4253 if (Style.BraceWrapping.AfterObjCDeclaration)
4262 parseObjCUntilAtEnd();
4265void UnwrappedLineParser::parseObjCLightweightGenerics() {
4266 assert(FormatTok->is(tok::less));
4274 unsigned NumOpenAngles = 1;
4278 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
4280 if (FormatTok->is(tok::less)) {
4282 }
else if (FormatTok->is(tok::greater)) {
4283 assert(NumOpenAngles > 0 &&
"'>' makes NumOpenAngles negative");
4286 }
while (!
eof() && NumOpenAngles != 0);
4292bool UnwrappedLineParser::parseObjCProtocol() {
4293 assert(FormatTok->is(tok::objc_protocol));
4296 if (FormatTok->is(tok::l_paren)) {
4308 if (FormatTok->is(tok::less))
4309 parseObjCProtocolList();
4312 if (FormatTok->is(tok::semi)) {
4319 parseObjCUntilAtEnd();
4323void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
4324 bool IsImport = FormatTok->is(Keywords.kw_import);
4325 assert(IsImport || FormatTok->is(tok::kw_export));
4329 if (FormatTok->is(tok::kw_default))
4335 if (FormatTok->is(Keywords.kw_async))
4337 if (FormatTok->is(Keywords.kw_function)) {
4346 if (!IsImport && FormatTok->isNoneOf(tok::l_brace, tok::star) &&
4347 !FormatTok->isStringLiteral() &&
4348 !(FormatTok->is(Keywords.kw_type) &&
4349 Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {
4354 if (FormatTok->is(tok::semi))
4356 if (
Line->Tokens.empty()) {
4361 if (FormatTok->is(tok::l_brace)) {
4362 FormatTok->setBlockKind(BK_Block);
4371void UnwrappedLineParser::parseStatementMacro() {
4373 if (FormatTok->is(tok::l_paren))
4375 if (FormatTok->is(tok::semi))
4380void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
4383 if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
4384 tok::coloncolon, tok::hash) ||
4385 Keywords.isVerilogIdentifier(*FormatTok)) {
4387 }
else if (FormatTok->is(tok::l_square)) {
4395void UnwrappedLineParser::parseVerilogSensitivityList() {
4396 if (FormatTok->isNot(tok::at))
4400 if (FormatTok->is(tok::at))
4402 switch (FormatTok->Tok.getKind()) {
4410 parseVerilogHierarchyIdentifier();
4415unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
4416 unsigned AddLevels = 0;
4418 if (FormatTok->is(Keywords.kw_clocking)) {
4420 if (Keywords.isVerilogIdentifier(*FormatTok))
4422 parseVerilogSensitivityList();
4423 if (FormatTok->is(tok::semi))
4425 }
else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
4426 Keywords.kw_casez, Keywords.kw_randcase,
4427 Keywords.kw_randsequence)) {
4428 if (Style.IndentCaseLabels)
4431 if (FormatTok->is(tok::l_paren)) {
4432 FormatTok->setFinalizedType(TT_ConditionLParen);
4435 if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
4444 if (FormatTok->is(tok::l_square)) {
4445 auto Prev = FormatTok->getPreviousNonComment();
4446 if (Prev && Keywords.isVerilogIdentifier(*Prev))
4447 Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
4449 }
else if (Keywords.isVerilogIdentifier(*FormatTok) ||
4450 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
4451 Keywords.kw_automatic, tok::kw_static)) {
4458 auto NewLine = [
this]() {
4460 Line->IsContinuation =
true;
4464 while (FormatTok->is(Keywords.kw_import)) {
4467 parseVerilogHierarchyIdentifier();
4468 if (FormatTok->is(tok::semi))
4473 if (FormatTok->is(Keywords.kw_verilogHash)) {
4476 if (FormatTok->is(tok::l_paren)) {
4477 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4481 if (FormatTok->is(tok::l_paren)) {
4483 FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
4488 if (FormatTok->is(Keywords.kw_extends)) {
4491 parseVerilogHierarchyIdentifier();
4492 if (FormatTok->is(tok::l_paren))
4495 if (FormatTok->is(Keywords.kw_implements)) {
4499 parseVerilogHierarchyIdentifier();
4500 }
while (FormatTok->is(tok::comma));
4504 if (FormatTok->is(tok::at)) {
4506 parseVerilogSensitivityList();
4509 if (FormatTok->is(tok::semi))
4517void UnwrappedLineParser::parseVerilogTable() {
4518 assert(FormatTok->is(Keywords.kw_table));
4522 auto InitialLevel =
Line->Level++;
4523 while (!
eof() && !Keywords.isVerilogEnd(*FormatTok)) {
4526 if (
Tok->
is(tok::semi))
4528 else if (
Tok->
isOneOf(tok::star, tok::colon, tok::question, tok::minus))
4529 Tok->setFinalizedType(TT_VerilogTableItem);
4531 Line->Level = InitialLevel;
4536void UnwrappedLineParser::parseVerilogCaseLabel() {
4542 auto OrigLevel =
Line->Level;
4543 auto FirstLine = CurrentLines->size();
4544 if (
Line->Level == 0 || (
Line->InPPDirective &&
Line->Level <= 1))
4546 else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
4548 parseStructuralElement();
4551 if (CurrentLines->size() > FirstLine)
4552 (*CurrentLines)[FirstLine].Level = OrigLevel;
4553 Line->Level = OrigLevel;
4556void UnwrappedLineParser::parseVerilogExtern() {
4558 FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
4561 if (FormatTok->is(tok::string_literal))
4563 if (FormatTok->isOneOf(Keywords.kw_context, Keywords.kw_pure))
4565 if (Keywords.isVerilogIdentifier(*FormatTok))
4567 if (FormatTok->is(tok::equal))
4569 if (Keywords.isVerilogHierarchy(*FormatTok))
4570 parseVerilogHierarchyHeader();
4573bool UnwrappedLineParser::containsExpansion(
const UnwrappedLine &
Line)
const {
4574 for (
const auto &N :
Line.Tokens) {
4575 if (N.Tok->MacroCtx)
4577 for (
const UnwrappedLine &Child : N.Children)
4578 if (containsExpansion(Child))
4584void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
4585 if (
Line->Tokens.empty())
4588 if (!parsingPPDirective()) {
4589 llvm::dbgs() <<
"Adding unwrapped line:\n";
4590 printDebugInfo(*
Line);
4598 bool ClosesWhitesmithsBlock =
4599 Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
4600 Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
4605 if (!parsingPPDirective() && !InExpansion && containsExpansion(*
Line)) {
4607 Reconstruct.emplace(
Line->Level, Unexpanded);
4608 Reconstruct->addLine(*
Line);
4613 CurrentExpandedLines.push_back(std::move(*
Line));
4615 if (Reconstruct->finished()) {
4616 UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();
4617 assert(!Reconstructed.Tokens.empty() &&
4618 "Reconstructed must at least contain the macro identifier.");
4619 assert(!parsingPPDirective());
4621 llvm::dbgs() <<
"Adding unexpanded line:\n";
4622 printDebugInfo(Reconstructed);
4624 ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;
4625 Lines.push_back(std::move(Reconstructed));
4626 CurrentExpandedLines.clear();
4627 Reconstruct.reset();
4632 assert(!Reconstruct || (CurrentLines != &Lines) || !PPStack.empty());
4633 CurrentLines->push_back(std::move(*
Line));
4635 Line->Tokens.clear();
4636 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
4637 Line->FirstStartColumn = 0;
4638 Line->IsContinuation =
false;
4639 Line->SeenDecltypeAuto =
false;
4641 if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
4643 if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {
4644 CurrentLines->append(
4645 std::make_move_iterator(PreprocessorDirectives.begin()),
4646 std::make_move_iterator(PreprocessorDirectives.end()));
4647 PreprocessorDirectives.clear();
4650 FormatTok->Previous =
nullptr;
4653bool UnwrappedLineParser::eof()
const {
return FormatTok->is(tok::eof); }
4655bool UnwrappedLineParser::isOnNewLine(
const FormatToken &FormatTok) {
4656 return (
Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
4657 FormatTok.NewlinesBefore > 0;
4665 const llvm::Regex &CommentPragmasRegex) {
4666 if (
Line.Tokens.empty() || Style.ReflowComments != FormatStyle::RCS_Always)
4669 StringRef IndentContent = FormatTok.
TokenText;
4670 if (FormatTok.
TokenText.starts_with(
"//") ||
4671 FormatTok.
TokenText.starts_with(
"/*")) {
4672 IndentContent = FormatTok.
TokenText.substr(2);
4674 if (CommentPragmasRegex.match(IndentContent))
4749 if (PreviousToken && PreviousToken->
is(tok::l_brace) &&
4751 MinColumnToken = PreviousToken;
4754 PreviousToken = Node.
Tok;
4758 MinColumnToken = Node.
Tok;
4760 if (PreviousToken && PreviousToken->
is(tok::l_brace))
4761 MinColumnToken = PreviousToken;
4767void UnwrappedLineParser::flushComments(
bool NewlineBeforeNext) {
4768 bool JustComments =
Line->Tokens.empty();
4778 Tok->ContinuesLineCommentSection =
4779 continuesLineCommentSection(*
Tok, *
Line, Style, CommentPragmasRegex);
4780 if (isOnNewLine(*
Tok) && JustComments && !
Tok->ContinuesLineCommentSection)
4784 if (NewlineBeforeNext && JustComments)
4786 CommentsBeforeNextToken.clear();
4789void UnwrappedLineParser::nextToken(
int LevelDifference) {
4792 flushComments(isOnNewLine(*FormatTok));
4793 pushToken(FormatTok);
4795 if (!Style.isJavaScript())
4796 readToken(LevelDifference);
4798 readTokenWithJavaScriptASI();
4800 if (Style.isVerilog()) {
4807 if (Keywords.isVerilogEnd(*FormatTok))
4808 FormatTok->Tok.setKind(tok::r_brace);
4812void UnwrappedLineParser::distributeComments(
4832 if (Comments.empty())
4834 bool ShouldPushCommentsInCurrentLine =
true;
4835 bool HasTrailAlignedWithNextToken =
false;
4836 unsigned StartOfTrailAlignedWithNextToken = 0;
4839 for (
unsigned i = Comments.size() - 1; i > 0; --i) {
4841 HasTrailAlignedWithNextToken =
true;
4842 StartOfTrailAlignedWithNextToken = i;
4846 for (
unsigned i = 0, e = Comments.size(); i < e; ++i) {
4848 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
4849 FormatTok->ContinuesLineCommentSection =
false;
4852 *FormatTok, *
Line, Style, CommentPragmasRegex);
4854 if (!FormatTok->ContinuesLineCommentSection &&
4855 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
4856 ShouldPushCommentsInCurrentLine =
false;
4858 if (ShouldPushCommentsInCurrentLine)
4859 pushToken(FormatTok);
4861 CommentsBeforeNextToken.push_back(FormatTok);
4865void UnwrappedLineParser::readToken(
int LevelDifference) {
4867 bool PreviousWasComment =
false;
4868 bool FirstNonCommentOnLine =
false;
4870 FormatTok = Tokens->getNextToken();
4872 while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
4873 TT_ConflictAlternative)) {
4874 if (FormatTok->is(TT_ConflictStart))
4875 conditionalCompilationStart(
false);
4876 else if (FormatTok->is(TT_ConflictAlternative))
4877 conditionalCompilationAlternative();
4878 else if (FormatTok->is(TT_ConflictEnd))
4879 conditionalCompilationEnd();
4880 FormatTok = Tokens->getNextToken();
4881 FormatTok->MustBreakBefore =
true;
4882 FormatTok->MustBreakBeforeFinalized =
true;
4885 auto IsFirstNonCommentOnLine = [](
bool FirstNonCommentOnLine,
4887 bool PreviousWasComment) {
4889 return Tok.HasUnescapedNewline ||
Tok.IsFirst;
4894 if (PreviousWasComment)
4895 return FirstNonCommentOnLine || IsFirstOnLine(
Tok);
4896 return IsFirstOnLine(
Tok);
4899 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4900 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4901 PreviousWasComment = FormatTok->is(tok::comment);
4903 while (!
Line->InPPDirective && FormatTok->is(tok::hash) &&
4904 FirstNonCommentOnLine) {
4907 const auto *
Next = Tokens->peekNextToken();
4908 if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*
Next)) ||
4909 (Style.isTableGen() &&
4910 Next->isNoneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef,
4911 tok::pp_ifndef, tok::pp_endif))) {
4914 distributeComments(Comments, FormatTok);
4918 bool SwitchToPreprocessorLines = !
Line->Tokens.empty();
4919 ScopedLineState BlockState(*
this, SwitchToPreprocessorLines);
4920 assert((LevelDifference >= 0 ||
4921 static_cast<unsigned>(-LevelDifference) <=
Line->Level) &&
4922 "LevelDifference makes Line->Level negative");
4923 Line->Level += LevelDifference;
4927 if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
4928 PPBranchLevel > 0) {
4929 Line->Level += PPBranchLevel;
4931 assert(
Line->Level >=
Line->UnbracedBodyLevel);
4932 Line->Level -=
Line->UnbracedBodyLevel;
4933 flushComments(isOnNewLine(*FormatTok));
4935 PreviousWasComment = FormatTok->is(tok::comment);
4936 FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4937 FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4940 if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
4941 !
Line->InPPDirective) {
4945 if (FormatTok->is(tok::identifier) &&
4946 Macros.defined(FormatTok->TokenText) &&
4948 !
Line->InPPDirective) {
4950 unsigned Position = Tokens->getPosition();
4954 auto PreCall = std::move(
Line);
4955 Line.reset(
new UnwrappedLine);
4956 bool OldInExpansion = InExpansion;
4959 auto Args = parseMacroCall();
4960 InExpansion = OldInExpansion;
4961 assert(
Line->Tokens.front().Tok == ID);
4963 auto UnexpandedLine = std::move(
Line);
4965 Line = std::move(PreCall);
4968 llvm::dbgs() <<
"Macro call: " <<
ID->TokenText <<
"(";
4970 llvm::dbgs() <<
"(";
4971 for (
const auto &Arg : Args.value())
4972 for (
const auto &T : Arg)
4973 llvm::dbgs() << T->TokenText <<
" ";
4974 llvm::dbgs() <<
")";
4976 llvm::dbgs() <<
"\n";
4978 if (
Macros.objectLike(
ID->TokenText) && Args &&
4979 !
Macros.hasArity(
ID->TokenText, Args->size())) {
4985 LLVM_DEBUG(llvm::dbgs()
4986 <<
"Macro \"" <<
ID->TokenText
4987 <<
"\" not overloaded for arity " << Args->size()
4988 <<
"or not function-like, using object-like overload.");
4990 UnexpandedLine->Tokens.resize(1);
4991 Tokens->setPosition(Position);
4993 assert(!Args &&
Macros.objectLike(
ID->TokenText));
4995 if ((!Args &&
Macros.objectLike(
ID->TokenText)) ||
4996 (Args &&
Macros.hasArity(
ID->TokenText, Args->size()))) {
4999 Unexpanded[
ID] = std::move(UnexpandedLine);
5001 Macros.expand(ID, std::move(Args));
5002 if (!Expansion.empty())
5003 FormatTok = Tokens->insertTokens(Expansion);
5006 llvm::dbgs() <<
"Expanded: ";
5007 for (
const auto &T : Expansion)
5008 llvm::dbgs() << T->TokenText <<
" ";
5009 llvm::dbgs() <<
"\n";
5013 llvm::dbgs() <<
"Did not expand macro \"" <<
ID->TokenText
5014 <<
"\", because it was used ";
5016 llvm::dbgs() <<
"with " << Args->size();
5018 llvm::dbgs() <<
"without";
5019 llvm::dbgs() <<
" arguments, which doesn't match any definition.\n";
5021 Tokens->setPosition(Position);
5026 if (FormatTok->isNot(tok::comment)) {
5027 distributeComments(Comments, FormatTok);
5032 Comments.push_back(FormatTok);
5035 distributeComments(Comments,
nullptr);
5040template <
typename Iterator>
5041void pushTokens(Iterator Begin, Iterator End,
5043 for (
auto I = Begin; I != End; ++I) {
5044 Into.push_back(I->Tok);
5045 for (
const auto &Child : I->Children)
5046 pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);
5051std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
5052UnwrappedLineParser::parseMacroCall() {
5053 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;
5054 assert(
Line->Tokens.empty());
5056 if (FormatTok->isNot(tok::l_paren))
5058 unsigned Position = Tokens->getPosition();
5062 auto ArgStart = std::prev(
Line->Tokens.end());
5066 switch (FormatTok->Tok.getKind()) {
5071 case tok::r_paren: {
5077 Args->push_back({});
5078 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5087 Args->push_back({});
5088 pushTokens(std::next(ArgStart),
Line->Tokens.end(), Args->back());
5090 ArgStart = std::prev(
Line->Tokens.end());
5098 Line->Tokens.resize(1);
5099 Tokens->setPosition(Position);
5105 Line->Tokens.push_back(UnwrappedLineNode(
Tok));
5106 if (AtEndOfPPLine) {
5107 auto &
Tok = *
Line->Tokens.back().Tok;
5108 Tok.MustBreakBefore =
true;
5109 Tok.MustBreakBeforeFinalized =
true;
5110 Tok.FirstAfterPPLine =
true;
5111 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',...
@ 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.