Skip to content

Commit

Permalink
Add specific supplemental message
Browse files Browse the repository at this point in the history
  • Loading branch information
ntrel committed Jun 12, 2024
1 parent 04327b4 commit 2f0efed
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
38 changes: 31 additions & 7 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -9251,14 +9251,23 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}

// Check for unsafe casts
auto r = isSafeCast(ex, t1b, tob);
if (r == -1 && sc.setUnsafePreview(FeatureState.default_, false, exp.loc,
"cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to))
return setError();

if (r == 0 && sc.setUnsafe(false, exp.loc,
string msg;
if (!isSafeCast(ex, t1b, tob, &msg))
{
if (sc.setUnsafe(false, exp.loc,
"cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to))
return setError();
return setError();
}
else if (msg) // deprecated unsafe
{
const err = sc.setUnsafePreview(FeatureState.default_, false, exp.loc,
"cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to);
// if message was printed
if (sc.func && sc.func.isSafeBypassingInference() && !sc.isDeprecated())
deprecationSupplemental(exp.loc, "%s", (msg ~ '\0').ptr);

Check warning on line 9267 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L9267

Added line #L9267 was not covered by tests
if (err)
return setError();
}

// `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
// to handle certain casts. Those casts which `object.__ArrayCast` does not support are filtered out.
Expand Down Expand Up @@ -15287,6 +15296,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)

Expression visitStructLiteral(StructLiteralExp exp)
{
if (!exp.elements)
return exp;

Check warning on line 15300 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L15300

Added line #L15300 was not covered by tests

foreach (ref element; *exp.elements)
{
if (element)
Expand All @@ -15305,6 +15317,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
if (exp.lowering)
exp.lowering = exp.lowering.resolveLoc(loc, sc);

if (!exp.arguments)
return exp;

foreach (ref element; *exp.arguments)
{
if (element)
Expand All @@ -15316,6 +15331,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)

Expression visitCall(CallExp exp)
{
if (!exp.arguments)
return exp;

Check warning on line 15335 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L15335

Added line #L15335 was not covered by tests

foreach (ref element; *exp.arguments)
{
if (element)
Expand All @@ -15329,6 +15347,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
{
exp.e1 = exp.e1.resolveLoc(loc, sc);

if (!exp.arguments)
return exp;

Check warning on line 15351 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L15350-L15351

Added lines #L15350 - L15351 were not covered by tests

foreach (ref element; *exp.arguments)
{
if (element)
Expand Down Expand Up @@ -15362,6 +15383,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
if (exp.basis)
exp.basis = exp.basis.resolveLoc(loc, sc);

if (!exp.elements)
return exp;

Check warning on line 15387 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L15387

Added line #L15387 was not covered by tests

foreach (ref element; *exp.elements)
{
if (element)
Expand Down
11 changes: 7 additions & 4 deletions compiler/src/dmd/safe.d
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,11 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
* e = expression to be cast
* tfrom = type of e
* tto = type to cast e to
* msg = reason why cast is unsafe or deprecated
* Returns:
* 1 if @safe
* -1 if deprecated
* true if @safe or deprecated
*/
byte isSafeCast(Expression e, Type tfrom, Type tto)
bool isSafeCast(Expression e, Type tfrom, Type tto, string* msg = null)
{
// Implicit conversions are always safe
if (tfrom.implicitConvTo(tto))
Expand Down Expand Up @@ -217,7 +217,10 @@ byte isSafeCast(Expression e, Type tfrom, Type tto)
// For bool, only 0 and 1 are safe values
// Runtime array cast reinterprets data
if (ttobn.ty == Tbool && tfromn.ty != Tbool && e.op != EXP.arrayLiteral)
return -1;
{
if (msg)
*msg = "Array data may have bytes which are not 0 or 1";
}

// If the struct is opaque we don't know about the struct members then the cast becomes unsafe
if (ttobn.ty == Tstruct && !(cast(TypeStruct)ttobn).sym.members ||
Expand Down
3 changes: 2 additions & 1 deletion compiler/test/fail_compilation/bool_cast.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
REQUIRED_ARGS: -de
TEST_OUTPUT:
---
fail_compilation/bool_cast.d(12): Deprecation: cast from `ubyte[]` to `bool[]` not allowed in safe code
fail_compilation/bool_cast.d(13): Deprecation: cast from `ubyte[]` to `bool[]` not allowed in safe code
fail_compilation/bool_cast.d(13): Array data may have bytes which are not 0 or 1
---
*/

Expand Down

0 comments on commit 2f0efed

Please sign in to comment.