Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -5158,6 +5158,19 @@ extern (C++) final class CastExp : UnaExp
return to ? new CastExp(loc, e1.syntaxCopy(), to.syntaxCopy()) : new CastExp(loc, e1.syntaxCopy(), mod);
}

override bool isLvalue()
{
//printf("e1.type = %s, to.type = %s\n", e1.type.toChars(), to.toChars());
return e1.isLvalue() && e1.type.mutableOf().unSharedOf().equals(to.mutableOf().unSharedOf());
}

override Expression toLvalue(Scope* sc, Expression e)
{
if (isLvalue())
return this;
return Expression.toLvalue(sc, e);
}

override Expression addDtorHook(Scope* sc)
{
if (to.toBasetype().ty == Tvoid) // look past the cast(void)
Expand Down
8 changes: 5 additions & 3 deletions src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -8515,12 +8515,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Try to do a decent error message with the expression
// before it got constant folded

if (e1x.op != TOK.variable)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

20011 is caused by the displacement of this IfStatement

e1x = e1x.optimize(WANTvalue);

// https://issues.dlang.org/show_bug.cgi?id=19754
// first see if the unoptimized expression is modifiable
if (exp.op == TOK.assign)
e1x = e1x.modifiableLvalue(sc, e1old);

if (e1x.op != TOK.variable)
e1x = e1x.optimize(WANTvalue);

if (e1x.op == TOK.error)
{
result = e1x;
Expand Down
8 changes: 7 additions & 1 deletion src/dmd/semantic3.d
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,13 @@ private extern(C++) final class Semantic3Visitor : Visitor
const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor;
// if a copy constructor is present, the return type conversion will be handled by it
if (!hasCopyCtor)
exp = exp.implicitCastTo(sc2, tret);
{
if (f.isref && !MODimplicitConv(exp.type.mod, tret.mod) && !tret.isTypeSArray())
error(exp.loc, "expression `%s` of type `%s` is not implicitly convertible to return type `ref %s`",
exp.toChars(), exp.type.toChars(), tret.toChars());
else
exp = exp.implicitCastTo(sc2, tret);
}

if (f.isref)
{
Expand Down
9 changes: 8 additions & 1 deletion src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -1343,7 +1343,8 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc)
if (fparam.defaultArg)
{
Expression e = fparam.defaultArg;
if (fparam.storageClass & (STC.ref_ | STC.out_))
auto isRefOrOut = fparam.storageClass & (STC.ref_ | STC.out_);
if (isRefOrOut)
{
e = e.expressionSemantic(argsc);
e = resolveProperties(argsc, e);
Expand All @@ -1365,6 +1366,12 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc)
e = new AddrExp(e.loc, e);
e = e.expressionSemantic(argsc);
}
if (isRefOrOut && !MODimplicitConv(e.type.mod, fparam.type.mod))
{
const(char)* errTxt = fparam.storageClass & STC.ref_ ? "ref" : "out";
.error(e.loc, "expression `%s` of type `%s` is not implicitly convertible to type `%s %s` of parameter `%s`",
e.toChars(), e.type.toChars(), errTxt, fparam.type.toChars(), fparam.toChars());
}
e = e.implicitCastTo(argsc, fparam.type);

// default arg must be an lvalue
Expand Down
11 changes: 0 additions & 11 deletions test/fail_compilation/ice14929.d → test/compilable/test14929.d
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice14929.d(45): Error: `cast(Node)(*this.current).items[this.index]` is not an lvalue and cannot be modified
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was casting a const(Node) to a Node.

fail_compilation/ice14929.d(88): Error: template instance `ice14929.HashMap!(ulong, int).HashMap.opBinaryRight!"in"` error instantiating
fail_compilation/ice14929.d(92): instantiated from here: `HashmapComponentStorage!int`
fail_compilation/ice14929.d(92): Error: template instance `ice14929.isComponentStorage!(HashmapComponentStorage!int, int)` error instantiating
fail_compilation/ice14929.d(92): while evaluating: `static assert(isComponentStorage!(HashmapComponentStorage!int, int))`
---
*/

struct HashMap(K, V)
{
V* opBinaryRight(string op)(K key) const if (op == "in")
Expand Down
11 changes: 11 additions & 0 deletions test/compilable/test19754.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
void main()
{
shared int x;
(cast() x) = 5;

const int x1;
(cast() x1) = 5;

immutable int x2;
(cast() x2) = 5;
}
10 changes: 6 additions & 4 deletions test/fail_compilation/diag4596.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag4596.d(15): Error: `this` is not an lvalue and cannot be modified
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The branches of the ?: operator may return different things, e.g. an rvalue and an rvalue; this way the error is printed depending on the branch

fail_compilation/diag4596.d(16): Error: `1 ? this : this` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(18): Error: `super` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(19): Error: `1 ? super : super` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(17): Error: `this` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(18): Error: `this` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(18): Error: `this` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(20): Error: `super` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(21): Error: `super` is not an lvalue and cannot be modified
fail_compilation/diag4596.d(21): Error: `super` is not an lvalue and cannot be modified
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail106.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail106.d(12): Error: cannot modify `immutable` expression `'C'`
fail_compilation/fail106.d(12): Error: cannot modify `immutable` expression `"ABC"[2]`
---
*/

Expand Down
12 changes: 4 additions & 8 deletions test/fail_compilation/fail17491.d
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
/* TEST_OUTPUT:
---
fail_compilation/fail17491.d(24): Error: `(S17491).init` is not an lvalue and cannot be modified
fail_compilation/fail17491.d(25): Error: `S17491(0)` is not an lvalue and cannot be modified
fail_compilation/fail17491.d(27): Error: cannot modify constant `S17491(0).field`
fail_compilation/fail17491.d(28): Error: cannot modify constant `*&S17491(0).field`
fail_compilation/fail17491.d(33): Error: `S17491(0)` is not an lvalue and cannot be modified
fail_compilation/fail17491.d(34): Error: `S17491(0)` is not an lvalue and cannot be modified
fail_compilation/fail17491.d(36): Error: cannot modify constant `S17491(0).field`
fail_compilation/fail17491.d(37): Error: cannot modify constant `*&S17491(0).field`
fail_compilation/fail17491.d(20): Error: `(S17491).init` is not an lvalue and cannot be modified
fail_compilation/fail17491.d(21): Error: `S17491(0)` is not an lvalue and cannot be modified
fail_compilation/fail17491.d(29): Error: `S17491(0)` is not an lvalue and cannot be modified
fail_compilation/fail17491.d(30): Error: `S17491(0)` is not an lvalue and cannot be modified
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail351.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail351.d(14): Error: `cast(uint)this.num[index]` is not an lvalue and cannot be modified
fail_compilation/fail351.d(14): Error: expression `this.num[index]` of type `immutable(uint)` is not implicitly convertible to return type `ref uint`
---
*/

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/fail9891.d
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail9891.d(13): Error: `cast(int)i` is not an lvalue and cannot be modified
fail_compilation/fail9891.d(18): Error: `cast(int)i` is not an lvalue and cannot be modified
fail_compilation/fail9891.d(13): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `ref int` of parameter `n`
fail_compilation/fail9891.d(18): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `out int` of parameter `n`
fail_compilation/fail9891.d(23): Error: `prop()` is not an lvalue and cannot be modified
---
*/
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/test12385.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/test12385.d(29): Error: cannot modify `immutable` expression `BundledState("bla", 3).x`
fail_compilation/test12385.d(29): Error: cannot modify `immutable` expression `unbundled.x`
---
*/

Expand Down