The following code is accepted by clang 6.0.0 but rejected by gcc 8.2
enum class E {
Good, Bad,
};
struct S {
E e : 2;
int dummy;
};
S f() {
return {E::Good, 100};
}
The GCC complains
error: could not convert '
{Good, 100}
' from '<brace-enclosed initializer list>
' to 'S
'
Which one is correct? Where in the standard talks about this situation?
This should be well-formed and so this is a gcc bug.
We end up at aggregate initialization via [stmt.return]p2 which says:
… A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization ([dcl.init.list]) from the specified initializer list. …
then [dcl.init.list]p3.2 says:
Otherwise, if T is an aggregate, aggregate initialization is performed ([dcl.init.aggr]). …
At this point we may wonder if this is a narrowing conversion and therefore ill-formed but [dcl.init.list]p7 does not have any clauses that cover this case and no other cases in [dcl.init.list] apply to make this ill-formed.
We can see with a similar example which removes enum from the equation but keeps the bit-field shows neither gcc nor clang gives us a narrowing conversion diagnostic, which we expect to be the case, although this similar problem is covered by [dcl.init.list]p7.4 although not ill-formed:
struct S2 {
int e : 2 ;
int dummy ;
} ;
S2 foo( int x ) {
return {x, 100} ;
}
As observed gcc does not seem to have a problem in other contexts i.e.
S f(E e1, int x) {
S s {e1,100} ;
return s;
}
So you do have work-arounds available.