From 33be07be9e46f15b9556521050356c47460651ee Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 4 Dec 2020 18:00:54 +0100 Subject: [PATCH] fold-const: Don't use build_constructor for non-aggregate types in native_encode_initializer [PR93121] 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. 2020-12-04 Jakub Jelinek PR libstdc++/93121 * fold-const.c (native_encode_initializer): Use build_zero_cst instead of build_constructor. * g++.dg/cpp2a/bit-cast6.C: New test. --- gcc/fold-const.c | 10 ++++++---- gcc/testsuite/g++.dg/cpp2a/bit-cast6.C | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/bit-cast6.C diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e77d74e..1241b13 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8104,11 +8104,12 @@ native_encode_initializer (tree init, unsigned char *ptr, int len, { if (valueinit == -1) { - tree zero = build_constructor (TREE_TYPE (type), NULL); + tree 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 +8256,9 @@ native_encode_initializer (tree init, unsigned char *ptr, int len, { cnt--; field = fld; - val = build_constructor (TREE_TYPE (fld), NULL); - to_free = val; + val = build_zero_cst (TREE_TYPE (fld)); + if (TREE_CODE (val) == CONSTRUCTOR) + to_free = val; } } diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C new file mode 100644 index 0000000..4b70da1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C @@ -0,0 +1,31 @@ +// PR libstd++/93121 +// { dg-do compile { target c++20 } } + +namespace std +{ +enum class byte : unsigned char {}; +template +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(from1); +constexpr unsigned char from2[sizeof (S)]{}; +constexpr auto to2 = std::bit_cast(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{})); -- 2.7.4