aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp598
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;