Skip to content

Commit 0fc83d3

Browse files
committed
fix Issue 21821 - Optimizer assumes immutables do not change, but they can in @System code
1 parent a0faedf commit 0fc83d3

6 files changed

Lines changed: 49 additions & 5 deletions

File tree

compiler/src/dmd/backend/cc.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ enum
756756
Fnothrow = 0x10000, // function does not throw (even if not marked 'nothrow')
757757
Feh_none = 0x20000, // ehmethod==EH_NONE for this function only
758758
F3hiddenPtr = 0x40000, // function has hidden pointer to return value
759+
F3safe = 0x80000, // function is @safe
759760
}
760761

761762
struct func_t

compiler/src/dmd/backend/gdag.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ private void aewalk(elem **pn,vec_t ae)
332332
{
333333
assert(t.Eoper == OPvar);
334334
Symbol* s = t.EV.Vsym;
335-
if (!(s.Sflags & SFLunambig))
335+
if (Symbol_isAffected(*s))
336336
vec_subass(ae,go.starkill);
337337
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
338338
{
@@ -821,7 +821,7 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
821821

822822
assert(t.Eoper == OPvar);
823823
s = t.EV.Vsym;
824-
if (!(s.Sflags & SFLunambig))
824+
if (Symbol_isAffected(*s))
825825
vec_subass(ae,go.starkill);
826826
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
827827
{

compiler/src/dmd/backend/gother.d

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,18 +1255,19 @@ private bool copyPropWalk(elem *n,vec_t IN)
12551255
v = go.expnod[i].EV.E1.EV.Vsym;
12561256
if (ambig)
12571257
{
1258-
if (!(v.Sflags & SFLunambig))
1258+
if (Symbol_isAffected(*v))
12591259
goto clr;
12601260
}
12611261
else
12621262
{
12631263
if (v == t.EV.Vsym)
12641264
goto clr;
12651265
}
1266+
12661267
v = go.expnod[i].EV.E2.EV.Vsym;
12671268
if (ambig)
12681269
{
1269-
if (!(v.Sflags & SFLunambig))
1270+
if (Symbol_isAffected(*v))
12701271
goto clr;
12711272
}
12721273
else

compiler/src/dmd/backend/symbol.d

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,14 @@ bool Symbol_isAffected(const ref Symbol s)
276276
if (0 &&
277277
s.ty() & (mTYconst | mTYimmutable))
278278
{
279-
return false;
279+
/* Disabled for the moment because even @safe functions
280+
* may have inlined unsafe code from other functions
281+
*/
282+
if (funcsym_p.Sfunc.Fflags3 & F3safe &&
283+
s.ty() & mTYimmutable)
284+
{
285+
return false;
286+
}
280287
}
281288
return true;
282289
}

compiler/src/dmd/tocsym.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ Symbol *toSymbol(Dsymbol s)
353353
else if (fd.isMember2() && fd.isStatic())
354354
f.Fflags |= Fstatic;
355355

356+
if (fd.isSafe())
357+
f.Fflags3 |= F3safe;
358+
356359
if (fd.inlining == PINLINE.default_ && global.params.useInline ||
357360
fd.inlining == PINLINE.always)
358361
{

test/runnable/test21821.d

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// REQUIRED_ARGS: -preview=fieldwise -O
2+
// https://issues.dlang.org/show_bug.cgi?id=21821
3+
4+
// test case comes from unittests in core.lifetime
5+
6+
void test()
7+
{
8+
alias T = immutable(S);
9+
T source;
10+
T target;
11+
copyEmplacex(source, target);
12+
T expectedCopy = source;
13+
assert(target == expectedCopy);
14+
}
15+
16+
struct S
17+
{
18+
int x = 42;
19+
this(this) { x += 10; }
20+
}
21+
22+
void copyEmplacex(ref immutable(S) source, ref immutable(S) target) @system
23+
{
24+
import core.stdc.string : memcpy;
25+
memcpy(cast(S*) &target, cast(S*) &source, S.sizeof);
26+
(cast() target).__xpostblit(); // casting away immutable
27+
}
28+
29+
void main()
30+
{
31+
test();
32+
}

0 commit comments

Comments
 (0)