Bug 3147 – Incorrect value range propagation for addition

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Linux
Creation time
2009-07-06T22:50:00Z
Last change time
2015-06-09T01:27:14Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
andrei
Blocks
2809, 5225

Comments

Comment #0 by andrei — 2009-07-06T22:50:37Z
This code doesn't compile and it should: void main() { byte x, y, z; short a = x+y; } Although the manifest type of x+y is int, the actual range of x+y, regardless of the values of x and y, is -byte.min-byte.min to byte.max+byte.max. That range fits properly in a short so the compiler should let the code go through.
Comment #1 by sandford — 2009-07-07T08:07:25Z
Additionally, propagation doesn't work for byte, ubyte, bool and char. for operations + * - / % >> Also byte x,y; short z; z = x<<1; // Error: cannot implicitly convert expression (cast(int)x << 1) of type int to byte z = x << y; // compiles // Repeat for >>> Also ubyte x,y=10; ubyte z; z = -y; // compiles Inconsistancies: byte x,y; short z; z += x; //compiles, z = z + x doesn't x += y; //compiles, x = x + y doesn't x++; //compiles, x = x+1, doesn't ++x; //compiles, x = x+1, doesn't x = x + 1; // Error: cannot implicitly convert expression (cast(int)x + 1) of type int to byte // Again repeat for the other operations/type combos also byte[] x, y, z; z[] = x[] * z[]; //compiles // repeat for other array operation and type combos
Comment #2 by dfj1esp02 — 2010-11-16T13:40:52Z
Some asserts for modulus and shifts --- byte b; short s; int i; long l; static assert(is(typeof(s%b)==byte)); static assert(is(typeof(i%s)==short)); static assert(is(typeof(b<<b)==int)); static assert(is(typeof(b>>i)==byte)); static assert(is(typeof(b>>>b)==byte)); static assert(is(typeof(b>>l)==byte)); ---
Comment #3 by andrei — 2010-11-16T13:54:16Z
The point is not to ascribe the smallest static type to the result. That would break compatibility with C in many ways. All that happens is the compiler tracks the range of the expression statically while using the same typing rules as C.
Comment #4 by dfj1esp02 — 2010-11-16T14:01:34Z
--- l = cast(int)(s%b); l = cast(short)(s%b); --- What's the difference?
Comment #5 by dfj1esp02 — 2010-11-16T14:22:01Z
In any case --- static if(__traits(compiles, s=b+b)) { static assert(__traits(compiles, b=s%b)); static assert(__traits(compiles, s=s>>b)); static assert(__traits(compiles, s=s>>>b)); } ---
Comment #6 by dfj1esp02 — 2010-11-16T22:03:08Z
There should be ints in shift asserts --- static if(__traits(compiles, s=b+b)) { static assert(__traits(compiles, b=i%b)); static assert(__traits(compiles, b=b>>i)); static assert(__traits(compiles, b=b>>>i)); } ---
Comment #7 by kennytm — 2011-06-12T11:05:38Z
Comment #8 by kennytm — 2011-06-12T11:06:25Z
*** Issue 6000 has been marked as a duplicate of this issue. ***
Comment #9 by kennytm — 2011-06-12T11:07:25Z
*** Issue 5225 has been marked as a duplicate of this issue. ***
Comment #10 by yebblies — 2011-06-16T01:01:05Z
*** Issue 5528 has been marked as a duplicate of this issue. ***
Comment #11 by bearophile_hugs — 2011-06-16T05:30:16Z
This example was in bug 5528: void main() { uint i = 10; ubyte x1 = i % ubyte.max; ulong l = 10; uint x2 = l % uint.max; }
Comment #12 by bugzilla — 2011-06-27T14:45:08Z