Patchwork [C++] PR 56582

login
register
mail settings
Submitter Paolo Carlini
Date March 10, 2013, 1:46 a.m.
Message ID <513BE5D8.9080202@oracle.com>
Download mbox | patch
Permalink /patch/226405/
State New
Headers show

Comments

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" }
Jason Merrill - March 13, 2013, 3:20 p.m.
OK for 4.8.1.

Jason

Patch

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