[C++ Patch] PR 56582

Paolo Carlini paolo.carlini@oracle.com
Sun Mar 10 01:46:00 GMT 2013


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.

////////////////////
-------------- next part --------------
/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.
-------------- next part --------------
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" }
-------------- next part --------------
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" }


More information about the Gcc-patches mailing list