diff --git a/src/e2ir.c b/src/e2ir.c index 4a873c9e329b..045bd108bce3 100644 --- a/src/e2ir.c +++ b/src/e2ir.c @@ -2460,7 +2460,7 @@ elem *toElem(Expression *e, IRState *irs) Type *ta = are->e1->type->toBasetype(); // which we do if the 'next' types match - if (ae->ismemset) + if (ae->ismemset & 1) { // Do a memset for array[]=v //printf("Lpair %s\n", ae->toChars()); @@ -2649,7 +2649,7 @@ elem *toElem(Expression *e, IRState *irs) /* Look for reference initializations */ - if (ae->op == TOKconstruct && ae->e1->op == TOKvar) + if (ae->op == TOKconstruct && ae->e1->op == TOKvar && !(ae->ismemset & 2)) { VarExp *ve = (VarExp *)ae->e1; Declaration *s = ve->var; diff --git a/src/expression.c b/src/expression.c index 33cf9e3d88f6..3b46c0a16106 100644 --- a/src/expression.c +++ b/src/expression.c @@ -11205,6 +11205,13 @@ Expression *AssignExp::semantic(Scope *sc) { //printf("[%s] change to init - %s\n", loc.toChars(), toChars()); op = TOKconstruct; + if (e1->op == TOKvar && + ((VarExp *)e1)->var->storage_class & (STCout | STCref)) + { + // Bugzilla 14944, even if e1 is a ref variable, + // make an initialization of referenced memory. + ismemset |= 2; + } // Bugzilla 13515: set Index::modifiable flag for complex AA element initialization if (e1->op == TOKindex) @@ -11219,7 +11226,7 @@ Expression *AssignExp::semantic(Scope *sc) * check for operator overloading. */ if (op == TOKconstruct && e1->op == TOKvar && - ((VarExp *)e1)->var->storage_class & (STCout | STCref)) + ((VarExp *)e1)->var->storage_class & (STCout | STCref) && !(ismemset & 2)) { // If this is an initialization of a reference, // do nothing @@ -11666,7 +11673,7 @@ Expression *AssignExp::semantic(Scope *sc) // Check for block assignment. If it is of type void[], void[][], etc, // '= null' is the only allowable block assignment (Bug 7493) // memset - ismemset = 1; // make it easy for back end to tell what this is + ismemset |= 1; // make it easy for back end to tell what this is e2x = e2x->implicitCastTo(sc, t1->nextOf()); if (op != TOKblit && e2x->isLvalue() && e1->checkPostblit(sc, t1->nextOf())) @@ -11784,7 +11791,7 @@ Expression *AssignExp::semantic(Scope *sc) if ((t2->ty == Tarray || t2->ty == Tsarray) && isArrayOpValid(e2)) { // Look for valid array operations - if (!ismemset && e1->op == TOKslice && + if (!(ismemset & 1) && e1->op == TOKslice && (isUnaArrayOp(e2->op) || isBinArrayOp(e2->op))) { type = e1->type; @@ -11795,7 +11802,7 @@ Expression *AssignExp::semantic(Scope *sc) // Drop invalid array operations in e2 // d = a[] + b[], d = (a[] + b[])[0..2], etc - if (checkNonAssignmentArrayOp(e2, !ismemset && op == TOKassign)) + if (checkNonAssignmentArrayOp(e2, !(ismemset & 1) && op == TOKassign)) return new ErrorExp(); // Remains valid array assignments diff --git a/src/expression.h b/src/expression.h index 4e02a1ba813d..1004120b34ad 100644 --- a/src/expression.h +++ b/src/expression.h @@ -1160,7 +1160,9 @@ class PreExp : public UnaExp class AssignExp : public BinExp { public: - int ismemset; // !=0 if setting the contents of an array + // &1 != 0 if setting the contents of an array + // &2 != 0 if setting the content of ref variable + int ismemset; AssignExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); diff --git a/test/runnable/sctor.d b/test/runnable/sctor.d index c678e6a7dd83..a4bc5532a105 100644 --- a/test/runnable/sctor.d +++ b/test/runnable/sctor.d @@ -316,6 +316,26 @@ class D14351c : B14351 this(inout int[] arr) inout { super(arr); } } +/***************************************************/ +// 14944 + +static int[2] tbl14944; + +static this() +{ + foreach (ref v; tbl14944) + { + // This is an initialization of referenced memory + // rather than the initialization of the reference. + v = 1; + } +} + +void test14944() +{ + assert(tbl14944[0] == 1); +} + /***************************************************/ int main() @@ -324,6 +344,7 @@ int main() test9665(); test11246(); test13515(); + test14944(); printf("Success\n"); return 0;