← Back to context

Comment by jcranmer

2 hours ago

Having been involved in the WG14 discussions on this topic:

The issue is that there is a contingent of users who complains about cases where the return dynamically can't be hit but that isn't obvious statically. Consider something like this:

  int do_something(enum meow koala) {
    switch (koala) {
    case enum_val_1: return 5;
    case enum_val_2: return 3;
    /* etc., covering all the enum values */
    }
  }

Should this be required to diagnose? That's the sticking point.

There may be differences between C and C++ here (and I worked with C++ more recently than C), but: if that enum doesn't specify an underlying type it would be UB to have a value that isn't in the "member list" of the enum. In that case it should be possible to determine if all cases are covered.

If an underlying type is specified, then it should error since it is legal to have those values (unless the whole range of the underlying type is covered by the cases.

Again, that is what would be sensible from a C++ perspective, I don't know if C differs here.

EDIT: Also, and now I'm talking with my Rust user hat on: it is better to not have pointless UB. Yes some is needed to practically allow for optimisation. But C and C++ had a lot of UB that doesn't really help with making your code faster, such as this.

  • I don't think your C++ comment is true, otherwise you wouldn't be allowed to OR together C enums. I think the restriction is on values wider than the underlying type, where the underlying type is always wide enough to support any representable bit pattern.

  • > Again, that is what would be sensible from a C++ perspective, I don't know if C differs here.

    In C it is not UB for an enum to have an integer value that does not correspond to any listed enumeration constants.