diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index c7cfb4a7dd10..a109f4bd4e67 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -704,7 +704,8 @@ bool isLvalue(Expression _this) return false; auto t1b = _this.e1.type.toBasetype(); if (t1b.isTypeAArray() || t1b.isTypeSArray() || - (_this.e1.isIndexExp() && t1b != t1b.isTypeDArray())) + (_this.e1.isIndexExp() && t1b != t1b.isTypeDArray()) || + _this.e1.op == EXP.arrayLiteral) { return _this.e1.isLvalue(); } @@ -2072,9 +2073,7 @@ Expression checkNoreturnVarAccess(Expression exp) { auto msg = new StringExp(exp.loc, "Accessed expression of type `noreturn`"); msg.type = Type.tstring; - auto ae = new AssertExp(exp.loc, IntegerExp.literal!0, msg); - ae.loweredFrom = exp; - result = ae; + result = new AssertExp(exp.loc, IntegerExp.literal!0, msg); result.type = exp.type; } @@ -4189,10 +4188,6 @@ private bool functionParameters(Loc loc, Scope* sc, arg = arg.resolveLoc(loc, sc); (*arguments)[i] = arg; } - else if (!(p.storageClass & (STC.ref_ | STC.out_))) - { - (*arguments)[i] = checkNoreturnVarAccess(arg); - } if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic { @@ -8257,7 +8252,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - void errorHelper(const(char)* failMessage, Loc argloc) scope + void errorHelper(const(char)* failMessage, Loc loc) scope { OutBuffer buf; buf.writeByte('('); @@ -8270,7 +8265,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor .error(exp.loc, "%s `%s` is not callable using argument types `%s`", p, exp.e1.toErrMsg(), buf.peekChars()); if (failMessage) - errorSupplemental((argloc !is Loc.initial) ? argloc : exp.loc, "%s", failMessage); + errorSupplemental(exp.loc, "%s", failMessage); } if (callMatch(exp.f, tf, null, exp.argumentList, 0, &errorHelper, sc) == MATCH.nomatch) @@ -8333,7 +8328,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.f = exp.f.toAliasFunc(); TypeFunction tf = cast(TypeFunction)exp.f.type; - void errorHelper2(const(char)* failMessage, Loc argloc) scope + void errorHelper2(const(char)* failMessage, Loc loc) scope { OutBuffer buf; buf.writeByte('('); @@ -8351,7 +8346,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor .error(exp.loc, "%s `%s` is not callable using argument types `%s`", exp.f.kind(), exp.f.toErrMsg(), buf.peekChars()); if (failMessage) - errorSupplemental((argloc !is Loc.initial) ? argloc : exp.loc, "%s", failMessage); + errorSupplemental(exp.loc, "%s", failMessage); .errorSupplemental(exp.f.loc, "`%s%s` declared here", exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList)); exp.f = null; } @@ -17558,7 +17553,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); } @@ -17570,6 +17582,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/diag21167.d b/compiler/test/fail_compilation/diag21167.d index f400a194e8c0..fd6e8140f441 100644 --- a/compiler/test/fail_compilation/diag21167.d +++ b/compiler/test/fail_compilation/diag21167.d @@ -1,9 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation\diag21167.d(15): Error: function `f` is not callable using argument types `(int, string, int)` -fail_compilation\diag21167.d(17): cannot pass argument `"foo"` of type `string` to parameter `int __param_1` -fail_compilation\diag21167.d(11): `diag21167.f(int __param_0, int __param_1, int __param_2)` declared here +fail_compilation/diag21167.d(15): Error: function `f` is not callable using argument types `(int, string, int)` +fail_compilation/diag21167.d(15): cannot pass argument `"foo"` of type `string` to parameter `int __param_1` +fail_compilation/diag21167.d(11): `diag21167.f(int __param_0, int __param_1, int __param_2)` declared here --- */ // https://github.com/dlang/dmd/issues/21167 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); }