Skip to content

Commit 9da70ab

Browse files
committed
[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
1 parent 87039c0 commit 9da70ab

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
431431
}
432432
LLVM_FALLTHROUGH;
433433
default:
434-
parseStructuralElement();
434+
parseStructuralElement(/*IsTopLevel=*/true);
435435
break;
436436
}
437437
} while (!eof());
@@ -994,6 +994,33 @@ static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,
994994
Keywords.kw_import, tok::kw_export);
995995
}
996996

997+
// This function checks whether a token starts the first parameter declaration
998+
// in a K&R C (aka C78) function definition, e.g.:
999+
// int f(a, b)
1000+
// short a, b;
1001+
// {
1002+
// return a + b;
1003+
// }
1004+
static bool isC78ParameterDecl(const FormatToken *Tok) {
1005+
if (!Tok)
1006+
return false;
1007+
1008+
if (!Tok->isOneOf(tok::kw_int, tok::kw_char, tok::kw_float, tok::kw_double,
1009+
tok::kw_struct, tok::kw_union, tok::kw_long, tok::kw_short,
1010+
tok::kw_unsigned, tok::kw_register, tok::identifier))
1011+
return false;
1012+
1013+
Tok = Tok->Previous;
1014+
if (!Tok || Tok->isNot(tok::r_paren))
1015+
return false;
1016+
1017+
Tok = Tok->Previous;
1018+
if (!Tok || Tok->isNot(tok::identifier))
1019+
return false;
1020+
1021+
return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);
1022+
}
1023+
9971024
// readTokenWithJavaScriptASI reads the next token and terminates the current
9981025
// line if JavaScript Automatic Semicolon Insertion must
9991026
// happen between the current token and the next token.
@@ -1041,7 +1068,7 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() {
10411068
return addUnwrappedLine();
10421069
}
10431070

1044-
void UnwrappedLineParser::parseStructuralElement() {
1071+
void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
10451072
assert(!FormatTok->is(tok::l_brace));
10461073
if (Style.Language == FormatStyle::LK_TableGen &&
10471074
FormatTok->is(tok::pp_include)) {
@@ -1343,6 +1370,18 @@ void UnwrappedLineParser::parseStructuralElement() {
13431370
return;
13441371
case tok::l_paren:
13451372
parseParens();
1373+
// Break the unwrapped line if a K&R C function definition has a parameter
1374+
// declaration.
1375+
if (!IsTopLevel || !Style.isCpp())
1376+
break;
1377+
if (!Previous || Previous->isNot(tok::identifier))
1378+
break;
1379+
if (Previous->Previous && Previous->Previous->is(tok::at))
1380+
break;
1381+
if (isC78ParameterDecl(FormatTok)) {
1382+
addUnwrappedLine();
1383+
return;
1384+
}
13461385
break;
13471386
case tok::kw_operator:
13481387
nextToken();

clang/lib/Format/UnwrappedLineParser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class UnwrappedLineParser {
9797
void parsePPEndIf();
9898
void parsePPUnknown();
9999
void readTokenWithJavaScriptASI();
100-
void parseStructuralElement();
100+
void parseStructuralElement(bool IsTopLevel = false);
101101
bool tryToParseBracedList();
102102
bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false,
103103
tok::TokenKind ClosingBraceKind = tok::r_brace);

clang/unittests/Format/FormatTest.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8216,7 +8216,16 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) {
82168216
"f(i)\n"
82178217
"{\n"
82188218
" return i + 1;\n"
8219-
"}\n",
8219+
"}",
8220+
Style);
8221+
verifyFormat("int f(a, b, c);\n" // No break here.
8222+
"int\n" // Break here.
8223+
"f(a, b, c)\n" // Break here.
8224+
"short a, b;\n"
8225+
"float c;\n"
8226+
"{\n"
8227+
" return a + b < c;\n"
8228+
"}",
82208229
Style);
82218230

82228231
Style = getGNUStyle();
@@ -9423,7 +9432,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
94239432
verifyFormat("vector<A(uint64_t) * attr> v;", TypeMacros); // multiplication
94249433

94259434
FormatStyle CustomQualifier = getLLVMStyle();
9426-
// Add indentifers that should not be parsed as a qualifier by default.
9435+
// Add identifiers that should not be parsed as a qualifier by default.
94279436
CustomQualifier.AttributeMacros.push_back("__my_qualifier");
94289437
CustomQualifier.AttributeMacros.push_back("_My_qualifier");
94299438
CustomQualifier.AttributeMacros.push_back("my_other_qualifier");

0 commit comments

Comments
 (0)