| Issue |
169197
|
| Summary |
Conditional operators that result in bit-fields do not correctly preserve the width
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
Halalaluyafail3
|
The following program demonstrates the issue:
```cpp
#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, Clang 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, Clang prints 0
unsigned char d{1?u.u:u.u};//incorrectly considered narrowing
}
```
The two expressions `(0?throw 0:u.u)` and `(1?u.u:u.u)` should intuitively both be equivalent to `u.u`, but Clang appears to forget about the widths of the bit-fields in these cases and assumes that they have the full range of unsigned. #14181 also still exists and makes it impossible to use any non-constant condition here.
GCC has the same issues with propagating the bit-field with in these two expressions https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122811. MSVC too, but because it fails to implement promotion and narrowing checks with bit-fields correctly. For example with MSVC `+u.u` has the type unsigned and `unsigned char e{u.u};` is considered narrowing.
See also [CWG3134](https://github.com/cplusplus/CWG/issues/820). The standard doesn't clearly define the width in the cases where bit-field and non-bit-field expressions are used together, or two bit-field expressions of different widths are used together. The most reasonable behavior in these cases seems to be to take the maximum of the two widths, where the width of a non-bit-field is the width of its type. Though it may be worth waiting for the issue to be resolved before making a decision.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs