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

Reply via email to