diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index 38f913ed68..c12d3bf690 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -11873,6 +11873,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor (tb2.ty == Tarray || tb2.ty == Tsarray) && (exp.e2.implicitConvTo(exp.e1.type) || (tb2.nextOf().implicitConvTo(tb1next) && + // Do not strip const(void)[] + (!global.params.fixImmutableConv || tb1next.ty != Tvoid) && (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial))))) { // EXP.concatenateAssign @@ -12622,7 +12624,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.type = tb.nextOf().arrayOf(); if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod) { - exp.type = exp.type.nextOf().toHeadMutable().arrayOf(); + // Do not strip const(void)[] + if (!global.params.fixImmutableConv || tb.nextOf().ty != Tvoid) + exp.type = exp.type.nextOf().toHeadMutable().arrayOf(); } if (Type tbn = tb.nextOf()) { diff --git a/compiler/test/fail_compilation/void_cat.d b/compiler/test/fail_compilation/void_cat.d new file mode 100644 index 0000000000..da92d3b75b --- /dev/null +++ b/compiler/test/fail_compilation/void_cat.d @@ -0,0 +1,21 @@ +/* +REQUIRED_ARGS: -preview=fixImmutableConv +TEST_OUTPUT: +--- +fail_compilation/void_cat.d(15): Error: cannot copy `const(void)[]` to `void[]` +fail_compilation/void_cat.d(15): Source data has incompatible type qualifier(s) +fail_compilation/void_cat.d(15): Use `cast(void[])` to force copy +fail_compilation/void_cat.d(19): Error: cannot append type `const(void)[]` to type `void[]` +--- +*/ + +void g(int*[] a, const(int*)[] b) @system +{ + void[] va = a; + va[] = va.init ~ b; // a now contains b's data + *a[0] = 0; // modify const data + + const(void)[] vb = b; + va ~= vb; // also leaks const pointers into void[] + // va could be copied into `a` via another void[] +}