Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can switch default statement be optimised out for enum

If I have a switch statement that handles all enum cases explicitly, is the compiler allowed to optimise away the default case statement?

enum MyEnum {
 ZERO = 0,
 ONE = 1,
 TWO = 2,
 THREE = 3,
};

bool foo(MyEnum e) {
 switch(e) {
 case ZERO:
 case ONE:
 case TWO:
 case THREE:
  return true;
 default:    // Could a compiler optimise this away?
  return false;
 }
}

Cpp Reference says regarding enums (emphasis mine):

Values of integer, floating-point, and enumeration types can be converted by static_cast or explicit cast, to any enumeration type. If the underlying type is not fixed and the source value is out of range, the behavior is undefined. (The source value, as converted to the enumeration's underlying type if floating-point, is in range if it would fit in the smallest bit field large enough to hold all enumerators of the target enumeration.) Otherwise, the result is the same as the result of implicit conversion to the underlying type.

Note that the value after such conversion may not necessarily equal any of the named enumerators defined for the enumeration.

Which indicates it would be allowed to optimise out the default statement in the above example since the underlying type is not fixed and every 2-bit value is specified (though maybe you would need to include negative values to -4).

However, it is not clear if this also applies to fixed type enums or enum classes.


In practice, GCC, clang, and MSVC do not assume that the enum is one of the defined values. (Godbolt with full optimization enabled like -O3 -std=c++20.)

Is that a missed optimization, or is the standard saying that if the implementation picks int as the underlying type (even though you didn't specify) then any int value is legal?

CppReference shows an example under the paragraph quoted:

enum access_t { read = 1, write = 2, exec = 4 }; 
 // enumerators: 1, 2, 4 range: 0..7
access_t y = static_cast<access_t>(8);   // undefined behavior since CWG1766

That makes it clear that "range" is tied to the named enumerator values, not the full width of any integer type. Assuming that cppreference example is an accurate reflection of the ISO standard, of course, that implies that explicit or implicit conversion can't legally produce an enum object with a value that isn't accounted for.

like image 524
dast99 Avatar asked May 28 '26 21:05

dast99


1 Answers

Yes, I guess in theory they could. There is no standard-sanctioned way to reach the default.

As mentioned on the cppreference page, the standard essentially says in [dcl.enum]/8 that the possible values of an enumeration without fixed underlying type are zero to, exclusive, the smallest power of two able to fit all of the declared enumerator's values. Casting from the underlying type to values outside this range via static_cast is explicitly undefined behavior.

There may be some room to argue about memcpy/std::bit_cast from the underlying type to the enumeration, but I don't think that works out either. The linked standard passage seems to define the values of the enumeration exclusively, so it is not possible for object representations to represent any additional values (assuming they are valid object representations of the enumeration to begin with).

The standard currently doesn't even guarantee same representation as the underlying type for the values that the enumeration does have (although that may be a defect).

However, it wouldn't be compatible with C where all values of the underlying type are allowed. Since the smallest possible underlying type is char which is at least 8 bits wide, it will always be possible to reach the default in C.

So I don't expect any compiler to consider the default unreachable without additional knowledge of the argument's range.

Enumerations with fixed underlying type (which includes all enum class) are specified differently and guaranteed to support all values of the underlying type, as is the case in C for all enumerations.

like image 176
user17732522 Avatar answered May 31 '26 13:05

user17732522



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!