From fd2bfee51ee9b63869652ed0812df1d34aaca093 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 25 Jul 2016 14:32:06 -0400 Subject: [PATCH] PR c++/71972 - constexpr array self-modification * constexpr.c (cxx_eval_array_reference): Handle looking for the value of an element we're currently modifying. From-SVN: r238729 --- gcc/cp/ChangeLog | 6 +++ gcc/cp/constexpr.c | 63 +++++++++++++++------------ gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C | 13 ++++++ 3 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b5d816d..a540d31 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2016-07-25 Jason Merrill + + PR c++/71972 + * constexpr.c (cxx_eval_array_reference): Handle looking for the + value of an element we're currently modifying. + 2016-07-24 Jason Merrill PR c++/71515 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f139260..47fb39b 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2129,42 +2129,49 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, else found = (i < len); - if (!found) + if (found) { - if (TREE_CODE (ary) == CONSTRUCTOR - && CONSTRUCTOR_NO_IMPLICIT_ZERO (ary)) + tree r; + if (TREE_CODE (ary) == CONSTRUCTOR) + r = (*CONSTRUCTOR_ELTS (ary))[i].value; + else if (TREE_CODE (ary) == VECTOR_CST) + r = VECTOR_CST_ELT (ary, i); + else if (elem_nchars == 1) + r = build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))), + TREE_STRING_POINTER (ary)[i]); + else { - /* 'ary' is part of the aggregate initializer we're currently - building; if there's no initializer for this element yet, - that's an error. */ - if (!ctx->quiet) - error ("accessing uninitialized array element"); - *non_constant_p = true; - return t; + tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary))); + r = native_interpret_expr (type, (const unsigned char *) + TREE_STRING_POINTER (ary) + + i * elem_nchars, elem_nchars); } + if (r) + /* Don't VERIFY_CONSTANT here. */ + return r; - /* If it's within the array bounds but doesn't have an explicit - initializer, it's value-initialized. */ - tree val = build_value_init (elem_type, tf_warning_or_error); - return cxx_eval_constant_expression (ctx, val, lval, non_constant_p, - overflow_p); + /* Otherwise the element doesn't have a value yet. */ } - if (TREE_CODE (ary) == CONSTRUCTOR) - return (*CONSTRUCTOR_ELTS (ary))[i].value; - else if (TREE_CODE (ary) == VECTOR_CST) - return VECTOR_CST_ELT (ary, i); - else if (elem_nchars == 1) - return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))), - TREE_STRING_POINTER (ary)[i]); - else + /* Not found. */ + + if (TREE_CODE (ary) == CONSTRUCTOR + && CONSTRUCTOR_NO_IMPLICIT_ZERO (ary)) { - 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); + /* 'ary' is part of the aggregate initializer we're currently + building; if there's no initializer for this element yet, + that's an error. */ + if (!ctx->quiet) + error ("accessing uninitialized array element"); + *non_constant_p = true; + return t; } - /* Don't VERIFY_CONSTANT here. */ + + /* If it's within the array bounds but doesn't have an explicit + initializer, it's value-initialized. */ + tree val = build_value_init (elem_type, tf_warning_or_error); + return cxx_eval_constant_expression (ctx, val, lval, non_constant_p, + overflow_p); } /* Subroutine of cxx_eval_constant_expression. diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C new file mode 100644 index 0000000..3abdd84 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C @@ -0,0 +1,13 @@ +// PR c++/71972 +// { dg-do compile { target c++14 } } + +typedef int size_t; +template struct S { + template constexpr S(const char (&)[M]) : data{} { + data[0] = data[0]; + } + char data[N]; +}; +int main() { + constexpr S<1> s1(""); +} -- 2.7.4