www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 15805] New: Automatic fix two erroneous integer comparison

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 puremagic.com
          Reporter: b2.temp 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
}
Mar 17 2016