From 1e6d81ec316a62eb25ef6f96851a56b92ad15ccd Mon Sep 17 00:00:00 2001 From: Sergii Kuzko Date: Wed, 21 Jan 2026 17:28:39 +0300 Subject: [PATCH 1/3] fix --- compiler/src/dmd/expressionsem.d | 28 +++++++++++++++++++++- compiler/test/compilable/interpret4.d | 1 - compiler/test/fail_compilation/fail22328.d | 23 ++++++++++++++++++ compiler/test/fail_compilation/fail6795.d | 14 ++++++----- compiler/test/fail_compilation/retscope3.d | 2 +- compiler/test/fail_compilation/test21634.d | 2 +- compiler/test/runnable/nogc.d | 11 --------- compiler/test/runnable/test6795.d | 10 ++++---- 8 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 compiler/test/fail_compilation/fail22328.d diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index eb6cca75a85f..83cde15bb180 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -17561,7 +17561,24 @@ Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyF //printf("SliceExp::checkModifiable %s\n", sliceExp.toChars()); auto e1 = sliceExp.e1; - if (e1.type.ty == Tsarray || (e1.op == EXP.index && e1.type.ty != Tarray) || e1.op == EXP.slice) + + if (e1.op == EXP.arrayLiteral || e1.op == EXP.structLiteral) + { + if (!(flag & ModifyFlags.noError)) + { + if (e1.type.ty != Terror) + { + error(exp.loc, "cannot modify the content of %s literal `%s`", + e1.op == EXP.arrayLiteral ? "array".ptr : "struct".ptr, + e1.toChars()); + } + } + return Modifiable.no; + } + + if (e1.type.ty == Tsarray || + (e1.op == EXP.index && e1.type.ty != Tarray) || + e1.op == EXP.slice) { return e1.checkModifiable(sc, flag); } @@ -17573,6 +17590,15 @@ Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyF case EXP.index: auto indexExp = cast(IndexExp)exp; auto e1 = indexExp.e1; + + if (e1.op == EXP.arrayLiteral || e1.op == EXP.structLiteral) + { + if (!(flag & ModifyFlags.noError)) + error(exp.loc, "cannot modify the content of %s literal `%s`", + e1.op == EXP.arrayLiteral ? "array".ptr : "struct".ptr, + e1.toChars()); + return Modifiable.no; + } if (e1.type.ty == Tsarray || e1.type.ty == Taarray || (e1.op == EXP.index && e1.type.ty != Tarray) || diff --git a/compiler/test/compilable/interpret4.d b/compiler/test/compilable/interpret4.d index 98ebcdff745a..ef0a9598fbef 100644 --- a/compiler/test/compilable/interpret4.d +++ b/compiler/test/compilable/interpret4.d @@ -43,6 +43,5 @@ int* find(int[] arr, int needle) enum int[int] aa = [0: 0]; enum int[] da = [0, 1, 2]; static assert(0 in aa); -static assert(&da[1]); static assert(find(da, 1)); static assert(!find(da, 3)); diff --git a/compiler/test/fail_compilation/fail22328.d b/compiler/test/fail_compilation/fail22328.d new file mode 100644 index 000000000000..3c8ae9301a07 --- /dev/null +++ b/compiler/test/fail_compilation/fail22328.d @@ -0,0 +1,23 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fail22328.d(17): Error: cannot modify the content of array literal `[1, 2, 3]` +fail_compilation/fail22328.d(17): Error: cannot modify the content of array literal `[1, 2, 3]` +fail_compilation/fail22328.d(17): Error: cannot modify expression `[1, 2, 3][2]` because it is not an lvalue +fail_compilation/fail22328.d(18): Error: cannot modify the content of array literal `[10, 20]` +fail_compilation/fail22328.d(18): Error: cannot modify the content of array literal `[10, 20]` +fail_compilation/fail22328.d(18): Error: cannot modify expression `[10, 20][0]` because it is not an lvalue +fail_compilation/fail22328.d(20): Error: cannot modify the content of array literal `[1, 2, 3]` +fail_compilation/fail22328.d(22): Error: cannot take address of expression `[1, 2, 3][0]` because it is not an lvalue +--- +*/ + +void main() { + enum ARR = [1, 2, 3]; + ARR[2] = 4; + [10, 20][0] = 30; + + ARR[0..2] = [4, 5]; + + auto p = &ARR[0]; +} diff --git a/compiler/test/fail_compilation/fail6795.d b/compiler/test/fail_compilation/fail6795.d index e566aff570a9..dc25f50e0cc5 100644 --- a/compiler/test/fail_compilation/fail6795.d +++ b/compiler/test/fail_compilation/fail6795.d @@ -2,12 +2,14 @@ /* TEST_OUTPUT: --- -fail_compilation/fail6795.d(19): Error: cannot modify expression `[0][0]` because it is not an lvalue -fail_compilation/fail6795.d(20): Error: cannot modify expression `[0:0][0]` because it is not an lvalue -fail_compilation/fail6795.d(22): Error: cannot modify expression `[0][0]` because it is not an lvalue -fail_compilation/fail6795.d(23): Error: cannot modify expression `[0:0][0]` because it is not an lvalue -fail_compilation/fail6795.d(25): Error: cannot take address of expression `[0][0]` because it is not an lvalue -fail_compilation/fail6795.d(30): Error: cannot modify expression `Some["zz"]` because it is not an lvalue +fail_compilation/fail6795.d(21): Error: cannot modify the content of array literal `[0]` +fail_compilation/fail6795.d(21): Error: cannot modify expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(22): Error: cannot modify expression `[0:0][0]` because it is not an lvalue +fail_compilation/fail6795.d(24): Error: cannot modify the content of array literal `[0]` +fail_compilation/fail6795.d(24): Error: cannot modify expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(25): Error: cannot modify expression `[0:0][0]` because it is not an lvalue +fail_compilation/fail6795.d(27): Error: cannot take address of expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(32): Error: cannot modify expression `Some["zz"]` because it is not an lvalue --- */ diff --git a/compiler/test/fail_compilation/retscope3.d b/compiler/test/fail_compilation/retscope3.d index 8802469de2c4..da0c8a29ed3d 100644 --- a/compiler/test/fail_compilation/retscope3.d +++ b/compiler/test/fail_compilation/retscope3.d @@ -57,7 +57,7 @@ fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape fail_compilation/retscope3.d(4025): Deprecation: slice of static array temporary returned by `makeSA()` assigned to longer lived variable `a` fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory -fail_compilation/retscope3.d(4032): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function +fail_compilation/retscope3.d(4032): Error: cannot take address of expression `[& i][0]` because it is not an lvalue --- */ diff --git a/compiler/test/fail_compilation/test21634.d b/compiler/test/fail_compilation/test21634.d index 30bce9919145..2cf2a7b4acbe 100644 --- a/compiler/test/fail_compilation/test21634.d +++ b/compiler/test/fail_compilation/test21634.d @@ -7,7 +7,7 @@ fail_compilation/test21634.d(22): Error: function literal `(int x) { }` is not c ^ fail_compilation/test21634.d(22): cannot pass argument `"%s"` of type `string` to parameter `int x` (int x) {} ("%s"); - ^ + ^ fail_compilation/test21634.d(24): Error: declaration `test21634.main.foo` is already defined int foo; ^ diff --git a/compiler/test/runnable/nogc.d b/compiler/test/runnable/nogc.d index c71866fc1995..523a7a99bcb4 100644 --- a/compiler/test/runnable/nogc.d +++ b/compiler/test/runnable/nogc.d @@ -79,16 +79,6 @@ void testIndexedArrayLiteral() @nogc assert(arr[i] == 400); } -void testArrayLiteralLvalue() -{ - // https://github.com/dlang/dmd/pull/16784 - // Test that this array literal is *not* put on the stack because - // it gets its address taken - static int* getPtr(int i) => &[1, 2, 3][i]; - int* x = getPtr(1); - int* y = getPtr(1); - assert(x != y); -} /***********************/ @@ -98,7 +88,6 @@ int main() test3032(); test12642(); test12936(); - testArrayLiteralLvalue(); printf("Success\n"); return 0; diff --git a/compiler/test/runnable/test6795.d b/compiler/test/runnable/test6795.d index 7e44fd4ad7a7..eef57a95a34d 100644 --- a/compiler/test/runnable/test6795.d +++ b/compiler/test/runnable/test6795.d @@ -1,13 +1,13 @@ // https://issues.dlang.org/show_bug.cgi?id=6795 void check6795() { - enum int[] array = [0]; + auto array = [0]; // PostExp assert(array[0]++ == 0); - assert(array[0]-- == 0); + assert(array[0]-- == 1); // PreExp assert(++array[0] == 1); - assert(--array[0] == -1); + assert(--array[0] == 0); // BinAssignExp assert((array[0] += 3) == 3); } @@ -15,7 +15,9 @@ void check6795() // https://issues.dlang.org/show_bug.cgi?id=21312 void check21312() { - auto p = &[123][0]; + int[1] tmp = [123]; + auto p = &tmp[0]; + assert(*p == 123); } From 72d1934d14ee04a6f07e79be5a9fc4d733502eb4 Mon Sep 17 00:00:00 2001 From: Sergii Kuzko Date: Wed, 21 Jan 2026 18:56:28 +0300 Subject: [PATCH 2/3] fix --- .../test/fail_compilation/array_literal_assign.d | 15 +++++++++++---- compiler/test/fail_compilation/fail22328.d | 15 +++++++-------- compiler/test/fail_compilation/retscope3.d | 10 +++++----- compiler/test/fail_compilation/test21634.d | 2 +- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/compiler/test/fail_compilation/array_literal_assign.d b/compiler/test/fail_compilation/array_literal_assign.d index f10b5d63c12c..16a8bdc75c56 100644 --- a/compiler/test/fail_compilation/array_literal_assign.d +++ b/compiler/test/fail_compilation/array_literal_assign.d @@ -1,10 +1,17 @@ /* TEST_OUTPUT: --- -fail_compilation/array_literal_assign.d(13): Error: discarded assignment to indexed array literal -fail_compilation/array_literal_assign.d(15): Error: discarded assignment to indexed array literal -fail_compilation/array_literal_assign.d(16): Error: discarded assignment to indexed array literal -fail_compilation/array_literal_assign.d(17): Error: discarded assignment to indexed array literal +fail_compilation/array_literal_assign.d(20): Error: cannot modify the content of array literal `[1, 2, 3]` +fail_compilation/array_literal_assign.d(20): Error: cannot modify the content of array literal `[1, 2, 3]` +fail_compilation/array_literal_assign.d(20): Error: discarded assignment to indexed array literal +fail_compilation/array_literal_assign.d(22): Error: cannot modify the content of array literal `[1, 2]` +fail_compilation/array_literal_assign.d(22): Error: discarded assignment to indexed array literal +fail_compilation/array_literal_assign.d(23): Error: cannot modify the content of array literal `[1, 2]` +fail_compilation/array_literal_assign.d(23): Error: discarded assignment to indexed array literal +fail_compilation/array_literal_assign.d(24): Error: cannot modify the content of array literal `[1, 2]` +fail_compilation/array_literal_assign.d(24): Error: discarded assignment to indexed array literal +fail_compilation/array_literal_assign.d(26): Error: cannot modify the content of array literal `[1, 2]` +fail_compilation/array_literal_assign.d(26): Error: cannot modify the content of array literal `[1, 2]` --- */ diff --git a/compiler/test/fail_compilation/fail22328.d b/compiler/test/fail_compilation/fail22328.d index 3c8ae9301a07..fece144963dc 100644 --- a/compiler/test/fail_compilation/fail22328.d +++ b/compiler/test/fail_compilation/fail22328.d @@ -1,14 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/fail22328.d(17): Error: cannot modify the content of array literal `[1, 2, 3]` -fail_compilation/fail22328.d(17): Error: cannot modify the content of array literal `[1, 2, 3]` -fail_compilation/fail22328.d(17): Error: cannot modify expression `[1, 2, 3][2]` because it is not an lvalue -fail_compilation/fail22328.d(18): Error: cannot modify the content of array literal `[10, 20]` -fail_compilation/fail22328.d(18): Error: cannot modify the content of array literal `[10, 20]` -fail_compilation/fail22328.d(18): Error: cannot modify expression `[10, 20][0]` because it is not an lvalue -fail_compilation/fail22328.d(20): Error: cannot modify the content of array literal `[1, 2, 3]` -fail_compilation/fail22328.d(22): Error: cannot take address of expression `[1, 2, 3][0]` because it is not an lvalue +fail_compilation/fail22328.d(16): Error: cannot modify the content of array literal `[1, 2, 3]` +fail_compilation/fail22328.d(16): Error: cannot modify the content of array literal `[1, 2, 3]` +fail_compilation/fail22328.d(16): Error: discarded assignment to indexed array literal +fail_compilation/fail22328.d(17): Error: cannot modify the content of array literal `[10, 20]` +fail_compilation/fail22328.d(17): Error: cannot modify the content of array literal `[10, 20]` +fail_compilation/fail22328.d(17): Error: discarded assignment to indexed array literal +fail_compilation/fail22328.d(19): Error: cannot modify the content of array literal `[1, 2, 3]` --- */ diff --git a/compiler/test/fail_compilation/retscope3.d b/compiler/test/fail_compilation/retscope3.d index da0c8a29ed3d..aa0e3496c56c 100644 --- a/compiler/test/fail_compilation/retscope3.d +++ b/compiler/test/fail_compilation/retscope3.d @@ -7,6 +7,11 @@ TEST_OUTPUT: --- fail_compilation/retscope3.d(2008): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function fail_compilation/retscope3.d(2017): Error: escaping a reference to local variable `i` by copying `S2000(& i)` into allocated memory is not allowed in a `@safe` function +fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` by copying `u[]` into allocated memory is not allowed in a `@safe` function +fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape +fail_compilation/retscope3.d(4025): Deprecation: slice of static array temporary returned by `makeSA()` assigned to longer lived variable `a` +fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory +fail_compilation/retscope3.d(4032): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function --- */ @@ -53,11 +58,6 @@ void bar4() /* TEST_OUTPUT: --- -fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` by copying `u[]` into allocated memory is not allowed in a `@safe` function -fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape -fail_compilation/retscope3.d(4025): Deprecation: slice of static array temporary returned by `makeSA()` assigned to longer lived variable `a` -fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory -fail_compilation/retscope3.d(4032): Error: cannot take address of expression `[& i][0]` because it is not an lvalue --- */ diff --git a/compiler/test/fail_compilation/test21634.d b/compiler/test/fail_compilation/test21634.d index 2cf2a7b4acbe..30bce9919145 100644 --- a/compiler/test/fail_compilation/test21634.d +++ b/compiler/test/fail_compilation/test21634.d @@ -7,7 +7,7 @@ fail_compilation/test21634.d(22): Error: function literal `(int x) { }` is not c ^ fail_compilation/test21634.d(22): cannot pass argument `"%s"` of type `string` to parameter `int x` (int x) {} ("%s"); - ^ + ^ fail_compilation/test21634.d(24): Error: declaration `test21634.main.foo` is already defined int foo; ^ From dbfe2584028802678124ff62a0842a865a215976 Mon Sep 17 00:00:00 2001 From: Sergii Kuzko Date: Wed, 21 Jan 2026 19:08:44 +0300 Subject: [PATCH 3/3] fix --- compiler/test/fail_compilation/retscope3.d | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/test/fail_compilation/retscope3.d b/compiler/test/fail_compilation/retscope3.d index aa0e3496c56c..8802469de2c4 100644 --- a/compiler/test/fail_compilation/retscope3.d +++ b/compiler/test/fail_compilation/retscope3.d @@ -7,11 +7,6 @@ TEST_OUTPUT: --- fail_compilation/retscope3.d(2008): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function fail_compilation/retscope3.d(2017): Error: escaping a reference to local variable `i` by copying `S2000(& i)` into allocated memory is not allowed in a `@safe` function -fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` by copying `u[]` into allocated memory is not allowed in a `@safe` function -fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape -fail_compilation/retscope3.d(4025): Deprecation: slice of static array temporary returned by `makeSA()` assigned to longer lived variable `a` -fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory -fail_compilation/retscope3.d(4032): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function --- */ @@ -58,6 +53,11 @@ void bar4() /* TEST_OUTPUT: --- +fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` by copying `u[]` into allocated memory is not allowed in a `@safe` function +fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape +fail_compilation/retscope3.d(4025): Deprecation: slice of static array temporary returned by `makeSA()` assigned to longer lived variable `a` +fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory +fail_compilation/retscope3.d(4032): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function --- */