https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127247
Bug ID: 127247
Summary: UB free bit_cast is not optimized away to simpler
assembly
Product: gcc
Version: 16.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: uchanahome8 at gmail dot com
Target Milestone: ---
Hi, consider the following example: https://godbolt.org/z/Kc8c6Gjon. Here is
the code:
```
#include <bit>
#include <array>
#include <algorithm>
struct B {
double value{1};
};
struct C {
double value{2};
};
struct A {
B b;
C c;
};
constexpr double h(const A& a, int index)
{
const auto bytes = std::bit_cast<std::array<std::byte, sizeof(A)>>(a);
const auto offset = index * sizeof(double);
std::array<std::byte, sizeof(double)> target;
std::copy_n(bytes.begin() + offset, sizeof(double), target.begin());
return std::bit_cast<double>(target);
}
static_assert([] {
A a{};
if (h(a, 0) != 1) return false;
if (h(a, 1) != 2) return false;
return true;
}());
// non-constexpr so that I can see the generated assembly
double f(const A& a, int index) {
return h(a, index);
}
```
Above example is a reproducer for the problem which I faced in a large project,
which was accessing members of a class using an enum where:
- Enums were defined with X-macros.
- Class member names are defined with X-macros.
- Class member types were dependent on enum name where we select among multiple
wrappers of "double" -> B and C in above.
- Size of class = number of X-macro/enum entries * sizeof(double).
- All members are public.
Now the problem is that I wrote UB-free code using std::bit_cast (above) but
the generated assembly is not optimizing away the unnecessary copies. Whereas,
writing the following code is generating optimal assembly but is not UB-free
(static_assert fails): https://godbolt.org/z/hKEqE5zsY
```
constexpr double h(const A& a, int index)
{
const double* address = &a.b.value;
return *(address + index);
}
```
Am I missing something due to which bit_cast copies are not properly optimized
away here? I am not even doing unaligned accesses here.