https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |diagnostic Ever confirmed|0 |1 Status|UNCONFIRMED |NEW Last reconfirmed| |2024-02-09 --- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> --- If a1 and a2 are const then GCC also notices the undefined overflow: <source>: In function 'int main()': <source>:18:13: warning: integer overflow in expression of type 'int' results in '-131071' [-Woverflow] 18 | if ((a1 * a2) > a3) { | ~~~^~~~ <source>:18:19: warning: comparison of integer expressions of different signedness: 'int' and 'uint64_t' {aka 'long unsigned int'} [-Wsign-compare] 18 | if ((a1 * a2) > a3) { | ~~~~~~~~~~^~~~ I don't know why the -Wsign-compare warning is only given when we've detected the overflow. The types are always the same, whether the values are known to overflow or not. I assume what's happening is that GCC assumes integer promotion from uint16_t to int is value preserving and so we get two positive values, and therefore comparison with an unsigned value is fine - there are no negative values involved and so it doesn't matter that we're comparing int with unsigned long. But of course that's not true here. We have two positive ints but their product overflows to produce a negative int. I guess we're also assuming no overflow happens, because that would be undefined and we assume no UB. When the values are constant we can tell the overflow happens, and no longer assume it doesn't happen.