Author: owenca Date: 2021-07-19T13:30:38-07:00 New Revision: 9da70ab3d43c79116f80fc06aa7cf517374ce42c
URL: https://github.com/llvm/llvm-project/commit/9da70ab3d43c79116f80fc06aa7cf517374ce42c DIFF: https://github.com/llvm/llvm-project/commit/9da70ab3d43c79116f80fc06aa7cf517374ce42c.diff LOG: [clang-format] Break an unwrapped line at a K&R C parameter decl Break an unwrapped line before the first parameter declaration in a K&R C function definition. This fixes PR51074. Differential Revision: https://reviews.llvm.org/D106112 Added: Modified: clang/lib/Format/UnwrappedLineParser.cpp clang/lib/Format/UnwrappedLineParser.h clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index f76cb4d341a22..103e3559b1208 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -431,7 +431,7 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) { } LLVM_FALLTHROUGH; default: - parseStructuralElement(); + parseStructuralElement(/*IsTopLevel=*/true); break; } } while (!eof()); @@ -994,6 +994,33 @@ static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords, Keywords.kw_import, tok::kw_export); } +// This function checks whether a token starts the first parameter declaration +// in a K&R C (aka C78) function definition, e.g.: +// int f(a, b) +// short a, b; +// { +// return a + b; +// } +static bool isC78ParameterDecl(const FormatToken *Tok) { + if (!Tok) + return false; + + if (!Tok->isOneOf(tok::kw_int, tok::kw_char, tok::kw_float, tok::kw_double, + tok::kw_struct, tok::kw_union, tok::kw_long, tok::kw_short, + tok::kw_unsigned, tok::kw_register, tok::identifier)) + return false; + + Tok = Tok->Previous; + if (!Tok || Tok->isNot(tok::r_paren)) + return false; + + Tok = Tok->Previous; + if (!Tok || Tok->isNot(tok::identifier)) + return false; + + return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma); +} + // readTokenWithJavaScriptASI reads the next token and terminates the current // line if JavaScript Automatic Semicolon Insertion must // happen between the current token and the next token. @@ -1041,7 +1068,7 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() { return addUnwrappedLine(); } -void UnwrappedLineParser::parseStructuralElement() { +void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) { assert(!FormatTok->is(tok::l_brace)); if (Style.Language == FormatStyle::LK_TableGen && FormatTok->is(tok::pp_include)) { @@ -1343,6 +1370,18 @@ void UnwrappedLineParser::parseStructuralElement() { return; case tok::l_paren: parseParens(); + // Break the unwrapped line if a K&R C function definition has a parameter + // declaration. + if (!IsTopLevel || !Style.isCpp()) + break; + if (!Previous || Previous->isNot(tok::identifier)) + break; + if (Previous->Previous && Previous->Previous->is(tok::at)) + break; + if (isC78ParameterDecl(FormatTok)) { + addUnwrappedLine(); + return; + } break; case tok::kw_operator: nextToken(); diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index a5a82b5ab058c..f22bb6323e3d7 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -97,7 +97,7 @@ class UnwrappedLineParser { void parsePPEndIf(); void parsePPUnknown(); void readTokenWithJavaScriptASI(); - void parseStructuralElement(); + void parseStructuralElement(bool IsTopLevel = false); bool tryToParseBracedList(); bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false, tok::TokenKind ClosingBraceKind = tok::r_brace); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index eed3ea4cdbe37..3adf42d34cf13 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -8216,7 +8216,16 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) { "f(i)\n" "{\n" " return i + 1;\n" - "}\n", + "}", + Style); + verifyFormat("int f(a, b, c);\n" // No break here. + "int\n" // Break here. + "f(a, b, c)\n" // Break here. + "short a, b;\n" + "float c;\n" + "{\n" + " return a + b < c;\n" + "}", Style); Style = getGNUStyle(); @@ -9423,7 +9432,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("vector<A(uint64_t) * attr> v;", TypeMacros); // multiplication FormatStyle CustomQualifier = getLLVMStyle(); - // Add indentifers that should not be parsed as a qualifier by default. + // Add identifiers that should not be parsed as a qualifier by default. CustomQualifier.AttributeMacros.push_back("__my_qualifier"); CustomQualifier.AttributeMacros.push_back("_My_qualifier"); CustomQualifier.AttributeMacros.push_back("my_other_qualifier"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits