https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80733
Bug ID: 80733 Summary: -fstrict-enum ineffective, incorrect -Wtype-limits warning Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- The -fstrict-enums option's effect is documented as Allow the compiler to optimize using the assumption that a value of enumerated type can only be one of the values of the enumeration (as defined in the C++ standard; basically, a value that can be represented in the minimum number of bits needed to represent all the enumerators). The program below shows that GCC doesn't actually perform the optimization. It only appears to constrain the range of values of the type to that of the underlying type, apparently disregarding the TYPE_{MIN,MAX}_VALUE set by the C++ front end in finish_enum_value_list in response to the option. To add insult to injury, the -Wtype-limits warning suggests that GCC actually does perform the optimization (the "not eliminated (bug), warning (bug)" case below). When compiled without -fstrict-enums, the emitted code stays the same. The only thing that changes is that the first warning (on line 16) is not issued. $ cat t.C && gcc -O2 -S -Wall -Wextra -Wpedantic -Wconversion -xc++ -fstrict-enums -fdump-tree-optimized=/dev/stdout t.C | grep -E "(^void (foo|bar)|abort)" enum E { e0, e15 = 15 }; enum __attribute__ ((packed)) F { f0, f15 = 15 }; void foo (E e) { if (e > 15) __builtin_abort (); // not eliminated (bug) } void bar (E e) { if (e > 255) __builtin_abort (); // not eliminated (bug) } void foo (F f) { if (f > 15) __builtin_abort (); // not eliminated (bug), warning (bug) } void bar (F f) { if (f > 255) __builtin_abort (); // eliminated, warning (good) } t.C: In function ‘void foo(F)’: t.C:16:9: warning: comparison is always false due to limited range of data type [-Wtype-limits] if (f > 15) __builtin_abort (); // not eliminated (bug), warning (bug) ~~^~~~ t.C: In function ‘void bar(F)’: t.C:21:9: warning: comparison is always false due to limited range of data type [-Wtype-limits] if (f > 255) __builtin_abort (); // eliminated, warning ~~^~~~~ void foo(E) (E e) __builtin_abort (); void bar(E) (E e) __builtin_abort (); void foo(F) (F f) __builtin_abort (); void bar(F) (F f)