Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix Issue 21821 - Optimizer assumes immutables do not change, but the… #12424

Merged
merged 1 commit into from Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/src/dmd/backend/cc.d
Expand Up @@ -749,6 +749,7 @@ enum
Fnothrow = 0x10000, // function does not throw (even if not marked 'nothrow')
Feh_none = 0x20000, // ehmethod==EH_NONE for this function only
F3hiddenPtr = 0x40000, // function has hidden pointer to return value
F3safe = 0x80000, // function is @safe
}

struct func_t
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dmd/backend/gdag.d
Expand Up @@ -332,7 +332,7 @@ private void aewalk(elem **pn,vec_t ae)
{
assert(t.Eoper == OPvar);
Symbol* s = t.EV.Vsym;
if (!(s.Sflags & SFLunambig))
if (Symbol_isAffected(*s))
vec_subass(ae,go.starkill);
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
{
Expand Down Expand Up @@ -821,7 +821,7 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)

assert(t.Eoper == OPvar);
s = t.EV.Vsym;
if (!(s.Sflags & SFLunambig))
if (Symbol_isAffected(*s))
vec_subass(ae,go.starkill);
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
{
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dmd/backend/gother.d
Expand Up @@ -1255,18 +1255,19 @@ private bool copyPropWalk(elem *n,vec_t IN)
v = go.expnod[i].EV.E1.EV.Vsym;
if (ambig)
{
if (!(v.Sflags & SFLunambig))
if (Symbol_isAffected(*v))
goto clr;
}
else
{
if (v == t.EV.Vsym)
goto clr;
}

v = go.expnod[i].EV.E2.EV.Vsym;
if (ambig)
{
if (!(v.Sflags & SFLunambig))
if (Symbol_isAffected(*v))
goto clr;
}
else
Expand Down
13 changes: 10 additions & 3 deletions compiler/src/dmd/backend/symbol.d
Expand Up @@ -279,10 +279,17 @@ bool Symbol_isAffected(const ref Symbol s)
* 4. Const can be mutated by a separate view.
* Address this in a separate PR.
*/
if (0 &&
s.ty() & (mTYconst | mTYimmutable))
static if (0)
if (s.ty() & (mTYconst | mTYimmutable))
{
return false;
/* Disabled for the moment because even @safe functions
* may have inlined unsafe code from other functions
*/
if (funcsym_p.Sfunc.Fflags3 & F3safe &&
s.ty() & mTYimmutable)
{
return false;
}
}
return true;
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dmd/tocsym.d
Expand Up @@ -356,6 +356,9 @@ Symbol *toSymbol(Dsymbol s)
else if (fd.isMember2() && fd.isStatic())
f.Fflags |= Fstatic;

if (fd.isSafe())
f.Fflags3 |= F3safe;

if (fd.inlining == PINLINE.default_ && global.params.useInline ||
fd.inlining == PINLINE.always)
{
Expand Down
32 changes: 32 additions & 0 deletions test/runnable/test21821.d
@@ -0,0 +1,32 @@
// REQUIRED_ARGS: -preview=fieldwise -O
// https://issues.dlang.org/show_bug.cgi?id=21821

// test case comes from unittests in core.lifetime

void test()
{
alias T = immutable(S);
T source;
T target;
copyEmplacex(source, target);
T expectedCopy = source;
assert(target == expectedCopy);
}

struct S
{
int x = 42;
this(this) { x += 10; }
}

void copyEmplacex(ref immutable(S) source, ref immutable(S) target) @system
{
import core.stdc.string : memcpy;
memcpy(cast(S*) &target, cast(S*) &source, S.sizeof);
(cast() target).__xpostblit(); // casting away immutable
}

void main()
{
test();
}