Skip to content

Commit

Permalink
Fix Bugzilla 24434 - Casting away const with cast() is not a @safe lv… (
Browse files Browse the repository at this point in the history
#16315)

* Fix Bugzilla 24434 - Casting away const with cast() is not a @safe lvalue

* Use `pointerTo`

* Use cast to hide lvalue append error

* Fix unsafe shared increment

* Use setUnsafePreview

* Add test for lvalue assign

* Fix qualifier cast check

* Workaround for safe append

Fixes Bugzilla 23530 - casting immutable away allowed in safe.

* Update header

* Trigger tests
  • Loading branch information
ntrel authored Apr 28, 2024
1 parent ca7ee01 commit e60bfd1
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -3824,6 +3824,7 @@ extern (C++) final class CastExp : UnaExp
{
Type to; // type to cast to
ubyte mod = cast(ubyte)~0; // MODxxxxx
bool trusted; // assume cast is safe

extern (D) this(const ref Loc loc, Expression e, Type t) @safe
{
Expand Down
14 changes: 13 additions & 1 deletion compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -11865,7 +11865,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (checkNewEscape(*sc, exp.e2, false))
return setError();

exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
auto ecast = exp.e2.castTo(sc, tb1next);
if (auto ce = ecast.isCastExp())
ce.trusted = true;

exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, ecast);
exp.e2 = doCopyOrMove(sc, exp.e2);
}
else if (tb1.ty == Tarray &&
Expand Down Expand Up @@ -15735,7 +15739,15 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action
return visit(_this);
}
if (_this.isLvalue())
{
with (_this)
if (!trusted && !e1.type.pointerTo().implicitConvTo(to.pointerTo()))
sc.setUnsafePreview(FeatureState.default_, false, loc,
"cast from `%s` to `%s` cannot be used as an lvalue in @safe code",
e1.type, to);

return _this;
}
return visit(_this);
}

Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -2435,6 +2435,7 @@ class CastExp final : public UnaExp
public:
Type* to;
uint8_t mod;
bool trusted;
CastExp* syntaxCopy() override;
bool isLvalue() override;
void accept(Visitor* v) override;
Expand Down
19 changes: 19 additions & 0 deletions compiler/test/fail_compilation/cast_qual.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
REQUIRED_ARGS: -preview=dip1000 -de
TEST_OUTPUT:
---
fail_compilation/cast_qual.d(15): Deprecation: cast from `const(int)` to `int` cannot be used as an lvalue in @safe code
fail_compilation/cast_qual.d(17): Deprecation: cast from `const(int)` to `int` cannot be used as an lvalue in @safe code
---
*/

@safe:

void main() {
const int i = 3;
int j = cast() i; // OK
int* p = &cast() i; // this should not compile in @safe code
*p = 4; // oops
cast() i = 5; // NG
auto q = &cast(const) j; // OK, int* to const int*
}
2 changes: 1 addition & 1 deletion druntime/src/core/sync/mutex.d
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ unittest
cargo = 42;
}

void useResource() shared @safe nothrow @nogc
void useResource() shared @trusted nothrow @nogc
{
mtx.lock_nothrow();
(cast() cargo) += 1;
Expand Down

0 comments on commit e60bfd1

Please sign in to comment.