[Issue 15805] New: Automatic fix two erroneous integer comparison cases by widening
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Thu Mar 17 05:49:35 PDT 2016
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: nobody at puremagic.com
Reporter: b2.temp at 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.
--
More information about the Digitalmars-d-bugs
mailing list