https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122811
Bug ID: 122811
Summary: Bit-field widths are not correctly handled in
conditional operators
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: luigighiron at gmail dot com
Target Milestone: ---
The following program demonstrates when GCC does not correctly handle bit-field
widths in conditional operators:
#include<iostream>
int main(){
struct{unsigned u:1;}u{};
auto a=(0?throw 0:u.u)-1;
std::cout<<(a<0)<<'\n';//should print 1, GCC prints 0
unsigned char b{0?throw 0:u.u};//incorrectly considered narrowing
auto c=(1?u.u:u.u)-1;
std::cout<<(c<0)<<'\n';//should print 1, GCC prints 0
unsigned char d{1?u.u:u.u};//incorrectly considered narrowing
auto e=(1?u.u:0)-1;
std::cout<<(e<0)<<'\n';//should print 1, GCC prints 0
}
The expressions (0?throw 0:u.u) and (1?u.u:u.u) should intuitively both be
equivalent to u.u, but GCC appears to forget about the widths of the bit-fields
in these cases and assumes that they have the full range of unsigned. In the
expression (1?u.u:0) the usual arithmetic conversions should be applied because
u.u and 0 have different types, but GCC appears to forget about the width of
the bit-field in this case and treats it the same as a non-bit-field. Other
contexts that use the usual arithmetic conversions work fine, e.g. u.u+0 has
the correct type.
Clang gets (1?u.u:0) correct but handles the other two expressions incorrectly.
MSVC has the same behavior as GCC in this program, but it entirely fails to
implement promotion and narrowing checks with bit-fields correctly. For example
+u.u in MSVC has type unsigned, and unsigned char f{u.u}; is considered
narrowing.
The standard also requires the resulting expression of a conditional operator
to be a bit-field when both the second and third operands have the same value
category and type, even if one is a bit-field and the other is not, or both are
bit-fields but of different widths. The standard does not clearly define what
the widths in those cases should be, but using the maximum of the widths seems
like the most reasonable choice (the width of a non-bit-field is the width of
its type in this context). See also CWG3134, it may be worth waiting for that
to be resolved before taking any action in these cases.