diff --git a/src/declaration.c b/src/declaration.c index 8d1b983cd01e..a0fc4570c8d4 100644 --- a/src/declaration.c +++ b/src/declaration.c @@ -138,8 +138,13 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *t) if ((sc->flags & SCOPEcontract) && isResult()) error(loc, "cannot modify result '%s' in contract", toChars()); - if (isCtorinit() && !t->isMutable() || - (storage_class & STCnodefaultctor)) + if (isCtorinit() && !t->isMutable()) + { + if ((storage_class & (STCforeach | STCref)) == (STCforeach | STCref)) + return TRUE; + return modifyFieldVar(loc, sc, isVarDeclaration(), NULL); + } + else if (storage_class & STCnodefaultctor) { // It's only modifiable if inside the right constructor return modifyFieldVar(loc, sc, isVarDeclaration(), NULL); } diff --git a/src/statement.c b/src/statement.c index d7af09979a48..5e25737fbcc3 100644 --- a/src/statement.c +++ b/src/statement.c @@ -1812,7 +1812,9 @@ Statement *ForeachStatement::semantic(Scope *sc) { /* Reference to immutable data should be marked as const */ - if (!tn->isMutable()) + if (aggr->checkCtorInit(sc)) + var->storage_class |= STCctorinit; + else if (!tn->isMutable()) var->storage_class |= STCconst; Type *t = tab->nextOf(); diff --git a/test/runnable/assignable.d b/test/runnable/assignable.d index e442e45b1dfd..24c0056e5aa3 100644 --- a/test/runnable/assignable.d +++ b/test/runnable/assignable.d @@ -1120,6 +1120,24 @@ void test6336() // Allow return by ref both S1 and S2 } +/***************************************************/ +// 8783 + +struct Foo8783 +{ + int[1] bar; +} + +const Foo8783[1] foos8783; + +static this() +{ + foreach (i; 0 .. foos8783.length) + foos8783[i].bar[i] = 1; // OK + foreach (i, ref f; foos8783) + f.bar[i] = 1; // line 9, Error +} + /***************************************************/ // 9077