Skip to content

Commit 7a23a5d

Browse files
owencatru
authored andcommitted
[clang-format] Fix a bug in RemoveParentheses: ReturnStatement (#67911)
Don't remove the outermost parentheses surrounding a return statement expression when inside a function/lambda that has the decltype(auto) return type. Fixed #67892. (cherry picked from commit 75441a6)
1 parent be4016e commit 7a23a5d

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,12 @@ void UnwrappedLineParser::reset() {
173173
CommentsBeforeNextToken.clear();
174174
FormatTok = nullptr;
175175
MustBreakBeforeNextToken = false;
176+
IsDecltypeAutoFunction = false;
176177
PreprocessorDirectives.clear();
177178
CurrentLines = &Lines;
178179
DeclarationScopeStack.clear();
179180
NestedTooDeep.clear();
181+
NestedLambdas.clear();
180182
PPStack.clear();
181183
Line->FirstStartColumn = FirstStartColumn;
182184

@@ -1757,6 +1759,17 @@ void UnwrappedLineParser::parseStructuralElement(
17571759
if (parseStructLike())
17581760
return;
17591761
break;
1762+
case tok::kw_decltype:
1763+
nextToken();
1764+
if (FormatTok->is(tok::l_paren)) {
1765+
parseParens();
1766+
assert(FormatTok->Previous);
1767+
if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
1768+
tok::l_paren)) {
1769+
Line->SeenDecltypeAuto = true;
1770+
}
1771+
}
1772+
break;
17601773
case tok::period:
17611774
nextToken();
17621775
// In Java, classes have an implicit static member "class".
@@ -1818,6 +1831,7 @@ void UnwrappedLineParser::parseStructuralElement(
18181831
if (NextLBracesType != TT_Unknown)
18191832
FormatTok->setFinalizedType(NextLBracesType);
18201833
if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
1834+
IsDecltypeAutoFunction = Line->SeenDecltypeAuto;
18211835
// A block outside of parentheses must be the last part of a
18221836
// structural element.
18231837
// FIXME: Figure out cases where this is not true, and add projections
@@ -1835,6 +1849,7 @@ void UnwrappedLineParser::parseStructuralElement(
18351849
}
18361850
FormatTok->setFinalizedType(TT_FunctionLBrace);
18371851
parseBlock();
1852+
IsDecltypeAutoFunction = false;
18381853
addUnwrappedLine();
18391854
return;
18401855
}
@@ -2249,9 +2264,15 @@ bool UnwrappedLineParser::tryToParseLambda() {
22492264
return true;
22502265
}
22512266
}
2267+
22522268
FormatTok->setFinalizedType(TT_LambdaLBrace);
22532269
LSquare.setFinalizedType(TT_LambdaLSquare);
2270+
2271+
NestedLambdas.push_back(Line->SeenDecltypeAuto);
22542272
parseChildBlock();
2273+
assert(!NestedLambdas.empty());
2274+
NestedLambdas.pop_back();
2275+
22552276
return true;
22562277
}
22572278

@@ -2471,6 +2492,8 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
24712492
PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
24722493
const bool ReturnParens =
24732494
Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
2495+
((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2496+
(!NestedLambdas.empty() && !NestedLambdas.back())) &&
24742497
Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next &&
24752498
Next->is(tok::semi);
24762499
if ((DoubleParens && !Blacklisted) || ReturnParens) {
@@ -4386,6 +4409,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
43864409
Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
43874410
Line->FirstStartColumn = 0;
43884411
Line->IsContinuation = false;
4412+
Line->SeenDecltypeAuto = false;
43894413

43904414
if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
43914415
--Line->Level;

clang/lib/Format/UnwrappedLineParser.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ struct UnwrappedLine {
6161

6262
bool MustBeDeclaration;
6363

64+
/// Whether the parser has seen \c decltype(auto) in this line.
65+
bool SeenDecltypeAuto = false;
66+
6467
/// \c True if this line should be indented by ContinuationIndent in
6568
/// addition to the normal indention level.
6669
bool IsContinuation = false;
@@ -341,6 +344,14 @@ class UnwrappedLineParser {
341344
// statement contains more than some predefined number of nested statements).
342345
SmallVector<bool, 8> NestedTooDeep;
343346

347+
// Keeps a stack of the states of nested lambdas (true if the return type of
348+
// the lambda is `decltype(auto)`).
349+
SmallVector<bool, 4> NestedLambdas;
350+
351+
// Whether the parser is parsing the body of a function whose return type is
352+
// `decltype(auto)`.
353+
bool IsDecltypeAutoFunction = false;
354+
344355
// Represents preprocessor branch type, so we can find matching
345356
// #if/#else/#endif directives.
346357
enum PPBranchKind {

clang/unittests/Format/FormatTest.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26305,6 +26305,56 @@ TEST_F(FormatTest, RemoveParentheses) {
2630526305
verifyFormat("co_return 0;", "co_return ((0));", Style);
2630626306
verifyFormat("return 0;", "return (((0)));", Style);
2630726307
verifyFormat("return ({ 0; });", "return ((({ 0; })));", Style);
26308+
verifyFormat("inline decltype(auto) f() {\n"
26309+
" if (a) {\n"
26310+
" return (a);\n"
26311+
" }\n"
26312+
" return (b);\n"
26313+
"}",
26314+
"inline decltype(auto) f() {\n"
26315+
" if (a) {\n"
26316+
" return ((a));\n"
26317+
" }\n"
26318+
" return ((b));\n"
26319+
"}",
26320+
Style);
26321+
verifyFormat("auto g() {\n"
26322+
" decltype(auto) x = [] {\n"
26323+
" auto y = [] {\n"
26324+
" if (a) {\n"
26325+
" return a;\n"
26326+
" }\n"
26327+
" return b;\n"
26328+
" };\n"
26329+
" if (c) {\n"
26330+
" return (c);\n"
26331+
" }\n"
26332+
" return (d);\n"
26333+
" };\n"
26334+
" if (e) {\n"
26335+
" return e;\n"
26336+
" }\n"
26337+
" return f;\n"
26338+
"}",
26339+
"auto g() {\n"
26340+
" decltype(auto) x = [] {\n"
26341+
" auto y = [] {\n"
26342+
" if (a) {\n"
26343+
" return ((a));\n"
26344+
" }\n"
26345+
" return ((b));\n"
26346+
" };\n"
26347+
" if (c) {\n"
26348+
" return ((c));\n"
26349+
" }\n"
26350+
" return ((d));\n"
26351+
" };\n"
26352+
" if (e) {\n"
26353+
" return ((e));\n"
26354+
" }\n"
26355+
" return ((f));\n"
26356+
"}",
26357+
Style);
2630826358

2630926359
Style.ColumnLimit = 25;
2631026360
verifyFormat("return (a + b) - (c + d);",

0 commit comments

Comments
 (0)