Skip to content

Commit b7b19d6

Browse files
committed
Fix dlang#22639 - opApply triggers GC allocation error with -betterC
1 parent 97b0d1b commit b7b19d6

2 files changed

Lines changed: 49 additions & 1 deletion

File tree

compiler/src/dmd/semantic3.d

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,20 @@ private extern(C++) final class Semantic3Visitor : Visitor
975975

976976
if (funcdecl.vresult)
977977
{
978-
Scope* scret = rs.fesFunc ? rs.fesFunc._scope : sc2;
978+
Scope* scret = sc2;
979+
980+
if (rs.fesFunc)
981+
{
982+
// Create a scope with foreach body being `.parent`
983+
// and `funcdecl` as `.func`. So the return value
984+
// is aware of closure access, but picks up
985+
// attributes and instantiates templated copy/move
986+
// ctors in the context of `funcdecl`.
987+
// BUG: remove this fragile hack
988+
scret = rs.fesFunc._scope.push();
989+
scret.parent = rs.fesFunc;
990+
scret.func = funcdecl;
991+
}
979992

980993
// Create: return (vresult = exp, vresult);
981994
exp = new ConstructExp(rs.loc, funcdecl.vresult, exp);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// REQUIRED_ARGS: -betterC
2+
3+
struct Arr(T, int CAPACITY)
4+
{
5+
int count = 0;
6+
T[CAPACITY] items;
7+
int opApply(scope int delegate(T) dg)
8+
{
9+
int result;
10+
for (int i = 0; i < count; i++)
11+
if ((result = dg(items[i])) != 0)
12+
break;
13+
return result;
14+
}
15+
}
16+
17+
struct Foo {}
18+
struct Bar {
19+
Arr!(Foo*, 32) array;
20+
Foo* get()
21+
{
22+
foreach(Foo* it; array)
23+
{
24+
return it;
25+
}
26+
return null;
27+
}
28+
}
29+
30+
Foo* foo;
31+
Bar bar;
32+
extern(C) void main()
33+
{
34+
foo = bar.get();
35+
}

0 commit comments

Comments
 (0)