[C++] PR 56582

Submitted by Paolo Carlini on March 10, 2013, 1:46 a.m.

Details

Message ID 513BE5D8.9080202@oracle.com
State New
Headers show

Commit Message

Paolo Carlini March 10, 2013, 1:46 a.m.
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.carlini@oracle.com>

	PR c++/56582
	* semantics.c (cxx_eval_array_reference): Check for negative index.

/testsuite
2013-03-09  Paolo Carlini  <paolo.carlini@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)
@@ -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" }

Comments

Jason Merrill March 13, 2013, 3:20 p.m.
OK for 4.8.1.

Jason

Patch hide | download patch | download mbox

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" }