Skip to content

Commit f7a4e3a

Browse files
owencatstellar
authored andcommitted
[clang-format] Don't remove parentheses separated from ellipsis by comma (llvm#130471)
Also clean up `case tok::r_paren` in `UnwrappedLineParser::parseParens()`. Fix llvm#130359 (cherry picked from commit 7d4d850)
1 parent 1d4d84c commit f7a4e3a

File tree

2 files changed

+55
-35
lines changed

2 files changed

+55
-35
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2562,12 +2562,12 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
25622562
/// Returns whether there is a `=` token between the parentheses.
25632563
bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
25642564
assert(FormatTok->is(tok::l_paren) && "'(' expected.");
2565-
auto *LeftParen = FormatTok;
2565+
auto *LParen = FormatTok;
25662566
bool SeenComma = false;
25672567
bool SeenEqual = false;
25682568
bool MightBeFoldExpr = false;
2569-
const bool MightBeStmtExpr = Tokens->peekNextToken()->is(tok::l_brace);
25702569
nextToken();
2570+
const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
25712571
do {
25722572
switch (FormatTok->Tok.getKind()) {
25732573
case tok::l_paren:
@@ -2577,44 +2577,60 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
25772577
parseChildBlock();
25782578
break;
25792579
case tok::r_paren: {
2580-
auto *Prev = LeftParen->Previous;
2581-
if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody &&
2582-
Style.RemoveParentheses > FormatStyle::RPS_Leave) {
2583-
const auto *Next = Tokens->peekNextToken();
2584-
const bool DoubleParens =
2585-
Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren);
2586-
const bool CommaSeparated =
2587-
!DoubleParens && Prev && Prev->isOneOf(tok::l_paren, tok::comma) &&
2588-
Next && Next->isOneOf(tok::comma, tok::r_paren);
2589-
const auto *PrevPrev = Prev ? Prev->getPreviousNonComment() : nullptr;
2590-
const bool Excluded =
2591-
PrevPrev &&
2592-
(PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2593-
SeenComma ||
2594-
(SeenEqual &&
2595-
(PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2596-
PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2597-
const bool ReturnParens =
2598-
Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
2599-
((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2600-
(!NestedLambdas.empty() && !NestedLambdas.back())) &&
2601-
Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next &&
2602-
Next->is(tok::semi);
2603-
if ((DoubleParens && !Excluded) || (CommaSeparated && !SeenComma) ||
2604-
ReturnParens) {
2605-
LeftParen->Optional = true;
2606-
FormatTok->Optional = true;
2607-
}
2608-
}
2580+
auto *Prev = LParen->Previous;
2581+
auto *RParen = FormatTok;
2582+
nextToken();
26092583
if (Prev) {
2584+
auto OptionalParens = [&] {
2585+
if (MightBeStmtExpr || MightBeFoldExpr || Line->InMacroBody ||
2586+
SeenComma || Style.RemoveParentheses == FormatStyle::RPS_Leave) {
2587+
return false;
2588+
}
2589+
const bool DoubleParens =
2590+
Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);
2591+
if (DoubleParens) {
2592+
const auto *PrevPrev = Prev->getPreviousNonComment();
2593+
const bool Excluded =
2594+
PrevPrev &&
2595+
(PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
2596+
(SeenEqual &&
2597+
(PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
2598+
PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
2599+
if (!Excluded)
2600+
return true;
2601+
} else {
2602+
const bool CommaSeparated =
2603+
Prev->isOneOf(tok::l_paren, tok::comma) &&
2604+
FormatTok->isOneOf(tok::comma, tok::r_paren);
2605+
if (CommaSeparated &&
2606+
// LParen is not preceded by ellipsis, comma.
2607+
!Prev->endsSequence(tok::comma, tok::ellipsis) &&
2608+
// RParen is not followed by comma, ellipsis.
2609+
!(FormatTok->is(tok::comma) &&
2610+
Tokens->peekNextToken()->is(tok::ellipsis))) {
2611+
return true;
2612+
}
2613+
const bool ReturnParens =
2614+
Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
2615+
((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2616+
(!NestedLambdas.empty() && !NestedLambdas.back())) &&
2617+
Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
2618+
FormatTok->is(tok::semi);
2619+
if (ReturnParens)
2620+
return true;
2621+
}
2622+
return false;
2623+
};
26102624
if (Prev->is(TT_TypenameMacro)) {
2611-
LeftParen->setFinalizedType(TT_TypeDeclarationParen);
2612-
FormatTok->setFinalizedType(TT_TypeDeclarationParen);
2613-
} else if (Prev->is(tok::greater) && FormatTok->Previous == LeftParen) {
2625+
LParen->setFinalizedType(TT_TypeDeclarationParen);
2626+
RParen->setFinalizedType(TT_TypeDeclarationParen);
2627+
} else if (Prev->is(tok::greater) && RParen->Previous == LParen) {
26142628
Prev->setFinalizedType(TT_TemplateCloser);
2629+
} else if (OptionalParens()) {
2630+
LParen->Optional = true;
2631+
RParen->Optional = true;
26152632
}
26162633
}
2617-
nextToken();
26182634
return SeenEqual;
26192635
}
26202636
case tok::r_brace:

clang/unittests/Format/FormatTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27881,6 +27881,10 @@ TEST_F(FormatTest, RemoveParentheses) {
2788127881
verifyFormat("foo((a, b));", "foo(((a), b));", Style);
2788227882
verifyFormat("foo((a, b));", "foo((a, (b)));", Style);
2788327883
verifyFormat("foo((a, b, c));", "foo((a, ((b)), c));", Style);
27884+
verifyFormat("(..., (hash_a = hash_combine(hash_a, hash_b)));",
27885+
"(..., ((hash_a = hash_combine(hash_a, hash_b))));", Style);
27886+
verifyFormat("((hash_a = hash_combine(hash_a, hash_b)), ...);",
27887+
"(((hash_a = hash_combine(hash_a, hash_b))), ...);", Style);
2788427888
verifyFormat("return (0);", "return (((0)));", Style);
2788527889
verifyFormat("return (({ 0; }));", "return ((({ 0; })));", Style);
2788627890
verifyFormat("return ((... && std::is_convertible_v<TArgsLocal, TArgs>));",

0 commit comments

Comments
 (0)