https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89175
Bug ID: 89175 Summary: gcc's conversion code from double to unsigned int handles overflows incorrectly on x86-64 Product: gcc Version: 8.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: david.monni...@univ-grenoble-alpes.fr Target Milestone: --- $ gcc-8 --version gcc-8 (Ubuntu 8.2.0-1ubuntu2~18.04) 8.2.0 Compile the following: unsigned conversion(double x) { return (unsigned) x; } The compiled code performs incorrectly if the rounded value of x lies in the range of the 'signed long long' but not in the range of 'unsigned int': it should signal a floating-point "invalid operation" exception (as per C99 F.4) but it does not. Explanation: The generated code performs the conversion using cvttsd2siq %xmm0, %rax which raises "invalid operation"if the result does not fit into a 64-bit signed number. It suggest that, unless -ffast-math or similar option is set, the result of this conversion should be checked for being in the correct range for unsigned, and if not, the exception should be flagged. The following code demonstrates the issue: it should display invalid=1 but does not (it does display invalid=1 if compiled under CompCert, which performs a range check). #include <inttypes.h> #include <stdint.h> #include <stdio.h> #include <fenv.h> int main() { double x = 1E10; uint32_t u=x; printf("x=%lf u=%" PRIu32 " %" PRIx32 " equal=%d invalid=%x\n", x, u, u, u==x, fetestexcept(FE_INVALID | FE_OVERFLOW)); double y= 0; y = y / y; printf("invalid2=%x\n", fetestexcept(FE_INVALID | FE_OVERFLOW)); return 0; }