From: Nathan Sidwell Date: Thu, 8 Dec 2016 19:27:32 +0000 (+0000) Subject: re PR c++/78551 (Internal compiler error with constexpr initialization of union) X-Git-Tag: releases/gcc-5.5.0~655 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b2873465cf6a8bf304c87603ac39fd4e48a6931;p=thirdparty%2Fgcc.git re PR c++/78551 (Internal compiler error with constexpr initialization of union) PR c++/78551 * constexpr.c (extract_string_elt): New. Broken out of ... (cxx_eval_array_reference): ... here. Call it. (cxx_eval_store_expression): Convert init by STRING_CST into CONSTRUCTOR, if needed. PR c++/78551 * g++.dg/cpp1y/pr78551.C: New. From-SVN: r243457 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 86ba33098743..0fbbe2118bae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2016-12-08 Nathan Sidwell + + PR c++/78551 + * constexpr.c (extract_string_elt): New. Broken out of ... + (cxx_eval_array_reference): ... here. Call it. + (cxx_eval_store_expression): Convert init by STRING_CST into + CONSTRUCTOR, if needed. + 2016-08-05 Nathan Sidwell PR c++/68724 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 50e2338a13fb..e558e69066ae 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1829,6 +1829,27 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert = false) } +/* Extract element INDEX consisting of CHARS_PER_ELT chars from + STRING_CST STRING. */ + +static tree +extract_string_elt (tree string, unsigned chars_per_elt, unsigned index) +{ + tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (string))); + tree r; + + if (chars_per_elt == 1) + r = build_int_cst (type, TREE_STRING_POINTER (string)[index]); + else + { + const unsigned char *ptr + = ((const unsigned char *)TREE_STRING_POINTER (string) + + index * chars_per_elt); + r = native_interpret_expr (type, ptr, chars_per_elt); + } + return r; +} + /* Subroutine of cxx_eval_constant_expression. Attempt to reduce a reference to an array slot. */ @@ -1913,16 +1934,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, if (TREE_CODE (ary) == CONSTRUCTOR) return (*CONSTRUCTOR_ELTS (ary))[i].value; - else if (elem_nchars == 1) - return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))), - TREE_STRING_POINTER (ary)[i]); else - { - tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary))); - return native_interpret_expr (type, (const unsigned char *) - TREE_STRING_POINTER (ary) - + i * elem_nchars, elem_nchars); - } + return extract_string_elt (ary, elem_nchars, i); /* Don't VERIFY_CONSTANT here. */ } @@ -2838,6 +2851,34 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, *valp = build_constructor (type, NULL); CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = true; } + else if (TREE_CODE (*valp) == STRING_CST) + { + /* An array was initialized with a string constant, and now + we're writing into one of its elements. Explode the + single initialization into a set of element + initializations. */ + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); + + tree string = *valp; + tree elt_type = TREE_TYPE (type); + unsigned chars_per_elt = (TYPE_PRECISION (elt_type) + / TYPE_PRECISION (char_type_node)); + unsigned num_elts = TREE_STRING_LENGTH (string) / chars_per_elt; + tree ary_ctor = build_constructor (type, NULL); + + vec_safe_reserve (CONSTRUCTOR_ELTS (ary_ctor), num_elts); + for (unsigned ix = 0; ix != num_elts; ix++) + { + constructor_elt elt = + { + build_int_cst (size_type_node, ix), + extract_string_elt (string, chars_per_elt, ix) + }; + CONSTRUCTOR_ELTS (ary_ctor)->quick_push (elt); + } + + *valp = ary_ctor; + } enum tree_code code = TREE_CODE (type); type = refs->pop(); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f60246814545..c560323c275f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-12-08 Nathan Sidwell + + PR c++/78551 + * g++.dg/cpp1y/pr78551.C: New. + 2016-12-07 Thomas Preud'homme Backport from mainline diff --git a/gcc/testsuite/g++.dg/cpp1y/pr78551.C b/gcc/testsuite/g++.dg/cpp1y/pr78551.C new file mode 100644 index 000000000000..a549fff4fefe --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr78551.C @@ -0,0 +1,32 @@ +// { dg-do compile { target c++14 } } + +// PR c++/78551 ICE in constexpr evaluation overwriting array +// intialized by string constant. + +constexpr char Foo (char x, int ix) +{ + char d[4] = "012"; + d[0] = x; + return d[ix]; +} + +static const char a = Foo ('a', 1); +static const char b = Foo ('a', 0); + +static_assert (a == '1', ""); +static_assert (b == 'a', ""); + +struct A { + union { + long s; + char d[4]; + }; + constexpr A (char x) + : d("012") + { d[0] = x; } +}; + +static constexpr A c{'a'}; + +static_assert (c.d[0] == 'a', ""); +static_assert (c.d[1] == '1', "");