(Disclaimer: I'm not a compiler guy, so I may accidentally use the wrong terminology) Example: https://godbolt.org/g/brhTMw #include <iostream> struct A { long x : 32; long y : 33; }; int main() { A a; std::cout << a.x; // OK std::cout << a.y; // OK std::cout << +a.x; // OK std::cout << +a.y; // BREAKS on gcc } The problem is the last line. The type of the expression `+a.y` is 'long int:33', which is not a type that operator<<() has an overload for. The type of the expression `a.y` is 'long int' and so op<<() has an overload and works. This issue seems to be affected by (a) The size of the bit field; <= 32 bits works, > 32 bits breaks. (b) Whether the bitfield is used in an expression producing a temporary; >32-bit size AND a temporary breaks, <= 32-bit size and an lvalue works. I confirmed this behavior on x86-64 gcc trunk using godbolt.org. (link again: https://godbolt.org/g/brhTMw)
The issue is not related to iostream. So, here's perhaps a simpler reproduction example that may focus more on the issue at hand. Link: https://godbolt.org/g/vA2rPN struct A { long x : 32; long y : 33; }; void F(int) {} void F(long) {} template <typename T> void F(T) = delete; int main() { A a; F(a.x); // Calls F(long) F(+a.x); // Calls F(int) F(a.y); // Calls F(long) F(+a.y); // error: use of deleted function 'void F(T) [with T = long int:33]' } Here we can see that the type of the expression `+a.y` is `long int:33`, which I suspect is a problem. I think the type of that expression should be `long int`.
See also bug 70733, another bug with these types being user-exposed for bit-fields for C++. For C++ (unlike C), the existence of these types internally in the compiler should never be user-visible, because bit-field width is explicitly not part of the type for C++.
This seems to be related to the following rule in [conv.prom]: > A prvalue for an integral bit-field (10.3.10) can be converted to a prvalue of type int if int can represent all the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can represent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. But the fact no promotion applies should mean the type is unchanged, so is just long, not long:33.
There is most likely a missing call to unlowered_expr_type somewhere, most likely in finish_unary_op_expr.