Portability bug in integral conversion
Don
nospam at nospam.com
Mon Jan 17 12:53:45 PST 2011
Andrei Alexandrescu wrote:
> On 1/17/11 2:47 AM, Don wrote:
>> Andrei Alexandrescu wrote:
> [snip]
>> This is a new example of an old issue; it is in no way specific to 64
>> bits.
>> Any expression which contains a size-extension AND a signed<->unsigned
>> implicit conversion is almost always a bug. (unsigned - unsigned leaves
>> the carry flag unknown, so sign extension is impossible).
>>
>> It happens a lot with ushort, ubyte. There are several examples of it in
>> bugzilla. short a=-1; a = a>>>1; is a particularly horrific example.
>
> That doesn't compile. This does:
>
> short a = -1;
> a >>>= 1;
>
> a becomes 32767, which didn't surprise me. Replacing >>>= with >>= keeps
> a unchanged, which I also didn't find surprising.
Aargh, that should have been:
short a = -1;
ushort b = -1;
assert( a == b ); // passes
assert( a >>> 1 == b >>> 1); // fails
Another example:
uint x = 3;
uint y = 8;
ulong z = 0;
ulong a = (z + x) - y;
ulong b = z + (x - y);
assert(a == b); // Thought addition was associative, did you?
'a' only involves size-extension, so it's OK.
But 'b' has a subexpression which sets the carry bit.
Actually it doesn't even need subtraction.
uint x = uint.max;
uint y = uint.max;
ulong z = 0;
ulong a = (z + x) + y;
ulong b = z + (x + y);
assert(a == b); // Still thought addition was associative?
It's the same deal: you shouldn't be able to size-extend, when the state
of the carry flag is unknown.
Once you have performed an operation which can wrap around, you have
discarded the carry bit. This means you have made a commitment to
arithmetic modulo 2^^32.
And then the next addition is arithmetic modulo 2^^64! Which is a
fundamentally different, incompatible operation. It should be a type
mismatch.
Note that because small types get promoted to int, the problem mostly
shows up with uint -> ulong (for smaller types, the carry bit is
retained inside the int).
>> I think it should be forbidden in all cases. I think it can be done with
>> a flag in the range propagation.
>
> Yes, that would be awesome!
>
>
> Andrei
More information about the Digitalmars-d
mailing list