Bug 41425

Summary: switch with enums doesn't work
Product: gcc Reporter: André Wöbbeking <Woebbeking>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: critical CC: gcc-bugs, jason
Priority: P3    
Version: 4.4.1   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:
Attachments: testcase

Description André Wöbbeking 2009-09-21 12:17:02 UTC
If I cast an int to the enum type all values outside the enum triggers the first case-statement.

The number of enum values is important. It must be a power of 2.

This works in GCC 4.3.4.
Comment 1 André Wöbbeking 2009-09-21 12:19:29 UTC
Created attachment 18622 [details]
testcase
Comment 2 André Wöbbeking 2009-09-21 12:21:32 UTC
g++ case.cpp is sufficient to reproduce this.
Comment 3 Paolo Carlini 2009-09-21 12:41:31 UTC
As far as I can see, you are triggering undefined behavior. Per 5.2.9/7: "A value of integral or enumeration type can be explicitly converted to an enumeration type. The value is unchanged if the original value is within the range of the enumeration values (7.2). Otherwise, the resulting enumeration value is unspecified."
Comment 4 Richard Biener 2009-09-21 12:44:29 UTC
In C++ an enum type only has the minimum number of bits that is required to
store all its values, thus 1 in your case.  So (foo)5 is a truncation.
Comment 5 André Wöbbeking 2009-09-21 12:53:58 UTC
Paolo, but std::cout << static_cast<foo>(i); prints 5, so it's not the conversion but the switch statement which is "broken".

Richard, if it's only truncation shouldn't case B be triggered?
Comment 6 Richard Biener 2009-09-21 13:08:33 UTC
Switch assembly is optimized if you handle all valid cases (which you do) into
if (i != 0)
  case B
else
  case A
Comment 7 Andreas Schwab 2009-09-21 14:25:11 UTC
(In reply to comment #3)
> As far as I can see, you are triggering undefined behavior.

There is a big difference between undefined and unspecified behaviour.  With unspecified behaviour the implementation must chose a consistent behaviour, although it does not have to document which one it choses.
Comment 8 Paolo Carlini 2009-09-21 14:45:48 UTC
Agreed, unspecified, as the actual citation says.
Comment 9 André Wöbbeking 2009-09-21 16:46:03 UTC
So it's ok to change the behavior in a minor release?
Comment 10 Richard Biener 2009-09-22 11:43:35 UTC
Yes, as part of a wrong-code fix.
Comment 11 Jason Merrill 2010-05-04 04:48:10 UTC
In G++ 4.6 the confusing optimization will only be performed with -fstrict-enums.