diff --git a/src/ddmd/expression.d b/src/ddmd/expression.d index ae60d1a5609a..24ecd7f57a53 100644 --- a/src/ddmd/expression.d +++ b/src/ddmd/expression.d @@ -6016,12 +6016,11 @@ extern (C++) abstract class BinExp : Expression // T opAssign floating yields a floating. Prevent truncating conversions (float to int). // See issue 3841. - // Should we also prevent double to float (type.isfloating() && type.size() < t2.size()) ? if (op == TOKaddass || op == TOKminass || op == TOKmulass || op == TOKdivass || op == TOKmodass || op == TOKpowass) { - if ((type.isintegral() && t2.isfloating())) + if ((type.isintegral() && t2.isfloating()) || (type.isfloating() && type.size() < t2.size())) { warning("%s %s %s is performing truncating conversion", type.toChars(), Token.toChars(op), t2.toChars()); } diff --git a/src/ddmd/expressionsem.d b/src/ddmd/expressionsem.d index 4faf0c19bd5d..bc9fe090d496 100644 --- a/src/ddmd/expressionsem.d +++ b/src/ddmd/expressionsem.d @@ -5396,6 +5396,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor assert(exp.e1.type); } Type t1 = exp.e1.type.toBasetype(); + Type oldt2; /* Run this.e2 semantic. * Different from other binary expressions, the analysis of e2 @@ -5414,7 +5415,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (e2x.checkValue()) return setError(); + exp.e2 = e2x; + if (e2x.type) + oldt2 = e2x.type; } /* Rewrite tuple assignment as a tuple of assignments. @@ -6144,6 +6148,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.e2 = e2x; t2 = exp.e2.type.toBasetype(); + if (oldt2 && oldt2.isfloating() && exp.e1.type.isfloating() && + exp.e1.type.size() < oldt2.size()) + { + exp.warning("%s = %s is performing truncating conversion", + exp.e1.type.toChars(), oldt2.toChars()); + } + /* Look for array operations */ if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2)) diff --git a/src/ddmd/statementsem.d b/src/ddmd/statementsem.d index f52f30183000..be753081f908 100644 --- a/src/ddmd/statementsem.d +++ b/src/ddmd/statementsem.d @@ -2928,6 +2928,13 @@ else */ } + if (rs && rs.exp && tret && tret.isfloating() && rs.exp.type.isfloating() && + tret.size() < rs.exp.type.size()) + { + rs.warning("return %s from %s function is performing truncating conversion", + rs.exp.type.toChars(), tret.toChars()); + } + // handle NRVO if (fd.nrvo_can && rs.exp.op == TOKvar) { diff --git a/test/fail_compilation/warn17933.d b/test/fail_compilation/warn17933.d new file mode 100644 index 000000000000..919980244d21 --- /dev/null +++ b/test/fail_compilation/warn17933.d @@ -0,0 +1,24 @@ +// REQUIRED_ARGS: -w + +/* +TEST_OUTPUT: +--- +fail_compilation/warn17933.d(14): Warning: float = double is performing truncating conversion +fail_compilation/warn17933.d(15): Warning: float += double is performing truncating conversion +fail_compilation/warn17933.d(22): Warning: return double from float function is performing truncating conversion +--- +*/ + +void test17933() +{ + float f; + double d; + f = d; + f += 0.1; +} + +float testReturn(float f) +{ + return f * 0.5; +} +