diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
| commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
| tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp | |
| parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
| parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) | |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp | 598 |
1 files changed, 466 insertions, 132 deletions
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp index 83b4f1e7991f..3e58b6f90559 100644 --- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp +++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp @@ -41,13 +41,7 @@ public: // Returns the token that would be returned by the next call to // getNextToken(). - virtual FormatToken *peekNextToken() = 0; - - // Returns the token that would be returned after the next N calls to - // getNextToken(). N needs to be greater than zero, and small enough that - // there are still tokens. Check for tok::eof with N-1 before calling it with - // N. - virtual FormatToken *peekNextToken(int N) = 0; + virtual FormatToken *peekNextToken(bool SkipComment = false) = 0; // Returns whether we are at the end of the file. // This can be different from whether getNextToken() returned an eof token @@ -64,6 +58,39 @@ public: namespace { +void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line, + StringRef Prefix = "", bool PrintText = false) { + OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn + << ")" << (Line.InPPDirective ? " MACRO" : "") << ": "; + bool NewLine = false; + for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(), + E = Line.Tokens.end(); + I != E; ++I) { + if (NewLine) { + OS << Prefix; + NewLine = false; + } + OS << I->Tok->Tok.getName() << "[" + << "T=" << (unsigned)I->Tok->getType() + << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText + << "\"] "; + for (SmallVectorImpl<UnwrappedLine>::const_iterator + CI = I->Children.begin(), + CE = I->Children.end(); + CI != CE; ++CI) { + OS << "\n"; + printLine(OS, *CI, (Prefix + " ").str()); + NewLine = true; + } + } + if (!NewLine) + OS << "\n"; +} + +LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line) { + printLine(llvm::dbgs(), Line); +} + class ScopedDeclarationState { public: ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack, @@ -116,12 +143,14 @@ public: TokenSource = this; Line.Level = 0; Line.InPPDirective = true; + // InMacroBody gets set after the `#define x` part. } ~ScopedMacroState() override { TokenSource = PreviousTokenSource; ResetToken = Token; Line.InPPDirective = false; + Line.InMacroBody = false; Line.Level = PreviousLineLevel; } @@ -140,17 +169,10 @@ public: return PreviousTokenSource->getPreviousToken(); } - FormatToken *peekNextToken() override { + FormatToken *peekNextToken(bool SkipComment) override { if (eof()) return &FakeEOF; - return PreviousTokenSource->peekNextToken(); - } - - FormatToken *peekNextToken(int N) override { - assert(N > 0); - if (eof()) - return &FakeEOF; - return PreviousTokenSource->peekNextToken(N); + return PreviousTokenSource->peekNextToken(SkipComment); } bool isEOF() override { return PreviousTokenSource->isEOF(); } @@ -195,7 +217,9 @@ public: PreBlockLine = std::move(Parser.Line); Parser.Line = std::make_unique<UnwrappedLine>(); Parser.Line->Level = PreBlockLine->Level; + Parser.Line->PPLevel = PreBlockLine->PPLevel; Parser.Line->InPPDirective = PreBlockLine->InPPDirective; + Parser.Line->InMacroBody = PreBlockLine->InMacroBody; } ~ScopedLineState() { @@ -245,7 +269,7 @@ public: : Tokens(Tokens), Position(-1) {} FormatToken *getNextToken() override { - if (Position >= 0 && Tokens[Position]->is(tok::eof)) { + if (Position >= 0 && isEOF()) { LLVM_DEBUG({ llvm::dbgs() << "Next "; dbgToken(Position); @@ -264,8 +288,11 @@ public: return Position > 0 ? Tokens[Position - 1] : nullptr; } - FormatToken *peekNextToken() override { + FormatToken *peekNextToken(bool SkipComment) override { int Next = Position + 1; + if (SkipComment) + while (Tokens[Next]->is(tok::comment)) + ++Next; LLVM_DEBUG({ llvm::dbgs() << "Peeking "; dbgToken(Next); @@ -273,16 +300,6 @@ public: return Tokens[Next]; } - FormatToken *peekNextToken(int N) override { - assert(N > 0); - int Next = Position + N; - LLVM_DEBUG({ - llvm::dbgs() << "Peeking (+" << (N - 1) << ") "; - dbgToken(Next); - }); - return Tokens[Next]; - } - bool isEOF() override { return Tokens[Position]->is(tok::eof); } unsigned getPosition() override { @@ -573,12 +590,16 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, break; } // Else, if it is 'default:', fall through to the case handling. - LLVM_FALLTHROUGH; + [[fallthrough]]; } case tok::kw_case: - if (Style.isJavaScript() && Line->MustBeDeclaration) { - // A 'case: string' style field declaration. - parseStructuralElement(); + if (Style.isProto() || Style.isVerilog() || + (Style.isJavaScript() && Line->MustBeDeclaration)) { + // Proto: there are no switch/case statements + // Verilog: Case labels don't have this word. We handle case + // labels including default in TokenAnnotator. + // JavaScript: A 'case: string' style field declaration. + ParseDefault(); break; } if (!SwitchLabelEncountered && @@ -597,7 +618,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, } if (handleCppAttributes()) break; - LLVM_FALLTHROUGH; + [[fallthrough]]; default: ParseDefault(); break; @@ -733,7 +754,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { case tok::identifier: if (!Tok->is(TT_StatementMacro)) break; - LLVM_FALLTHROUGH; + [[fallthrough]]; case tok::at: case tok::semi: case tok::kw_if: @@ -812,9 +833,18 @@ bool UnwrappedLineParser::mightFitOnOneLine( auto Length = LastToken->TotalLength; if (OpeningBrace) { assert(OpeningBrace != Tokens.front().Tok); + if (auto Prev = OpeningBrace->Previous; + Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) { + Length -= ColumnLimit; + } Length -= OpeningBrace->TokenText.size() + 1; } + if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) { + assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace)); + Length -= FirstToken->TokenText.size() + 1; + } + Index = 0; for (auto &Token : Tokens) { const auto &SavedToken = SavedTokens[Index++]; @@ -823,6 +853,9 @@ bool UnwrappedLineParser::mightFitOnOneLine( delete SavedToken.Tok; } + // If these change PPLevel needs to be used for get correct indentation. + assert(!Line.InMacroBody); + assert(!Line.InPPDirective); return Line.Level * Style.IndentWidth + Length <= ColumnLimit; } @@ -839,8 +872,13 @@ FormatToken *UnwrappedLineParser::parseBlock( } }; + // Whether this is a Verilog-specific block that has a special header like a + // module. + const bool VerilogHierarchy = + Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok); assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) || - (Style.isVerilog() && Keywords.isVerilogBegin(*FormatTok))) && + (Style.isVerilog() && + (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) && "'{' or macro block token expected"); FormatToken *Tok = FormatTok; const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment); @@ -850,14 +888,20 @@ FormatToken *UnwrappedLineParser::parseBlock( // For Whitesmiths mode, jump to the next level prior to skipping over the // braces. - if (AddLevels > 0 && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) + if (!VerilogHierarchy && AddLevels > 0 && + Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) { ++Line->Level; + } size_t PPStartHash = computePPHash(); const unsigned InitialLevel = Line->Level; - nextToken(/*LevelDifference=*/AddLevels); - HandleVerilogBlockLabel(); + if (VerilogHierarchy) { + AddLevels += parseVerilogHierarchyHeader(); + } else { + nextToken(/*LevelDifference=*/AddLevels); + HandleVerilogBlockLabel(); + } // Bail out if there are too many levels. Otherwise, the stack might overflow. if (Line->Level > 300) @@ -899,6 +943,9 @@ FormatToken *UnwrappedLineParser::parseBlock( return IfLBrace; } + const bool IsFunctionRBrace = + FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace); + auto RemoveBraces = [=]() mutable { if (!SimpleBlock) return false; @@ -938,11 +985,24 @@ FormatToken *UnwrappedLineParser::parseBlock( // Munch the closing brace. nextToken(/*LevelDifference=*/-AddLevels); + + // When this is a function block and there is an unnecessary semicolon + // afterwards then mark it as optional (so the RemoveSemi pass can get rid of + // it later). + if (Style.RemoveSemicolon && IsFunctionRBrace) { + while (FormatTok->is(tok::semi)) { + FormatTok->Optional = true; + nextToken(); + } + } + HandleVerilogBlockLabel(); if (MacroBlock && FormatTok->is(tok::l_paren)) parseParens(); + Line->Level = InitialLevel; + if (FormatTok->is(tok::kw_noexcept)) { // A noexcept in a requires expression. nextToken(); @@ -958,8 +1018,6 @@ FormatToken *UnwrappedLineParser::parseBlock( if (MunchSemi && FormatTok->is(tok::semi)) nextToken(); - Line->Level = InitialLevel; - if (PPStartHash == PPEndHash) { Line->MatchingOpeningBlockLineIndex = OpeningLineIndex; if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) { @@ -1073,16 +1131,17 @@ void UnwrappedLineParser::parsePPDirective() { parsePPIf(/*IfDef=*/true); break; case tok::pp_else: - parsePPElse(); - break; case tok::pp_elifdef: case tok::pp_elifndef: case tok::pp_elif: - parsePPElIf(); + parsePPElse(); break; case tok::pp_endif: parsePPEndIf(); break; + case tok::pp_pragma: + parsePPPragma(); + break; default: parsePPUnknown(); break; @@ -1109,7 +1168,7 @@ void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) { PPLevelBranchIndex.push_back(0); PPLevelBranchCount.push_back(0); } - PPChainBranchIndex.push(0); + PPChainBranchIndex.push(Unreachable ? -1 : 0); bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0; conditionalCompilationCondition(Unreachable || Skip); } @@ -1175,15 +1234,16 @@ void UnwrappedLineParser::parsePPElse() { // If a potential include guard has an #else, it's not an include guard. if (IncludeGuard == IG_Defined && PPBranchLevel == 0) IncludeGuard = IG_Rejected; + // Don't crash when there is an #else without an #if. + assert(PPBranchLevel >= -1); + if (PPBranchLevel == -1) + conditionalCompilationStart(/*Unreachable=*/true); conditionalCompilationAlternative(); - if (PPBranchLevel > -1) - --PPBranchLevel; + --PPBranchLevel; parsePPUnknown(); ++PPBranchLevel; } -void UnwrappedLineParser::parsePPElIf() { parsePPElse(); } - void UnwrappedLineParser::parsePPEndIf() { conditionalCompilationEnd(); parsePPUnknown(); @@ -1234,6 +1294,10 @@ void UnwrappedLineParser::parsePPDefine() { addUnwrappedLine(); ++Line->Level; + Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1); + assert((int)Line->PPLevel >= 0); + Line->InMacroBody = true; + // Errors during a preprocessor directive can only affect the layout of the // preprocessor directive, and thus we ignore them. An alternative approach // would be to use the same approach we use on the file level (no @@ -1242,6 +1306,11 @@ void UnwrappedLineParser::parsePPDefine() { parseFile(); } +void UnwrappedLineParser::parsePPPragma() { + Line->InPragmaDirective = true; + parsePPUnknown(); +} + void UnwrappedLineParser::parsePPUnknown() { do { nextToken(); @@ -1369,7 +1438,15 @@ static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next, return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma); } -void UnwrappedLineParser::parseModuleImport() { +bool UnwrappedLineParser::parseModuleImport() { + assert(FormatTok->is(Keywords.kw_import) && "'import' expected"); + + if (auto Token = Tokens->peekNextToken(/*SkipComment=*/true); + !Token->Tok.getIdentifierInfo() && + !Token->isOneOf(tok::colon, tok::less, tok::string_literal)) { + return false; + } + nextToken(); while (!eof()) { if (FormatTok->is(tok::colon)) { @@ -1396,6 +1473,7 @@ void UnwrappedLineParser::parseModuleImport() { } addUnwrappedLine(); + return true; } // readTokenWithJavaScriptASI reads the next token and terminates the current @@ -1457,13 +1535,30 @@ void UnwrappedLineParser::parseStructuralElement( addUnwrappedLine(); return; } + + if (Style.isVerilog()) { + // Skip things that can exist before keywords like 'if' and 'case'. + while (true) { + if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique, + Keywords.kw_unique0)) { + nextToken(); + } else if (FormatTok->is(tok::l_paren) && + Tokens->peekNextToken()->is(tok::star)) { + parseParens(); + } else { + break; + } + } + } + + // Tokens that only make sense at the beginning of a line. switch (FormatTok->Tok.getKind()) { case tok::kw_asm: nextToken(); if (FormatTok->is(tok::l_brace)) { FormatTok->setFinalizedType(TT_InlineASMBrace); nextToken(); - while (FormatTok && FormatTok->isNot(tok::eof)) { + while (FormatTok && !eof()) { if (FormatTok->is(tok::r_brace)) { FormatTok->setFinalizedType(TT_InlineASMBrace); nextToken(); @@ -1523,6 +1618,9 @@ void UnwrappedLineParser::parseStructuralElement( parseSwitch(); return; case tok::kw_default: + // In Verilog default along with other labels are handled in the next loop. + if (Style.isVerilog()) + break; if (Style.isJavaScript() && Line->MustBeDeclaration) { // 'default: string' field declaration. break; @@ -1535,6 +1633,16 @@ void UnwrappedLineParser::parseStructuralElement( // e.g. "default void f() {}" in a Java interface. break; case tok::kw_case: + // Proto: there are no switch/case statements. + if (Style.isProto()) { + nextToken(); + return; + } + if (Style.isVerilog()) { + parseBlock(); + addUnwrappedLine(); + return; + } if (Style.isJavaScript() && Line->MustBeDeclaration) { // 'case: string' field declaration. nextToken(); @@ -1552,7 +1660,14 @@ void UnwrappedLineParser::parseStructuralElement( return; case tok::kw_extern: nextToken(); - if (FormatTok->is(tok::string_literal)) { + if (Style.isVerilog()) { + // In Verilog and extern module declaration looks like a start of module. + // But there is no body and endmodule. So we handle it separately. + if (Keywords.isVerilogHierarchy(*FormatTok)) { + parseVerilogHierarchyHeader(); + return; + } + } else if (FormatTok->is(tok::string_literal)) { nextToken(); if (FormatTok->is(tok::l_brace)) { if (Style.BraceWrapping.AfterExternBlock) @@ -1577,10 +1692,16 @@ void UnwrappedLineParser::parseStructuralElement( parseJavaScriptEs6ImportExport(); return; } - if (!Style.isCpp()) - break; - // Handle C++ "(inline|export) namespace". - LLVM_FALLTHROUGH; + if (Style.isCpp()) { + nextToken(); + if (FormatTok->is(tok::kw_namespace)) { + parseNamespace(); + return; + } + if (FormatTok->is(Keywords.kw_import) && parseModuleImport()) + return; + } + break; case tok::kw_inline: nextToken(); if (FormatTok->is(tok::kw_namespace)) { @@ -1615,10 +1736,8 @@ void UnwrappedLineParser::parseStructuralElement( addUnwrappedLine(); return; } - if (Style.isCpp()) { - parseModuleImport(); + if (Style.isCpp() && parseModuleImport()) return; - } } if (Style.isCpp() && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals, @@ -1712,9 +1831,6 @@ void UnwrappedLineParser::parseStructuralElement( break; } break; - case tok::kw_concept: - parseConcept(); - return; case tok::kw_requires: { if (Style.isCpp()) { bool ParsedClause = parseRequires(); @@ -1751,9 +1867,15 @@ void UnwrappedLineParser::parseStructuralElement( parseEnum(); } break; + case tok::kw_class: + if (Style.isVerilog()) { + parseBlock(); + addUnwrappedLine(); + return; + } + [[fallthrough]]; case tok::kw_struct: case tok::kw_union: - case tok::kw_class: if (parseStructLike()) return; break; @@ -1782,9 +1904,11 @@ void UnwrappedLineParser::parseStructuralElement( parseParens(); // Break the unwrapped line if a K&R C function definition has a parameter // declaration. - if (!IsTopLevel || !Style.isCpp() || !Previous || FormatTok->is(tok::eof)) + if (!IsTopLevel || !Style.isCpp() || !Previous || eof()) break; - if (isC78ParameterDecl(FormatTok, Tokens->peekNextToken(), Previous)) { + if (isC78ParameterDecl(FormatTok, + Tokens->peekNextToken(/*SkipComment=*/true), + Previous)) { addUnwrappedLine(); return; } @@ -1825,8 +1949,7 @@ void UnwrappedLineParser::parseStructuralElement( } else if (Style.BraceWrapping.AfterFunction) { addUnwrappedLine(); } - if (!Line->InPPDirective) - FormatTok->setFinalizedType(TT_FunctionLBrace); + FormatTok->setFinalizedType(TT_FunctionLBrace); parseBlock(); addUnwrappedLine(); return; @@ -1888,6 +2011,19 @@ void UnwrappedLineParser::parseStructuralElement( return; } + if (Style.isVerilog()) { + if (FormatTok->is(Keywords.kw_table)) { + parseVerilogTable(); + return; + } + if (Keywords.isVerilogBegin(*FormatTok) || + Keywords.isVerilogHierarchy(*FormatTok)) { + parseBlock(); + addUnwrappedLine(); + return; + } + } + if (FormatTok->is(Keywords.kw_interface)) { if (parseStructLike()) return; @@ -1919,7 +2055,9 @@ void UnwrappedLineParser::parseStructuralElement( return I != E && (++I == E); }; if (OneTokenSoFar()) { - if (FormatTok->is(tok::colon) && !Line->MustBeDeclaration) { + // In Verilog labels can be any expression, so we don't do them here. + if (!Style.isVerilog() && FormatTok->is(tok::colon) && + !Line->MustBeDeclaration) { Line->Tokens.begin()->Tok->MustBreakBefore = true; parseLabel(!Style.IndentGotoLabels); if (HasLabel) @@ -1939,7 +2077,8 @@ void UnwrappedLineParser::parseStructuralElement( if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) && tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) { - PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro); + if (PreviousToken->isNot(TT_UntouchableMacroFunc)) + PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro); addUnwrappedLine(); return; } @@ -1976,6 +2115,17 @@ void UnwrappedLineParser::parseStructuralElement( parseNew(); break; case tok::kw_case: + // Proto: there are no switch/case statements. + if (Style.isProto()) { + nextToken(); + return; + } + // In Verilog switch is called case. + if (Style.isVerilog()) { + parseBlock(); + addUnwrappedLine(); + return; + } if (Style.isJavaScript() && Line->MustBeDeclaration) { // 'case: string' field declaration. nextToken(); @@ -1983,6 +2133,30 @@ void UnwrappedLineParser::parseStructuralElement( } parseCaseLabel(); break; + case tok::kw_default: + nextToken(); + if (Style.isVerilog()) { + if (FormatTok->is(tok::colon)) { + // The label will be handled in the next iteration. + break; + } + if (FormatTok->is(Keywords.kw_clocking)) { + // A default clocking block. + parseBlock(); + addUnwrappedLine(); + return; + } + parseVerilogCaseLabel(); + return; + } + break; + case tok::colon: + nextToken(); + if (Style.isVerilog()) { + parseVerilogCaseLabel(); + return; + } + break; default: nextToken(); break; @@ -2108,26 +2282,29 @@ bool UnwrappedLineParser::tryToParseLambda() { case tok::l_square: parseSquare(); break; - case tok::kw_class: - case tok::kw_template: - case tok::kw_typename: + case tok::less: assert(FormatTok->Previous); - if (FormatTok->Previous->is(tok::less)) + if (FormatTok->Previous->is(tok::r_square)) InTemplateParameterList = true; nextToken(); break; + case tok::kw_auto: + case tok::kw_class: + case tok::kw_template: + case tok::kw_typename: case tok::amp: case tok::star: case tok::kw_const: case tok::kw_constexpr: + case tok::kw_consteval: case tok::comma: - case tok::less: case tok::greater: case tok::identifier: case tok::numeric_constant: case tok::coloncolon: case tok::kw_mutable: case tok::kw_noexcept: + case tok::kw_static: nextToken(); break; // Specialization of a template with an integer parameter can contain @@ -2201,7 +2378,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() { if (FormatTok->is(tok::l_square)) return false; if (FormatTok->is(tok::r_square)) { - const FormatToken *Next = Tokens->peekNextToken(); + const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true); if (Next->is(tok::greater)) return false; } @@ -2432,7 +2609,7 @@ void UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { case tok::ampamp: if (AmpAmpTokenType != TT_Unknown) FormatTok->setFinalizedType(AmpAmpTokenType); - LLVM_FALLTHROUGH; + [[fallthrough]]; default: nextToken(); break; @@ -2502,8 +2679,10 @@ void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) { FormatToken *Tok = nullptr; if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() && - PreprocessorDirectives.empty()) { - Tok = getLastNonComment(*Line); + PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) { + Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never + ? getLastNonComment(*Line) + : Line->Tokens.back().Tok; assert(Tok); if (Tok->BraceCount < 0) { assert(Tok->BraceCount == -1); @@ -2530,7 +2709,7 @@ void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) { ++Tok->BraceCount; } - if (CheckEOF && FormatTok->is(tok::eof)) + if (CheckEOF && eof()) addUnwrappedLine(); --Line->Level; @@ -2572,6 +2751,14 @@ bool UnwrappedLineParser::handleCppAttributes() { return false; } +/// Returns whether \c Tok begins a block. +bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const { + // FIXME: rename the function or make + // Tok.isOneOf(tok::l_brace, TT_MacroBlockBegin) work. + return Style.isVerilog() ? Keywords.isVerilogBegin(Tok) + : Tok.is(tok::l_brace); +} + FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, bool KeepBraces) { assert(FormatTok->is(tok::kw_if) && "'if' expected"); @@ -2597,7 +2784,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, FormatToken *IfLeftBrace = nullptr; IfStmtKind IfBlockKind = IfStmtKind::NotIf; - if (Keywords.isBlockBegin(*FormatTok, Style)) { + if (isBlockBegin(*FormatTok)) { FormatTok->setFinalizedType(TT_ControlStatementLBrace); IfLeftBrace = FormatTok; CompoundStatementIndenter Indenter(this, Style, Line->Level); @@ -2630,7 +2817,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, } nextToken(); handleAttributes(); - if (Keywords.isBlockBegin(*FormatTok, Style)) { + if (isBlockBegin(*FormatTok)) { const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if); FormatTok->setFinalizedType(TT_ElseLBrace); ElseLeftBrace = FormatTok; @@ -2862,6 +3049,11 @@ void UnwrappedLineParser::parseNew() { if (Style.isCSharp()) { do { + // Handle constructor invocation, e.g. `new(field: value)`. + if (FormatTok->is(tok::l_paren)) + parseParens(); + + // Handle array initialization syntax, e.g. `new[] {10, 20, 30}`. if (FormatTok->is(tok::l_brace)) parseBracedList(); @@ -2897,7 +3089,7 @@ void UnwrappedLineParser::parseNew() { void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) { keepAncestorBraces(); - if (Keywords.isBlockBegin(*FormatTok, Style)) { + if (isBlockBegin(*FormatTok)) { if (!KeepBraces) FormatTok->setFinalizedType(TT_ControlStatementLBrace); FormatToken *LeftBrace = FormatTok; @@ -3102,26 +3294,6 @@ void UnwrappedLineParser::parseAccessSpecifier() { } } -/// \brief Parses a concept definition. -/// \pre The current token has to be the concept keyword. -/// -/// Returns if either the concept has been completely parsed, or if it detects -/// that the concept definition is incorrect. -void UnwrappedLineParser::parseConcept() { - assert(FormatTok->is(tok::kw_concept) && "'concept' expected"); - nextToken(); - if (!FormatTok->is(tok::identifier)) - return; - nextToken(); - if (!FormatTok->is(tok::equal)) - return; - nextToken(); - parseConstraintExpression(); - if (FormatTok->is(tok::semi)) - nextToken(); - addUnwrappedLine(); -} - /// \brief Parses a requires, decides if it is a clause or an expression. /// \pre The current token has to be the requires keyword. /// \returns true if it parsed a clause. @@ -3204,37 +3376,41 @@ bool clang::format::UnwrappedLineParser::parseRequires() { // So we want basically to check for TYPE NAME, but TYPE can contain all kinds // of stuff: typename, const, *, &, &&, ::, identifiers. - int NextTokenOffset = 1; - auto NextToken = Tokens->peekNextToken(NextTokenOffset); - auto PeekNext = [&NextTokenOffset, &NextToken, this] { - ++NextTokenOffset; - NextToken = Tokens->peekNextToken(NextTokenOffset); + unsigned StoredPosition = Tokens->getPosition(); + FormatToken *NextToken = Tokens->getNextToken(); + int Lookahead = 0; + auto PeekNext = [&Lookahead, &NextToken, this] { + ++Lookahead; + NextToken = Tokens->getNextToken(); }; bool FoundType = false; bool LastWasColonColon = false; int OpenAngles = 0; - for (; NextTokenOffset < 50; PeekNext()) { + for (; Lookahead < 50; PeekNext()) { switch (NextToken->Tok.getKind()) { case tok::kw_volatile: case tok::kw_const: case tok::comma: + FormatTok = Tokens->setPosition(StoredPosition); parseRequiresExpression(RequiresToken); return false; case tok::r_paren: case tok::pipepipe: + FormatTok = Tokens->setPosition(StoredPosition); parseRequiresClause(RequiresToken); return true; case tok::eof: // Break out of the loop. - NextTokenOffset = 50; + Lookahead = 50; break; case tok::coloncolon: LastWasColonColon = true; break; case tok::identifier: if (FoundType && !LastWasColonColon && OpenAngles == 0) { + FormatTok = Tokens->setPosition(StoredPosition); parseRequiresExpression(RequiresToken); return false; } @@ -3249,14 +3425,15 @@ bool clang::format::UnwrappedLineParser::parseRequires() { break; default: if (NextToken->isSimpleTypeSpecifier()) { + FormatTok = Tokens->setPosition(StoredPosition); parseRequiresExpression(RequiresToken); return false; } break; } } - // This seems to be a complicated expression, just assume it's a clause. + FormatTok = Tokens->setPosition(StoredPosition); parseRequiresClause(RequiresToken); return true; } @@ -3283,6 +3460,8 @@ void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) { ? TT_RequiresClauseInARequiresExpression : TT_RequiresClause); + // NOTE: parseConstraintExpression is only ever called from this function. + // It could be inlined into here. parseConstraintExpression(); if (!InRequiresExpression) @@ -3316,9 +3495,8 @@ void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) { /// \brief Parses a constraint expression. /// -/// This is either the definition of a concept, or the body of a requires -/// clause. It returns, when the parsing is complete, or the expression is -/// incorrect. +/// This is the body of a requires clause. It returns, when the parsing is +/// complete, or the expression is incorrect. void UnwrappedLineParser::parseConstraintExpression() { // The special handling for lambdas is needed since tryToParseLambda() eats a // token and if a requires expression is the last part of a requires clause @@ -3385,7 +3563,6 @@ void UnwrappedLineParser::parseConstraintExpression() { case tok::minus: case tok::star: case tok::slash: - case tok::kw_decltype: LambdaNextTimeAllowed = true; // Just eat them. nextToken(); @@ -3417,9 +3594,9 @@ void UnwrappedLineParser::parseConstraintExpression() { // concept C = bool(...); // and bool is the only type, all other types as cast must be inside a // cast to bool an thus are handled by the other cases. - nextToken(); - if (FormatTok->isNot(tok::l_paren)) + if (Tokens->peekNextToken()->isNot(tok::l_paren)) return; + nextToken(); parseParens(); break; @@ -3438,7 +3615,8 @@ void UnwrappedLineParser::parseConstraintExpression() { switch (FormatTok->Previous->Tok.getKind()) { case tok::coloncolon: // Nested identifier. case tok::ampamp: // Start of a function or variable for the - case tok::pipepipe: // constraint expression. + case tok::pipepipe: // constraint expression. (binary) + case tok::exclaim: // The same as above, but unary. case tok::kw_requires: // Initial identifier of a requires clause. case tok::equal: // Initial identifier of a concept declaration. break; @@ -3639,7 +3817,7 @@ void UnwrappedLineParser::parseJavaEnumBody() { ++Line->Level; // Parse the enum constants. - while (FormatTok->isNot(tok::eof)) { + while (!eof()) { if (FormatTok->is(tok::l_brace)) { // Parse the constant's class body. parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u, @@ -3989,21 +4167,176 @@ void UnwrappedLineParser::parseStatementMacro() { addUnwrappedLine(); } -LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line, - StringRef Prefix = "") { - llvm::dbgs() << Prefix << "Line(" << Line.Level - << ", FSC=" << Line.FirstStartColumn << ")" - << (Line.InPPDirective ? " MACRO" : "") << ": "; - for (const auto &Node : Line.Tokens) { - llvm::dbgs() << Node.Tok->Tok.getName() << "[" - << "T=" << static_cast<unsigned>(Node.Tok->getType()) - << ", OC=" << Node.Tok->OriginalColumn << "] "; - } - for (const auto &Node : Line.Tokens) - for (const auto &ChildNode : Node.Children) - printDebugInfo(ChildNode, "\nChild: "); - - llvm::dbgs() << "\n"; +void UnwrappedLineParser::parseVerilogHierarchyIdentifier() { + // consume things like a::`b.c[d:e] or a::* + while (true) { + if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar, + tok::coloncolon, tok::hash) || + Keywords.isVerilogIdentifier(*FormatTok)) { + nextToken(); + } else if (FormatTok->is(tok::l_square)) { + parseSquare(); + } else { + break; + } + } +} + +void UnwrappedLineParser::parseVerilogSensitivityList() { + if (!FormatTok->is(tok::at)) + return; + nextToken(); + // A block event expression has 2 at signs. + if (FormatTok->is(tok::at)) + nextToken(); + switch (FormatTok->Tok.getKind()) { + case tok::star: + nextToken(); + break; + case tok::l_paren: + parseParens(); + break; + default: + parseVerilogHierarchyIdentifier(); + break; + } +} + +unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() { + unsigned AddLevels = 0; + + if (FormatTok->is(Keywords.kw_clocking)) { + nextToken(); + if (Keywords.isVerilogIdentifier(*FormatTok)) + nextToken(); + parseVerilogSensitivityList(); + if (FormatTok->is(tok::semi)) + nextToken(); + } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex, + Keywords.kw_casez, Keywords.kw_randcase, + Keywords.kw_randsequence)) { + if (Style.IndentCaseLabels) + AddLevels++; + nextToken(); + if (FormatTok->is(tok::l_paren)) { + FormatTok->setFinalizedType(TT_ConditionLParen); + parseParens(); + } + if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches)) + nextToken(); + // The case header has no semicolon. + } else { + // "module" etc. + nextToken(); + // all the words like the name of the module and specifiers like + // "automatic" and the width of function return type + while (true) { + if (FormatTok->is(tok::l_square)) { + auto Prev = FormatTok->getPreviousNonComment(); + if (Prev && Keywords.isVerilogIdentifier(*Prev)) + Prev->setFinalizedType(TT_VerilogDimensionedTypeName); + parseSquare(); + } else if (Keywords.isVerilogIdentifier(*FormatTok) || + FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) { + nextToken(); + } else { + break; + } + } + + auto NewLine = [this]() { + addUnwrappedLine(); + Line->IsContinuation = true; + }; + + // package imports + while (FormatTok->is(Keywords.kw_import)) { + NewLine(); + nextToken(); + parseVerilogHierarchyIdentifier(); + if (FormatTok->is(tok::semi)) + nextToken(); + } + + // parameters and ports + if (FormatTok->is(Keywords.kw_verilogHash)) { + NewLine(); + nextToken(); + if (FormatTok->is(tok::l_paren)) + parseParens(); + } + if (FormatTok->is(tok::l_paren)) { + NewLine(); + parseParens(); + } + + // extends and implements + if (FormatTok->is(Keywords.kw_extends)) { + NewLine(); + nextToken(); + parseVerilogHierarchyIdentifier(); + if (FormatTok->is(tok::l_paren)) + parseParens(); + } + if (FormatTok->is(Keywords.kw_implements)) { + NewLine(); + do { + nextToken(); + parseVerilogHierarchyIdentifier(); + } while (FormatTok->is(tok::comma)); + } + + // Coverage event for cover groups. + if (FormatTok->is(tok::at)) { + NewLine(); + parseVerilogSensitivityList(); + } + + if (FormatTok->is(tok::semi)) + nextToken(/*LevelDifference=*/1); + addUnwrappedLine(); + } + + return AddLevels; +} + +void UnwrappedLineParser::parseVerilogTable() { + assert(FormatTok->is(Keywords.kw_table)); + nextToken(/*LevelDifference=*/1); + addUnwrappedLine(); + + auto InitialLevel = Line->Level++; + while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) { + FormatToken *Tok = FormatTok; + nextToken(); + if (Tok->is(tok::semi)) + addUnwrappedLine(); + else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus)) + Tok->setFinalizedType(TT_VerilogTableItem); + } + Line->Level = InitialLevel; + nextToken(/*LevelDifference=*/-1); + addUnwrappedLine(); +} + +void UnwrappedLineParser::parseVerilogCaseLabel() { + // The label will get unindented in AnnotatingParser. If there are no leading + // spaces, indent the rest here so that things inside the block will be + // indented relative to things outside. We don't use parseLabel because we + // don't know whether this colon is a label or a ternary expression at this + // point. + auto OrigLevel = Line->Level; + auto FirstLine = CurrentLines->size(); + if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1)) + ++Line->Level; + else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok)) + --Line->Level; + parseStructuralElement(); + // Restore the indentation in both the new line and the line that has the + // label. + if (CurrentLines->size() > FirstLine) + (*CurrentLines)[FirstLine].Level = OrigLevel; + Line->Level = OrigLevel; } void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { @@ -4026,6 +4359,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { Line->Tokens.clear(); Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex; Line->FirstStartColumn = 0; + Line->IsContinuation = false; if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove) --Line->Level; |
