Skip to content

Commit 5b7dc52

Browse files
committed
Do semantic under nested scope when returning inside foreach body
1 parent b1faf12 commit 5b7dc52

8 files changed

Lines changed: 66 additions & 3 deletions

File tree

compiler/src/dmd/frontend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5179,6 +5179,7 @@ class ReturnStatement final : public Statement
51795179
public:
51805180
Expression* exp;
51815181
size_t caseDim;
5182+
FuncDeclaration* fesFunc;
51825183
ReturnStatement* syntaxCopy() override;
51835184
ReturnStatement* endsWithReturnStatement() override;
51845185
void accept(Visitor* v) override;

compiler/src/dmd/funcsem.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2780,7 +2780,7 @@ void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret)
27802780
if (sc && fd.vresult.semanticRun == PASS.initial)
27812781
{
27822782
TypeFunction tf = fd.type.toTypeFunction();
2783-
if (tf.isRef)
2783+
if (fd.isNRVO || tf.isRef)
27842784
fd.vresult.storage_class |= STC.ref_;
27852785
else if (target.isReturnOnStack(tf, fd.needThis()))
27862786
fd.vresult.nrvo = true;

compiler/src/dmd/semantic3.d

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -975,11 +975,12 @@ private extern(C++) final class Semantic3Visitor : Visitor
975975

976976
if (funcdecl.vresult)
977977
{
978+
Scope* scret = rs.fesFunc ? rs.fesFunc._scope : sc2;
979+
978980
// Create: return (vresult = exp, vresult);
979981
exp = new ConstructExp(rs.loc, funcdecl.vresult, exp);
980-
exp.type = funcdecl.vresult.type;
982+
exp = exp.expressionSemantic(scret);
981983
exp = Expression.combine(exp, new VarExp(rs.loc, funcdecl.vresult));
982-
exp = exp.expressionSemantic(sc2);
983984

984985
if (rs.caseDim)
985986
exp = Expression.combine(exp, new IntegerExp(rs.caseDim));

compiler/src/dmd/statement.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,7 @@ extern (C++) final class ReturnStatement : Statement
13081308
{
13091309
Expression exp;
13101310
size_t caseDim;
1311+
FuncDeclaration fesFunc; // nested function for foreach it is in
13111312

13121313
extern (D) this(Loc loc, Expression exp) @safe
13131314
{

compiler/src/dmd/statement.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ class ReturnStatement final : public Statement
518518
public:
519519
Expression *exp;
520520
size_t caseDim;
521+
FuncDeclaration *fesFunc; // nested function for foreach it is in
521522

522523
ReturnStatement *syntaxCopy() override;
523524

compiler/src/dmd/statementsem.d

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,8 +2481,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
24812481
//printf("ReturnStatement.dsymbolSemantic() %s\n", toChars(rs));
24822482

24832483
FuncDeclaration fd = sc.parent.isFuncDeclaration();
2484+
24842485
if (fd.fes)
2486+
{
2487+
rs.fesFunc = fd;
24852488
fd = fd.fes.func; // fd is now function enclosing foreach
2489+
}
24862490

24872491
auto tf = fd.type.isTypeFunction();
24882492

compiler/test/runnable/foreach5.d

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,36 @@ void testLDC326()
12081208
}
12091209
}
12101210

1211+
/***************************************/
1212+
// https://github.com/dlang/dmd/issues/22629
1213+
1214+
struct Collection2
1215+
{
1216+
this(ref Collection2) {}
1217+
1218+
int opApply(int delegate(Collection2))
1219+
{
1220+
return 0;
1221+
}
1222+
}
1223+
1224+
Collection2 testForeach2(ref Collection2 level1, ref Collection2 level2)
1225+
{
1226+
foreach (first; level1) {
1227+
foreach (second; level2)
1228+
return second;
1229+
}
1230+
1231+
return Collection2();
1232+
}
1233+
1234+
void test22629()
1235+
{
1236+
Collection2 c1, c2;
1237+
testForeach2(c1, c2);
1238+
}
1239+
1240+
12111241
/***************************************/
12121242

12131243
int main()
@@ -1241,6 +1271,7 @@ int main()
12411271
test14653();
12421272
test17041();
12431273
testLDC326();
1274+
test22629();
12441275

12451276
printf("Success\n");
12461277
return 0;

compiler/test/runnable/rvalue1.d

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,17 +286,41 @@ struct V12
286286
{
287287
S12 s;
288288
this(int) { s = S12(1); }
289+
int opApply(int delegate(Object)) { return 0; }
289290
}
290291

291292
S12 foo12()
292293
{
293294
return __rvalue(V12(1).s);
294295
}
295296

297+
S12 bar12()
298+
{
299+
S12 s = S12(1); // NRVO
300+
foreach (_; V12(1))
301+
return s;
302+
return s;
303+
}
304+
305+
S12 baz12()
306+
{
307+
S12 s1 = S12(1);
308+
S12 s2 = S12(1); // No NRVO
309+
foreach (_; V12(1))
310+
return s1;
311+
return s2;
312+
}
313+
296314
void test12()
297315
{
298316
S12 s = foo12();
299317
assert(&s == s.ptr);
318+
319+
S12 s2 = bar12();
320+
assert(&s2 == s2.ptr);
321+
322+
S12 s3 = baz12();
323+
assert(&s3 == s3.ptr);
300324
}
301325

302326
/********************************/

0 commit comments

Comments
 (0)