diff options
Diffstat (limited to 'clang/lib/Format/UnwrappedLineParser.cpp')
-rw-r--r-- | clang/lib/Format/UnwrappedLineParser.cpp | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 50d41c9f57a6..b904e0e56d9e 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1170,6 +1170,15 @@ void UnwrappedLineParser::parsePPDefine() { assert((int)Line->PPLevel >= 0); Line->InMacroBody = true; + if (Style.SkipMacroDefinitionBody) { + do { + FormatTok->Finalized = true; + nextToken(); + } while (!eof()); + addUnwrappedLine(); + return; + } + if (FormatTok->is(tok::identifier) && Tokens->peekNextToken()->is(tok::colon)) { nextToken(); @@ -1652,7 +1661,8 @@ void UnwrappedLineParser::parseStructuralElement( // In Verilog labels can be any expression, so we don't do them here. // JS doesn't have macros, and within classes colons indicate fields, not // labels. - if (!Style.isJavaScript() && !Style.isVerilog() && + // TableGen doesn't have labels. + if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() && Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) { nextToken(); Line->Tokens.begin()->Tok->MustBreakBefore = true; @@ -1781,6 +1791,12 @@ void UnwrappedLineParser::parseStructuralElement( addUnwrappedLine(); return; } + if (Style.isTableGen()) { + // Do nothing special. In this case the l_brace becomes FunctionLBrace. + // This is same as def and so on. + nextToken(); + break; + } [[fallthrough]]; case tok::kw_struct: case tok::kw_union: @@ -2019,6 +2035,16 @@ void UnwrappedLineParser::parseStructuralElement( // initialisers are indented the same way. if (Style.isCSharp()) FormatTok->setBlockKind(BK_BracedInit); + // TableGen's defset statement has syntax of the form, + // `defset <type> <name> = { <statement>... }` + if (Style.isTableGen() && + Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) { + FormatTok->setFinalizedType(TT_FunctionLBrace); + parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, + /*MunchSemi=*/false); + addUnwrappedLine(); + break; + } nextToken(); parseBracedList(); } else if (Style.Language == FormatStyle::LK_Proto && @@ -2734,6 +2760,14 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, } } + // TableGen's if statement has the form of `if <cond> then { ... }`. + if (Style.isTableGen()) { + while (!eof() && FormatTok->isNot(Keywords.kw_then)) { + // Simply skip until then. This range only contains a value. + nextToken(); + } + } + // Handle `if !consteval`. if (FormatTok->is(tok::exclaim)) nextToken(); @@ -3873,6 +3907,9 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { const FormatToken &InitialToken = *FormatTok; nextToken(); + auto IsNonMacroIdentifier = [](const FormatToken *Tok) { + return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper(); + }; // The actual identifier can be a nested name specifier, and in macros // it is often token-pasted. // An [[attribute]] can be before the identifier. @@ -3894,27 +3931,26 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { } if (FormatTok->is(tok::l_square) && handleCppAttributes()) continue; - bool IsNonMacroIdentifier = - FormatTok->is(tok::identifier) && - FormatTok->TokenText != FormatTok->TokenText.upper(); nextToken(); // We can have macros in between 'class' and the class name. - if (!IsNonMacroIdentifier && FormatTok->is(tok::l_paren)) + if (!IsNonMacroIdentifier(FormatTok->Previous) && + FormatTok->is(tok::l_paren)) { parseParens(); + } } - // Note that parsing away template declarations here leads to incorrectly - // accepting function declarations as record declarations. - // In general, we cannot solve this problem. Consider: - // class A<int> B() {} - // which can be a function definition or a class definition when B() is a - // macro. If we find enough real-world cases where this is a problem, we - // can parse for the 'template' keyword in the beginning of the statement, - // and thus rule out the record production in case there is no template - // (this would still leave us with an ambiguity between template function - // and class declarations). if (FormatTok->isOneOf(tok::colon, tok::less)) { + int AngleNestingLevel = 0; do { + if (FormatTok->is(tok::less)) + ++AngleNestingLevel; + else if (FormatTok->is(tok::greater)) + --AngleNestingLevel; + + if (AngleNestingLevel == 0 && FormatTok->is(tok::l_paren) && + IsNonMacroIdentifier(FormatTok->Previous)) { + break; + } if (FormatTok->is(tok::l_brace)) { calculateBraceTypes(/*ExpectClassBody=*/true); if (!tryToParseBracedList()) |