From 2f0efed2fc4af5785878abf7972f8a6536cadbb2 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 12 Jun 2024 11:29:34 +0100 Subject: [PATCH] Add specific supplemental message --- compiler/src/dmd/expressionsem.d | 38 ++++++++++++++++++---- compiler/src/dmd/safe.d | 11 ++++--- compiler/test/fail_compilation/bool_cast.d | 3 +- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index fc100f859411..c2a094413c70 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -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); + 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. @@ -15287,6 +15296,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) Expression visitStructLiteral(StructLiteralExp exp) { + if (!exp.elements) + return exp; + foreach (ref element; *exp.elements) { if (element) @@ -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) @@ -15316,6 +15331,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) Expression visitCall(CallExp exp) { + if (!exp.arguments) + return exp; + foreach (ref element; *exp.arguments) { if (element) @@ -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; + foreach (ref element; *exp.arguments) { if (element) @@ -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; + foreach (ref element; *exp.elements) { if (element) diff --git a/compiler/src/dmd/safe.d b/compiler/src/dmd/safe.d index b2dacc39efb7..9f094d00ee27 100644 --- a/compiler/src/dmd/safe.d +++ b/compiler/src/dmd/safe.d @@ -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)) @@ -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 || diff --git a/compiler/test/fail_compilation/bool_cast.d b/compiler/test/fail_compilation/bool_cast.d index ccacd62725c8..6a0f537a6f97 100644 --- a/compiler/test/fail_compilation/bool_cast.d +++ b/compiler/test/fail_compilation/bool_cast.d @@ -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 --- */