Skip to content

Commit a8f9492

Browse files
owencaharviniriawan
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.
1 parent bfeb8ad commit a8f9492

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

@@ -1766,6 +1768,17 @@ void UnwrappedLineParser::parseStructuralElement(
17661768
if (parseStructLike())
17671769
return;
17681770
break;
1771+
case tok::kw_decltype:
1772+
nextToken();
1773+
if (FormatTok->is(tok::l_paren)) {
1774+
parseParens();
1775+
assert(FormatTok->Previous);
1776+
if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
1777+
tok::l_paren)) {
1778+
Line->SeenDecltypeAuto = true;
1779+
}
1780+
}
1781+
break;
17691782
case tok::period:
17701783
nextToken();
17711784
// In Java, classes have an implicit static member "class".
@@ -1827,6 +1840,7 @@ void UnwrappedLineParser::parseStructuralElement(
18271840
if (InRequiresExpression)
18281841
FormatTok->setFinalizedType(TT_BracedListLBrace);
18291842
if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
1843+
IsDecltypeAutoFunction = Line->SeenDecltypeAuto;
18301844
// A block outside of parentheses must be the last part of a
18311845
// structural element.
18321846
// FIXME: Figure out cases where this is not true, and add projections
@@ -1844,6 +1858,7 @@ void UnwrappedLineParser::parseStructuralElement(
18441858
}
18451859
FormatTok->setFinalizedType(TT_FunctionLBrace);
18461860
parseBlock();
1861+
IsDecltypeAutoFunction = false;
18471862
addUnwrappedLine();
18481863
return;
18491864
}
@@ -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

@@ -2469,6 +2490,8 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
24692490
PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
24702491
const bool ReturnParens =
24712492
Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
2493+
((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
2494+
(!NestedLambdas.empty() && !NestedLambdas.back())) &&
24722495
Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next &&
24732496
Next->is(tok::semi);
24742497
if ((DoubleParens && !Blacklisted) || ReturnParens) {
@@ -4379,6 +4402,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
43794402
Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
43804403
Line->FirstStartColumn = 0;
43814404
Line->IsContinuation = false;
4405+
Line->SeenDecltypeAuto = false;
43824406

43834407
if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
43844408
--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 = false;
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;
@@ -335,6 +338,14 @@ class UnwrappedLineParser {
335338
// statement contains more than some predefined number of nested statements).
336339
SmallVector<bool, 8> NestedTooDeep;
337340

341+
// Keeps a stack of the states of nested lambdas (true if the return type of
342+
// the lambda is `decltype(auto)`).
343+
SmallVector<bool, 4> NestedLambdas;
344+
345+
// Whether the parser is parsing the body of a function whose return type is
346+
// `decltype(auto)`.
347+
bool IsDecltypeAutoFunction = false;
348+
338349
// Represents preprocessor branch type, so we can find matching
339350
// #if/#else/#endif directives.
340351
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)