https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108128
Bug ID: 108128 Summary: missing -Wshift-overflow warning Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: vincent-gcc at vinc17 dot net Target Milestone: --- Consider the following C program: #include <stdio.h> enum { A = 1 << 31 }; int main (void) { printf ("%d\n", A); printf ("%d\n", 1 << 31); printf ("%d\n", 2 << 31); return 0; } In C, the 3 shifts have undefined behavior. The GCC 12 man page says -Wshift-overflow=n These options control warnings about left shift overflows. -Wshift-overflow=1 This is the warning level of -Wshift-overflow and is enabled by default in C99 and C++11 modes (and newer). This warning level does not warn about left-shifting 1 into the sign bit. (However, in C, such an overflow is still rejected in contexts where an integer constant expression is required.) No warning is emitted in C++20 mode (and newer), as signed left shifts always wrap. -Wshift-overflow=2 This warning level also warns about left-shifting 1 into the sign bit, unless C++14 mode (or newer) is active. Nothing is said about the default, but I assume that this should be -Wshift-overflow=2 in C because undefined behavior should be warned. But with gcc-12 (Debian 12.2.0-10) 12.2.0, I get a warning only for 2 << 31. cventin:~> /usr/bin/gcc-12 -std=c99 tst.c -o tst tst.c: In function ‘main’: tst.c:7:21: warning: result of ‘2 << 31’ requires 34 bits to represent, but ‘in’ only has 32 bits [-Wshift-overflow=] 7 | printf ("%d\n", 2 << 31); | ^~ BTW, according to the man page, gcc should warn on "enum { A = 1 << 31 };" even with -Wshift-overflow=1, but it doesn't. This is actually required by the standard as constraint 6.6#4 is violated (as the evaluation is not defined). With the UB sanitizer (-fsanitize=undefined), running the program gives as expected: -2147483648 tst.c:6:21: runtime error: left shift of 1 by 31 places cannot be represented in type 'int' -2147483648 tst.c:7:21: runtime error: left shift of 2 by 31 places cannot be represented in type 'int' 0 Note that the sanitizer does not emit an error for "enum { A = 1 << 31 };" since the issue occurs only at compilation (thus a warning is particularly important).