https://issues.dlang.org/show_bug.cgi?id=15805
Issue ID: 15805 Summary: Automatic fix two erroneous integer comparison cases by widening Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: enhancement Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: b2.t...@gmx.com The front end could automatically fix two cases where comparing two integers gives in wrong results. The trick is to widen the unsigned argument in a signed value, for example int a = -1; uint b; if (a > b) {} "b" can be widened in a long, which fixes the comaprison results. POC in a simple template: import std.traits; bool safeIntegralCmp(string op, L, R)(auto ref L lhs, auto ref R rhs) if (isIntegral!R && isIntegral!L) { // safe static if (is(Unqual!L == Unqual!R)) { mixin("return lhs" ~ op ~ "rhs;"); } else { // promote unsigned to bigger signed static if (isSigned!L && !isSigned!R && R.sizeof < 8) { long widenedRhs = rhs; mixin("return lhs" ~ op ~ "widenedRhs;"); } else static if (isSigned!R && !isSigned!L && L.sizeof < 8) { long widenedLhs = lhs; mixin("return widened" ~ op ~ "rhs;"); } // not fixable by operand widening else { pragma(msg, "warning, comparing a" ~ L.stringof ~ " with a" ~ R.stringof ~ " may result into wrong results"); mixin("return lhs" ~ op ~ "rhs;"); } } } unittest { int a = -1; uint b; assert(a > b); // wrong result assert(safeIntegralCmp!">"(a,b) == false); // fixed by promotion long aa = -1; ulong bb; assert(aa > bb); // wrong result assert(safeIntegralCmp!">"(aa,bb) == true); // not staticaly fixable, warning } The widening that happends in the CT branches * static if (isSigned!L && !isSigned!R && R.sizeof < 8) * static if (isSigned!R && !isSigned!L && L.sizeof < 8) could be done in the compiler. --