diff mbox

[C++] Diagnose constexpr store to ARRAY_REF with negative index (PR c++/79655)

Message ID 20170221164226.GT1849@tucnak
State New
Headers show

Commit Message

Jakub Jelinek Feb. 21, 2017, 4:42 p.m. UTC
Hi!

The following patch fixes ICE where we try to store a[-1].  The problem
is that we don't check the bounds first and then later on we assert it
is not negative.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2017-02-21  Jakub Jelinek  <jakub@redhat.com>

	PR c++/79655
	* constexpr.c (cxx_eval_array_reference): Diagnose negative subscript.

	* g++.dg/cpp1y/constexpr-79655.C: New test.

 
	Jakub

Comments

Jason Merrill Feb. 21, 2017, 5:54 p.m. UTC | #1
OK.

On Tue, Feb 21, 2017 at 8:42 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> The following patch fixes ICE where we try to store a[-1].  The problem
> is that we don't check the bounds first and then later on we assert it
> is not negative.
>
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
> trunk?
>
> 2017-02-21  Jakub Jelinek  <jakub@redhat.com>
>
>         PR c++/79655
>         * constexpr.c (cxx_eval_array_reference): Diagnose negative subscript.
>
>         * g++.dg/cpp1y/constexpr-79655.C: New test.
>
> --- gcc/cp/constexpr.c.jj       2017-02-17 18:29:21.000000000 +0100
> +++ gcc/cp/constexpr.c  2017-02-21 13:49:06.530261975 +0100
> @@ -2263,9 +2263,10 @@ cxx_eval_array_reference (const constexp
>    nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
>                                         overflow_p);
>    VERIFY_CONSTANT (nelts);
> -  if (lval
> -      ? !tree_int_cst_le (index, nelts)
> -      : !tree_int_cst_lt (index, nelts))
> +  if ((lval
> +       ? !tree_int_cst_le (index, nelts)
> +       : !tree_int_cst_lt (index, nelts))
> +      || tree_int_cst_sgn (index) < 0)
>      {
>        diag_array_subscript (ctx, ary, index);
>        *non_constant_p = true;
> --- gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C.jj     2017-02-21 14:14:37.245395108 +0100
> +++ gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C        2017-02-21 14:14:07.000000000 +0100
> @@ -0,0 +1,18 @@
> +// PR c++/79655
> +// { dg-do compile { target c++14 } }
> +
> +constexpr int
> +foo (int x, int y)
> +{
> +  int a[6] = { 1, 2, 3, 4, 5, 6 };
> +  a[x] = 0;
> +  return a[y];
> +}
> +
> +constexpr int b = foo (0, -1); // { dg-error "is outside the bounds" }
> +constexpr int c = foo (0, 6);  // { dg-error "is outside the bounds" }
> +constexpr int d = foo (6, 0);  // { dg-error "is outside the bounds" }
> +constexpr int e = foo (-1, 0); // { dg-error "is outside the bounds" }
> +static_assert (foo (5, 5) == 0, "");
> +static_assert (foo (4, 5) == 6, "");
> +static_assert (foo (5, 4) == 5, "");
>
>         Jakub
diff mbox

Patch

--- gcc/cp/constexpr.c.jj	2017-02-17 18:29:21.000000000 +0100
+++ gcc/cp/constexpr.c	2017-02-21 13:49:06.530261975 +0100
@@ -2263,9 +2263,10 @@  cxx_eval_array_reference (const constexp
   nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
 					overflow_p);
   VERIFY_CONSTANT (nelts);
-  if (lval
-      ? !tree_int_cst_le (index, nelts)
-      : !tree_int_cst_lt (index, nelts))
+  if ((lval
+       ? !tree_int_cst_le (index, nelts)
+       : !tree_int_cst_lt (index, nelts))
+      || tree_int_cst_sgn (index) < 0)
     {
       diag_array_subscript (ctx, ary, index);
       *non_constant_p = true;
--- gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C.jj	2017-02-21 14:14:37.245395108 +0100
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C	2017-02-21 14:14:07.000000000 +0100
@@ -0,0 +1,18 @@ 
+// PR c++/79655
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo (int x, int y)
+{
+  int a[6] = { 1, 2, 3, 4, 5, 6 };
+  a[x] = 0;
+  return a[y];
+}
+
+constexpr int b = foo (0, -1);	// { dg-error "is outside the bounds" }
+constexpr int c = foo (0, 6);	// { dg-error "is outside the bounds" }
+constexpr int d = foo (6, 0);	// { dg-error "is outside the bounds" }
+constexpr int e = foo (-1, 0);	// { dg-error "is outside the bounds" }
+static_assert (foo (5, 5) == 0, "");
+static_assert (foo (4, 5) == 6, "");
+static_assert (foo (5, 4) == 5, "");