Hi!
The following testcase is rejected, because when trying to encode a zeroing
CONSTRUCTOR, the code was using build_constructor to build initializers for
the elements but when recursing the function handles CONSTRUCTOR only for
aggregate types.
The following patch fixes that by using build_zero_cst instead for
non-aggregates. Another option would be add handling CONSTRUCTOR for
non-aggregates in native_encode_initializer. Or we can do both, I guess
the middle-end generally doesn't like CONSTRUCTORs for scalar variables, but
am not 100% sure if the FE doesn't produce those sometimes.
Ok for trunk if it passes bootstrap/regtest?
So far it passed
make check-c++-all RUNTESTFLAGS='--target_board=unix\{-m32,-m64\}
dg.exp=bit-cast*'
2020-12-04 Jakub Jelinek <[email protected]>
PR libstd++/93121
* fold-const.c (native_encode_initializer): Use build_constructor
only for aggregate types, otherwise use build_zero_cst.
* g++.dg/cpp2a/bit-cast6.C: New test.
--- gcc/fold-const.c.jj 2020-12-03 15:37:25.795342398 +0100
+++ gcc/fold-const.c 2020-12-04 11:25:54.949421799 +0100
@@ -8104,11 +8104,16 @@ native_encode_initializer (tree init, un
{
if (valueinit == -1)
{
- tree zero = build_constructor (TREE_TYPE (type), NULL);
+ tree zero;
+ if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
+ zero = build_constructor (TREE_TYPE (type), NULL);
+ else
+ zero = build_zero_cst (TREE_TYPE (type));
r = native_encode_initializer (zero, ptr + curpos,
fieldsize, 0,
mask + curpos);
- ggc_free (zero);
+ if (TREE_CODE (zero) == CONSTRUCTOR)
+ ggc_free (zero);
if (!r)
return 0;
valueinit = curpos;
@@ -8255,8 +8260,13 @@ native_encode_initializer (tree init, un
{
cnt--;
field = fld;
- val = build_constructor (TREE_TYPE (fld), NULL);
- to_free = val;
+ if (AGGREGATE_TYPE_P (TREE_TYPE (fld)))
+ {
+ val = build_constructor (TREE_TYPE (fld), NULL);
+ to_free = val;
+ }
+ else
+ val = build_zero_cst (TREE_TYPE (fld));
}
}
--- gcc/testsuite/g++.dg/cpp2a/bit-cast6.C.jj 2020-12-04 11:36:12.963456560
+0100
+++ gcc/testsuite/g++.dg/cpp2a/bit-cast6.C 2020-12-04 11:35:59.227611364
+0100
@@ -0,0 +1,31 @@
+// PR libstd++/93121
+// { dg-do compile { target c++20 } }
+
+namespace std
+{
+enum class byte : unsigned char {};
+template <typename To, typename From>
+constexpr To
+bit_cast (const From &from)
+{
+ return __builtin_bit_cast (To, from);
+}
+}
+
+struct S { unsigned short s[2]; };
+constexpr std::byte from1[sizeof (S)]{};
+constexpr auto to1 = std::bit_cast<S>(from1);
+constexpr unsigned char from2[sizeof (S)]{};
+constexpr auto to2 = std::bit_cast<S>(from2);
+
+constexpr bool
+cmp (const S &s1, const S &s2)
+{
+ for (int i = 0; i < sizeof (s1.s) / sizeof (s1.s[0]); i++)
+ if (s1.s[i] != s2.s[i])
+ return false;
+ return true;
+}
+
+static_assert (cmp (to1, S{}));
+static_assert (cmp (to2, S{}));
Jakub