diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-08-17 15:44:29 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-08-17 15:44:29 +0000 |
commit | d7bf39711ad2367458a1705a49839cd4b84c82f8 (patch) | |
tree | ad49e63d9dd8ab6d2e29b2b1e3fe13d5ad890865 | |
parent | 79032e78dc96828b5fc0d42c780503e8bb9b4758 (diff) | |
download | gcc-d7bf39711ad2367458a1705a49839cd4b84c82f8.tar.gz |
PR c++/67104
* constexpr.c (cxx_eval_array_reference): Handle sparse
CONSTRUCTORs.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-5-branch@226940 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 37 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/constexpr-array1.C | 20 |
3 files changed, 60 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 52691aaadeb..6678f1d8381 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2015-08-17 Jason Merrill <jason@redhat.com> + + PR c++/67104 + * constexpr.c (cxx_eval_array_reference): Handle sparse + CONSTRUCTORs. + 2015-08-14 Jason Merrill <jason@redhat.com> PR c++/65974 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index e25072631bd..96855e00773 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1750,7 +1750,38 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, VERIFY_CONSTANT (ary); gcc_unreachable (); } - if (compare_tree_int (index, len) >= 0) + + i = tree_to_shwi (index); + bool found = true; + if (TREE_CODE (ary) == CONSTRUCTOR && len + && (TREE_CODE (CONSTRUCTOR_ELT (ary, len-1)->index) == RANGE_EXPR + || compare_tree_int (CONSTRUCTOR_ELT (ary, len-1)->index, len-1))) + { + /* The last element doesn't match its position in the array; this must be + a sparse array from cxx_eval_store_expression. So iterate. */ + found = false; + vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (ary); + constructor_elt *e; + for (unsigned ix = 0; vec_safe_iterate (v, ix, &e); ++ix) + { + if (TREE_CODE (e->index) == RANGE_EXPR) + { + tree lo = TREE_OPERAND (e->index, 0); + tree hi = TREE_OPERAND (e->index, 1); + if (tree_int_cst_le (lo, index) && tree_int_cst_le (index, hi)) + found = true; + } + else if (tree_int_cst_equal (e->index, index)) + found = true; + if (found) + { + i = ix; + break; + } + } + } + + if (i >= len || !found) { if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary)))) { @@ -1767,14 +1798,14 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, *non_constant_p = true; return t; } - else if (tree_int_cst_lt (index, integer_zero_node)) + else if (i < 0) { if (!ctx->quiet) error ("negative array subscript"); *non_constant_p = true; return t; } - i = tree_to_shwi (index); + if (TREE_CODE (ary) == CONSTRUCTOR) return (*CONSTRUCTOR_ELTS (ary))[i].value; else if (elem_nchars == 1) diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-array1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-array1.C new file mode 100644 index 00000000000..efe4617c9e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-array1.C @@ -0,0 +1,20 @@ +// PR c++/67104 +// { dg-do compile { target c++14 } } + +template <typename T, int N> struct array +{ + constexpr T &operator[](int index) { return data[index]; } + constexpr T operator[](int index) const { return data[index]; } + T data[N]; +}; + +constexpr array<long unsigned, 1001> +make_bottle_count () +{ + array<long unsigned, 1001> a{}; + a[65] = 1; + return a; +} + +constexpr auto bottle_count = make_bottle_count (); +static_assert (bottle_count[65], ""); |