On Wed, Jan 31, 2018 at 11:02:36AM -0500, Jason Merrill wrote:
> > In this case I was just extending existing warning and wanted
> > consistency with that.  Both can be changed in a GCC9 follow-up,
> > or if Jason/Nathan want it now, even for GCC8, sure.

So, do you want %qE as in the patch or %E?  Note, sidx might
actually not be a INTEGER_CST (as we only verify_constant it which
allows all kinds of expressions), though usually it will be.
E.g. the
      if (!tree_fits_shwi_p (index)
          || (i = tree_to_shwi (index)) < 0)
        {
          diag_array_subscript (ctx, ary, index);
case will call it if index is some reduced_constant_expression_p
which is not INTEGER_CST, initializer_constant_valid_p* has lots
of cases, sure not all apply to integral types.

> > Well, even zero subscript is wrong if lval is false, i.e. a[0] + 1
> > rather than e.g. &a[0].  So we'd need to have another wordings
> > for the case when the index is zero.
> 
> But if lval is false we want the value of the array, and if we know
> the value we know the bounds, so that shouldn't be needed.

You're right, when dereferencing it we'll error already earlier,
because the array of unknown bounds can't be constexpr.

I think the " with unknown bounds" part still might be useful to users,
it can be seen in the type as [], but it might take some time to the users
to figure out that is the reason why we disallow it.

So like this?

2018-01-31  Jakub Jelinek  <ja...@redhat.com>

        PR c++/83993
        * constexpr.c (diag_array_subscript): Emit different diagnostics
        if TYPE_DOMAIN (arraytype) is NULL.
        (cxx_eval_array_reference, cxx_eval_store_expression): For arrays
        with NULL TYPE_DOMAIN use size_zero_node as nelts.

        * g++.dg/init/pr83993-1.C: New test.
        * g++.dg/cpp0x/pr83993.C: New test.

--- gcc/cp/constexpr.c.jj       2018-01-19 23:34:04.897278768 +0100
+++ gcc/cp/constexpr.c  2018-01-24 13:38:40.572913190 +0100
@@ -2270,13 +2270,20 @@ diag_array_subscript (const constexpr_ct
       tree sidx = fold_convert (ssizetype, index);
       if (DECL_P (array))
        {
-         error ("array subscript value %qE is outside the bounds "
-                "of array %qD of type %qT", sidx, array, arraytype);
+         if (TYPE_DOMAIN (arraytype))
+           error ("array subscript value %qE is outside the bounds "
+                  "of array %qD of type %qT", sidx, array, arraytype);
+         else
+           error ("non-zero array subscript %qE is used with array %qD of "
+                  "type %qT with unknown bounds", sidx, array, arraytype);
          inform (DECL_SOURCE_LOCATION (array), "declared here");
        }
-      else
+      else if (TYPE_DOMAIN (arraytype))
        error ("array subscript value %qE is outside the bounds "
               "of array type %qT", sidx, arraytype);
+      else
+       error ("non-zero array subscript %qE is used with array of type %qT "
+              "with unknown bounds", sidx, arraytype);
     }
 }
 
@@ -2361,7 +2368,12 @@ cxx_eval_array_reference (const constexp
 
   tree nelts;
   if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
-    nelts = array_type_nelts_top (TREE_TYPE (ary));
+    {
+      if (TYPE_DOMAIN (TREE_TYPE (ary)))
+       nelts = array_type_nelts_top (TREE_TYPE (ary));
+      else
+       nelts = size_zero_node;
+    }
   else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
     nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
   else
@@ -3439,7 +3451,12 @@ cxx_eval_store_expression (const constex
          tree nelts, ary;
          ary = TREE_OPERAND (probe, 0);
          if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
-           nelts = array_type_nelts_top (TREE_TYPE (ary));
+           {
+             if (TYPE_DOMAIN (TREE_TYPE (ary)))
+               nelts = array_type_nelts_top (TREE_TYPE (ary));
+             else
+               nelts = size_zero_node;
+           }
          else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
            nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
          else
--- gcc/testsuite/g++.dg/init/pr83993-1.C.jj    2018-01-24 13:45:43.430864528 
+0100
+++ gcc/testsuite/g++.dg/init/pr83993-1.C       2018-01-24 13:44:59.352869530 
+0100
@@ -0,0 +1,11 @@
+// PR c++/83993
+// { dg-do compile }
+
+extern const int a[];
+const int *const b = &a[0];
+
+int
+foo ()
+{
+  return b[0];
+}
--- gcc/testsuite/g++.dg/cpp0x/pr83993.C.jj     2018-01-24 14:09:01.846716177 
+0100
+++ gcc/testsuite/g++.dg/cpp0x/pr83993.C        2018-01-24 14:08:41.246718212 
+0100
@@ -0,0 +1,49 @@
+// PR c++/83993
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern const int a[];
+const int b[5] = { 1, 2, 3, 4, 5 };
+extern const int c[4];
+constexpr const int *d = &a[0];
+constexpr const int *d2 = a;
+constexpr const int *e = &a[1];                // { dg-error "non-zero array 
subscript '1' is used with array 'a' of type 'const int \\\[\\\]' with unknown 
bounds" }
+constexpr const int *f = &b[0];
+constexpr const int *f2 = b;
+constexpr const int *g = &b[5];
+constexpr const int *h = &b[6];                // { dg-error "array subscript 
value '6' is outside the bounds of array 'b' of type 'const int \\\[5\\\]'" }
+constexpr const int *i = &c[0];
+constexpr const int *i2 = c;
+constexpr const int *j = &c[4];
+constexpr const int *k = &c[5];                // { dg-error "array subscript 
value '5' is outside the bounds of array 'c' of type 'const int \\\[4\\\]'" }
+extern const int l[];
+
+void
+foo ()
+{
+  extern const int l[3];
+  constexpr const int *m = &l[0];
+  constexpr const int *m2 = l;
+  constexpr const int *n = &l[1];
+  static_assert (m == m2, "");
+}
+
+constexpr const int *m = &l[0];
+constexpr const int *m2 = l;
+constexpr const int *n = &l[1];                // { dg-error "non-zero array 
subscript '1' is used with array 'l' of type 'const int \\\[\\\]' with unknown 
bounds" }
+static_assert (d == d2 && f == f2 && i == i2 && m == m2, "");
+const int o[] = { 1, 2 };
+constexpr const int *p = &o[0];
+constexpr const int *p2 = o;
+constexpr const int *q = &o[2];
+constexpr const int *r = &o[3];                // { dg-error "array subscript 
value '3' is outside the bounds of array 'o' of type 'const int \\\[2\\\]'" }
+struct S { char a; char b[]; } s;
+constexpr const char *t = &s.b[0];
+constexpr const char *t2 = s.b;
+constexpr const char *u = &s.b[1];     // { dg-error "non-zero array subscript 
'1' is used with array of type 'char \\\[\\\]' with unknown bounds" }
+struct V { int a; };
+extern V v[];
+constexpr V *w = &v[0];
+constexpr V *w2 = v;
+constexpr int *x = &v[0].a;
+constexpr int y = a[0];                        // { dg-error "the value of 'a' 
is not usable in a constant expression" }


        Jakub

Reply via email to