Summary: | bitfield temporaries > 32-bits have wrong type | ||
---|---|---|---|
Product: | gcc | Reporter: | Greg Miller <gnu> |
Component: | c++ | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | NEW --- | ||
Severity: | normal | CC: | webrown.cpp |
Priority: | P3 | Keywords: | rejects-valid, wrong-code |
Version: | 7.3.1 | ||
Target Milestone: | --- | ||
See Also: |
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70733 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87547 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95009 |
||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2018-10-08 00:00:00 | |
Bug Depends on: | 95009 | ||
Bug Blocks: | 94058 |
Description
Greg Miller
2018-02-22 15:07:32 UTC
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. |