summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2015-08-17 15:44:29 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2015-08-17 15:44:29 +0000
commitd7bf39711ad2367458a1705a49839cd4b84c82f8 (patch)
treead49e63d9dd8ab6d2e29b2b1e3fe13d5ad890865
parent79032e78dc96828b5fc0d42c780503e8bb9b4758 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/constexpr.c37
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-array1.C20
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], "");