Skip to content

Commit eda5a4a

Browse files
committed
Always make a copy when constructing mutable struct literals
1 parent 9decd49 commit eda5a4a

3 files changed

Lines changed: 79 additions & 20 deletions

File tree

compiler/src/dmd/expressionsem.d

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -808,8 +808,7 @@ bool canElideCopy(Expression e, Type to, bool checkMod = true)
808808
case EXP.dotVariable:
809809
return visitDotVarExp(e.isDotVarExp());
810810
case EXP.structLiteral:
811-
auto sle = e.isStructLiteralExp();
812-
return !(checkMod && sle.useStaticInit && to.isMutable());
811+
return true;
813812
case EXP.variable:
814813
return (e.isVarExp().var.storage_class & STC.rvalue) != 0;
815814
default:

compiler/src/dmd/glue/e2ir.d

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,14 @@ elem* addressElem(elem* e, Type t, bool alwaysCopy = false)
465465
return e;
466466
}
467467

468-
if (alwaysCopy || ((*pe).Eoper != OPvar && (*pe).Eoper != OPind))
468+
static bool hasAddress(elem* e)
469+
{
470+
if (e.Eoper == OPeq || e.Eoper == OPstreq)
471+
e = e.E1;
472+
return e.Eoper == OPvar || e.Eoper == OPind;
473+
}
474+
475+
if (alwaysCopy || !hasAddress(*pe))
469476
{
470477
elem* e2 = *pe;
471478
type* tx;
@@ -6737,36 +6744,37 @@ elem* toElemStructLit(StructLiteralExp sle, ref IRState irs, EXP op, Symbol* sym
67376744
return ep;
67386745
}
67396746

6747+
elem* e;
6748+
// struct symbol to initialize with the literal
6749+
Symbol* stmp = sym;
6750+
67406751
if (sle.useStaticInit)
67416752
{
67426753
/* Use the struct declaration's init symbol
67436754
*/
6744-
elem* e = el_var(toInitializer(sle.sd));
6755+
e = el_var(toInitializer(sle.sd));
67456756
e.ET = Type_toCtype(sle.sd.type);
67466757
elem_setLoc(e, sle.loc);
67476758

6748-
if (sym)
6759+
if (!stmp && sle.type.isMutable())
6760+
stmp = symbol_genauto(Type_toCtype(sle.sd.type));
6761+
6762+
if (stmp)
67496763
{
6750-
elem* ev = el_var(sym);
6764+
elem* ev = el_var(stmp);
67516765
if (tybasic(ev.Ety) == TYnptr)
67526766
ev = el_una(OPind, e.Ety, ev);
67536767
ev.ET = e.ET;
67546768
e = elAssign(ev, e, null, ev.ET);
6755-
6756-
//ev = el_var(sym);
6757-
//ev.ET = e.ET;
6758-
//e = el_combine(e, ev);
67596769
elem_setLoc(e, sle.loc);
67606770
}
67616771
if (forcetype)
67626772
return Lreinterpret(sle.loc, e, forcetype);
67636773
return e;
67646774
}
67656775

6766-
// struct symbol to initialize with the literal
6767-
Symbol* stmp = sym ? sym : symbol_genauto(Type_toCtype(sle.sd.type));
6768-
6769-
elem* e = null;
6776+
if (!stmp)
6777+
stmp = symbol_genauto(Type_toCtype(sle.sd.type));
67706778

67716779
/* If a field has explicit initializer (*sle.elements)[i] != null),
67726780
* any other overlapped fields won't have initializer. It's asserted by
Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,67 @@
1-
void refCounted(ProcessPipes val)
1+
struct S22585_1
22
{
3-
val = ProcessPipes.init;
3+
char[32] a;
4+
int b = 1;
5+
6+
this(ref S22585_1 s)
7+
{
8+
s.b = 2;
9+
}
10+
}
11+
12+
struct T22585_1
13+
{
14+
S22585_1 s;
15+
}
16+
17+
void copyConstruct(S22585_1) {}
18+
19+
void mutate(ref S22585_1 s)
20+
{
21+
s.b = 2;
22+
}
23+
24+
struct S22585_2
25+
{
26+
char[32] a;
27+
int b = 1;
28+
~this() {}
29+
}
30+
31+
struct T22585_2
32+
{
33+
S22585_2 s;
34+
}
35+
36+
pragma(inline, true)
37+
S22585_2 inlinedRvalue1()
38+
{
39+
bool b;
40+
return (b ? T22585_2.init : T22585_2.init).s;
41+
}
42+
43+
void mutateCopyOf(S22585_2 s)
44+
{
45+
s.b = 2;
46+
}
47+
48+
pragma(inline, true)
49+
S22585_2 inlinedRvalue2()
50+
{
51+
return S22585_2.init;
452
}
553

6-
struct ProcessPipes
54+
void assignCopyOf(S22585_2 s)
755
{
8-
char[33] arr;
9-
~this() @safe {}
56+
s = S22585_2.init;
1057
}
1158

1259
void main()
1360
{
14-
refCounted(ProcessPipes.init);
61+
bool b;
62+
copyConstruct((b ? T22585_1.init : T22585_1.init).s);
63+
mutate((b ? T22585_1.init : T22585_1.init).s);
64+
mutateCopyOf(inlinedRvalue1());
65+
inlinedRvalue2.b = 2;
66+
assignCopyOf(S22585_2.init);
1567
}

0 commit comments

Comments
 (0)