Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cpp] wierd addition results upon int overflow #8879

Open
RealyUniqueName opened this issue Oct 15, 2019 · 6 comments
Open

[cpp] wierd addition results upon int overflow #8879

RealyUniqueName opened this issue Oct 15, 2019 · 6 comments
Labels
platform-cpp Everything related to CPP / C++
Milestone

Comments

@RealyUniqueName
Copy link
Member

class Main {
    static var tmp:Any;
    public static function main():Void {
        tmp = new Int32(-2147483648) + new Int32(-1);
    }
}

abstract Int32(Int) {
    public inline function new(v:Int) {
        this = v;
    }

    public inline function toInt():Int {
        return this;
    }

    @:op(A + B) inline function addition(b:Int32):Int32 {
        var result = this + b.toInt();
        trace(result);      // <----------- 2147483647
        trace(result >= 0); // <----------- false
        if((this < 0 && b.toInt() < 0 && result >= 0) || (this > 0 && b.toInt() > 0 && result <= 0)) {
            throw '($this + ${b.toInt()}) overflows Int32';
        }
        return new Int32(result);
    }
}
$ haxe -main Main -dce full -cpp bin/cpp -D analyzer-optimize && ./bin/cpp/Main
Main.hx:19: 2147483647
Main.hx:20: false

Making any one of the following changes fixes it:

  1. Remove inline accessor from addition function;
  2. Remove if expression;
  3. Disable analyzer-optimize.
@RealyUniqueName RealyUniqueName added platform-cpp Everything related to CPP / C++ feature-analyzer Static analyzer labels Oct 15, 2019
@RealyUniqueName RealyUniqueName added this to the Release 4.0 milestone Oct 15, 2019
@RealyUniqueName
Copy link
Member Author

Ok, I've managed to reduce

class Main {
    static var b:Int = -1;
    public static function main():Void {
        var result = -2147483648 + b;
        trace(result);
        trace(result >= 0);
    }
}
$ haxe -main Main -cpp bin && ./bin/Main
Main.hx:5: 2147483647
Main.hx:6: false

Analyzer is not involved. It's something about int overflow in cpp.
@hughsando could you please take a look?

@RealyUniqueName RealyUniqueName changed the title [analyzer][cpp] wierd addition results with analyzer-optimize [cpp] wierd addition results with analyzer-optimize Oct 16, 2019
@RealyUniqueName RealyUniqueName removed the feature-analyzer Static analyzer label Oct 16, 2019
@hughsando
Copy link
Member

What system are you on?
I added untyped __cpp__("printf(\"res: %08x\\n\",{0})", result); and on windows got:
res: 7fffffff
Main.hx:6: 2147483647
Main.hx:7: true

Which I what I'm expecting. A different compiler may be doing something different with the LessThan template, which is where I would look next.

var result = haxe.Int64.ofInt(-2147483648) + b; also works

@RealyUniqueName
Copy link
Member Author

I'm on linux.
Yeah, adding any manipulations with result makes it to behave correctly. E.g. string concatenation "fixes" it:

class Main {
    static var b:Int = -1;
    public static function main():Void {
        var result = -2147483648 + b;
        trace('' + result);  //2147483647
        trace(result >= 0);  //true
    }
}

Here is my system:

$ g++ --version
g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

@RealyUniqueName RealyUniqueName changed the title [cpp] wierd addition results with analyzer-optimize [cpp] wierd addition results upon int overflow Oct 18, 2019
@RealyUniqueName
Copy link
Member Author

Given it only happens for a single int constant -2147483648 we can add a field static var minInt = -2147483648 to Std module (for example) and generate an access to that field instead of -2147483648 constant.
It's not pretty, but it fixes the issue.
What do you think, @hughsando ?

@RealyUniqueName
Copy link
Member Author

Wild guess:
It's an optimization in g++: "Whatever integer you add to -2147483648 the result is always negative, because max integer is 2147483647. So I'm just gonna optimize 'result >= 0' into 'false'".

@Simn Simn modified the milestones: Release 4.0, Release 4.1 Oct 29, 2019
@Simn Simn modified the milestones: Release 4.1, Release 4.2 Feb 19, 2020
@ntrf
Copy link

ntrf commented Mar 13, 2021

This is normal for GCC. There is a bunch of questions on SO about that. In C++ standard overflow of signed integers is considered an UB. There is a documented flag for GCC called -fwrapv, that applies integer overflow rules of unsigned integers (which are required to wrap by the standard) to signed values as well. See https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html. If you're aiming for maximizing compatibility with other platforms, like Java, you might want to consider adding it to gcc flags in a build.xml.
Honestly, i can't expect people to still want UB or traps on overflow. It was a common practice in scientific research back in the early days (MIPS and SPARC even had special trap instructions for that).

@Simn Simn modified the milestones: Release 4.3, Later Mar 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform-cpp Everything related to CPP / C++
Projects
None yet
Development

No branches or pull requests

4 participants