https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82547
Bug ID: 82547 Summary: wide_int is not setting overflow properly for large unsigned add/subtract calculations. Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: other Assignee: unassigned at gcc dot gnu.org Reporter: amacleod at redhat dot com Target Milestone: --- Target: x86_64-pc-linux-gnu Created attachment 42364 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42364&action=edit patch which applied to wide-int.cc shows the bug in the selftests when the compiler is built. I ran into a bug when using a wide_int that is larger than HOST_WIDE_INT. Using an unsigned 128 bit integer fails to set the overflow bit properly when an underflow or overflow occurs in subtraction. I presume wi::add is the same. the calculation is 0 - (MAXINT - 2) It produces the correct value, but does not set the overflow bit properly. I notice all through the wide_int code 'overflow' is set differently depending on whether (sgn == SIGNED). However, in wi::sub_large, it simply says: if (len * HOST_BITS_PER_WIDE_INT < prec) { val[len] = mask0 - mask1 - borrow; len++; if (overflow) *overflow = false; } just always sets it to false regardless of the values. It doesn't actually check anything. Not sure how to reproduce it exactly, so I added some code to the wide_int selftests which show the overflow bits as they are calculated for 32, 64 and 128 bit unsigned values. Attached is a patch to wide-int.cc which performs the calculation in various precisions. It outputs the correct '1' for 32 and 64, but shows that overflow is not set correctly for the 128 bit type. output is: 32 bit ov2 1 64 bit ov2 1 128 bit ov2 0 ov2 should also be 1 in the final test for 128 bit.