This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug other/82547] wide_int is not setting overflow properly for large unsigned add/subtract calculations.
- From: "amacleod at redhat dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Mon, 16 Oct 2017 17:18:41 +0000
- Subject: [Bug other/82547] wide_int is not setting overflow properly for large unsigned add/subtract calculations.
- Auto-submitted: auto-generated
- References: <bug-82547-4@http.gcc.gnu.org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82547
--- Comment #1 from Andrew Macleod <amacleod at redhat dot com> ---
On a further note, this appears to be because wide_int tries not to use all the
words is it can sign extend?
the sequence with the issue is:
Mn = wi::min_value (128, UNSIGNED);
Mx = wi::max_value (128, UNSIGNED);
Mxminus2 = wi::sub (Mx, 2, UNSIGNED, &ov);
x = wi::sub (Mn, Mxminus2 , UNSIGNED, &ov2);
fprintf (stderr, "ov %d ov2 %d\n", ov, ov2);
if I look at Mn, I see:
(gdb) p Mn.dump()
[...,0], precision = 128
(gdb) p Mn
$14 = {<wide_int_storage> = {val = {0, 140737488344128, 34794152}, len = 1,
precision = 128}, static is_sign_extended = <optimized out>}
So the precision is 128, but len is set to 1 on a 64 bit host.
Same thing happens for Mx.
Then when wi::sub_large is called, it does the calculation and checks:
if (len * HOST_BITS_PER_WIDE_INT < prec)
{
val[len] = mask0 - mask1 - borrow;
len++;
if (overflow)
*overflow = false;
}
Since both values have a len of 1, and precision is 128, it decides there
cannot be an overflow. It seems to be ignoring that fgact that sign-extension
may exist.
Interestingly, if I remove that entire hunk of code, and and let it do the
general check for overflow which follows, It works as I would expect.
Of course, I have no idea what the side effects of that are...
I leave it in the hands of a wide_int expert.