D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4835 - DMD should warn about integer overflow in computed constant
Summary: DMD should warn about integer overflow in computed constant
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86 Linux
: P4 enhancement
Assignee: No Owner
URL:
Keywords: industry, pull
: 13785 (view as issue list)
Depends on:
Blocks:
 
Reported: 2010-09-07 10:09 UTC by Lars Holowko
Modified: 2024-12-13 17:53 UTC (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Lars Holowko 2010-09-07 10:09:23 UTC
I got bitten by this when I wanted to create a 6GB large file to test 64 bit support in std.stdio with dmd 2.048.


The output of:


import std.stdio;

void main(string args[])
{
    long l_dangerous = 1024 * 1024 * 1024 * 6;
    writefln("l_dangerous = 0x%x", l_dangerous);
    writefln("l_dangerous = %s", l_dangerous);
    
    long l_ok = 1024 * 1024 * 1024 * 6L;
    writefln("l_ok = 0x%x", l_ok);
    writefln("l_ok = %s", l_ok);
    return;    
}

is

l_dangerous = 0xffffffff80000000
l_dangerous = -2147483648
l_ok = 0x180000000
l_ok = 6442450944


dmd 2.048 did not issue a warning about the integer overflow (neither with or without -w)
Comment 1 bearophile_hugs 2010-09-07 12:39:13 UTC
I'm asking for overflow detection for years (both at compile-time and run-time).

Again here the C language is better than the D language:

// C code
#include "stdio.h"
int main() {
    long long x = 1024 * 1024 * 1024 * 6;
    printf("%lld\n", x);
    return 0;    
}


GCC 4.3.4 gives:
prog.c: In function ‘main’:
prog.c:3: warning: integer overflow in expression

D compiler is not _practical_ enough yet.
Comment 2 Brad Roberts 2011-02-06 15:38:57 UTC
Mass migration of bugs marked as x86-64 to just x86.  The platform run on isn't what's relevant, it's if the app is a 32 or 64 bit app.
Comment 3 bearophile_hugs 2013-03-26 11:27:23 UTC
An example in Go language:


package main
func main() {
    var x uint32 = 1 << 40
    var y = 1024 * 1024 * 1024 * 6
}


The Go compiler gives the errors:

test.go:3: constant 1099511627776 overflows uint32
test.go:4: constant 6442450944 overflows int
Comment 4 bearophile_hugs 2013-03-26 11:29:45 UTC
Another example in Go:	


package main
func main() {
    var x uint64 = 1 << 90
}


The Go compiler gives the error:

test.go:3: constant 1237940039285380274899124224 overflows uint64
Comment 5 Luís Marques 2013-03-26 11:50:04 UTC
(In reply to comment #4)

For completeness, it also does not have a problem (like in your example) where the initializer of the 64-bit variable is initialized with (what is not obvious) a folded and truncated 32-bit int:

    var x uint64 = 4 * 1024 * 1024 * 1024;
    // x is now 4294967296, not 0.
Comment 6 Walter Bright 2013-03-26 13:14:08 UTC
uint foo() {
    uint x = 1 << 40;
    return 1 << 90;
}

gives:

foo2.d(3): Error: shift by 40 is outside the range 0..31
foo2.d(4): Error: shift by 90 is outside the range 0..31
Comment 7 bearophile_hugs 2013-03-26 15:13:56 UTC
(In reply to comment #6)
> uint foo() {
>     uint x = 1 << 40;
>     return 1 << 90;
> }
> 
> gives:
> 
> foo2.d(3): Error: shift by 40 is outside the range 0..31
> foo2.d(4): Error: shift by 90 is outside the range 0..31

I was aware of that. I have added the 1<<90 example to show the peculiar error message given by Go, that contains 1237940039285380274899124224, that is larger than a ulong.
Comment 9 bearophile_hugs 2013-03-26 19:45:01 UTC
(In reply to comment #8)
> https://github.com/D-Programming-Language/dmd/pull/1803

An error, even :-) So the issue name should be updated.

Thank you Walter. Let's see how this patch goes.
Comment 10 Luís Marques 2013-03-26 20:04:13 UTC
(In reply to comment #9)
> (In reply to comment #8)
> > https://github.com/D-Programming-Language/dmd/pull/1803
> 
> An error, even :-) So the issue name should be updated.
> 
> Thank you Walter. Let's see how this patch goes.

I hope the feedback I provided with being bitten by this corner case helped nudge this issue to the limelight, that way I can feel slightly important ;-). Thanks for addressing it so quickly Walter.

(Also, isn't it strange that this was addressed quicker than in Java, which should have a larger support community, where the issue remains? Go D! (At least it remains with javac 1.6.0_43))
Comment 11 Walter Bright 2013-03-26 22:36:40 UTC
While I disagree with bearophile about doing such checks at runtime, due to the performance cost, doing them at compile time is a whole 'nother story.
Comment 12 Luís Marques 2013-03-26 22:46:13 UTC
(In reply to comment #11)
> While I disagree with bearophile about doing such checks at runtime, due to the
> performance cost, doing them at compile time is a whole 'nother story.

Why don't you make the runtime over/underflow checks opt-in? (compiler option). There's a 0 performance cost that way, both for debug and release, by default, so no performance excuse. Then we can always discuss it later if it should be opt-out for the debug builds.
Comment 13 Walter Bright 2013-03-27 02:38:18 UTC
Because it'll screw things up right and left, for example, address calculations.
Comment 14 bearophile_hugs 2013-03-27 04:00:40 UTC
(In reply to comment #11)
> While I disagree with bearophile about doing such checks at runtime, due to the
> performance cost,

A feature of LLVM 3.3, it seems those costs are not too much large for C language:

http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation

See:
-fsanitize=signed-integer-overflow
-fsanitize=integer

More info:
http://embed.cs.utah.edu/ioc/
Comment 15 Luís Marques 2013-03-27 09:00:14 UTC
(In reply to comment #13)
> Because it'll screw things up right and left, for example, address
> calculations.

Walter, what do you mean, screw? Is that a limitation of the dmd backend, or are you arguing that it is problematic in general? LLVM implements it, as bearophile points out...
Comment 16 Walter Bright 2013-03-28 00:39:03 UTC
(In reply to comment #15)
> Walter, what do you mean, screw? Is that a limitation of the dmd backend, or
> are you arguing that it is problematic in general? LLVM implements it, as
> bearophile points out...

Consider all the addressing modes used - they are all adds, with no overflow checks. Secondly, they all rely on wraparound (overflow) arithmetic, after all, that is how subtraction is done.
Comment 17 bearophile_hugs 2014-11-27 15:10:00 UTC
*** Issue 13785 has been marked as a duplicate of this issue. ***
Comment 18 dlangBugzillaToGithub 2024-12-13 17:53:17 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/18298

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB