Hi,
in cxx_eval_array_reference we don't check whether the subscript is
negative and we end up either ICEing or emitting wrong code. Adding the
check seems trivial, but I'm not sure if there is something more subtle
to the issue which I'm missing.
Also note that in principle we could have somewhat neater code but, as
far as I can see, we would end up doing more comparisons (see the _alt
patch).
Tested x86_64-linux.
Thanks,
Paolo.
////////////////////
/cp
2013-03-09 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/56582
* semantics.c (cxx_eval_array_reference): Check for negative index.
/testsuite
2013-03-09 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/56582
* g++.dg/cpp0x/constexpr-array5.C: New.
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 196574)
+++ cp/semantics.c (working copy)
@@ -7007,6 +7007,13 @@ cxx_eval_array_reference (const constexpr_call *ca
*non_constant_p = true;
return t;
}
+ else if (tree_int_cst_lt (index, integer_zero_node))
+ {
+ if (!allow_non_constant)
+ error ("negative array subscript");
+ *non_constant_p = true;
+ return t;
+ }
i = tree_low_cst (index, 0);
if (TREE_CODE (ary) == CONSTRUCTOR)
return (*CONSTRUCTOR_ELTS (ary))[i].value;
Index: testsuite/g++.dg/cpp0x/constexpr-array5.C
===================================================================
--- testsuite/g++.dg/cpp0x/constexpr-array5.C (revision 0)
+++ testsuite/g++.dg/cpp0x/constexpr-array5.C (working copy)
@@ -0,0 +1,9 @@
+// PR c++/56582
+// { dg-do compile { target c++11 } }
+
+// Reliable ICE
+constexpr int n[3] = {};
+constexpr int k = n[-1]; // { dg-error "negative" }
+
+// Some random byte
+constexpr char c = "foo"[-1000]; // { dg-error "negative" }
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 196574)
+++ cp/semantics.c (working copy)
@@ -6990,23 +6990,23 @@ cxx_eval_array_reference (const constexpr_call *ca
VERIFY_CONSTANT (ary);
gcc_unreachable ();
}
- if (compare_tree_int (index, len) >= 0)
+ if (tree_int_cst_lt (index, integer_zero_node)
+ || !tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
{
- if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
- {
- /* 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 (call, val,
- allow_non_constant, addr,
- non_constant_p, overflow_p);
- }
-
if (!allow_non_constant)
error ("array subscript out of bound");
*non_constant_p = true;
return t;
}
+ if (compare_tree_int (index, len) >= 0)
+ {
+ /* 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 (call, val,
+ allow_non_constant, addr,
+ non_constant_p, overflow_p);
+ }
i = tree_low_cst (index, 0);
if (TREE_CODE (ary) == CONSTRUCTOR)
return (*CONSTRUCTOR_ELTS (ary))[i].value;
Index: testsuite/g++.dg/cpp0x/constexpr-array5.C
===================================================================
--- testsuite/g++.dg/cpp0x/constexpr-array5.C (revision 0)
+++ testsuite/g++.dg/cpp0x/constexpr-array5.C (working copy)
@@ -0,0 +1,9 @@
+// PR c++/56582
+// { dg-do compile { target c++11 } }
+
+// Reliable ICE
+constexpr int n[3] = {};
+constexpr int k = n[-1]; // { dg-error "out of bound" }
+
+// Some random byte
+constexpr char c = "foo"[-1000]; // { dg-error "out of bound" }