public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993)
@ 2018-01-24 23:50 Jakub Jelinek
  2018-01-25 20:23 ` Martin Sebor
  0 siblings, 1 reply; 6+ messages in thread
From: Jakub Jelinek @ 2018-01-24 23:50 UTC (permalink / raw)
  To: Jason Merrill, Nathan Sidwell; +Cc: gcc-patches

Hi!

In constexpr evaluation of array references for arrays with unknown bounds,
we need to diagnose out of bounds accesses, but really don't know the bounds
at compile time, right now GCC will see nelts as error_mark_node + 1 and
will not consider them a constant expression at all.
From the clang commit message it seems that CWG is leaning towards allowing
&array_with_unknown_bound[0] and array_with_unknown_bound, but disallowing
any other indexes (i.e. assume the array could have zero elements).
The following patch implements that.  Bootstrapped/regtested on x86_64-linux
and i686-linux, ok for trunk?

2018-01-24  Jakub Jelinek  <jakub@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 ("array subscript value %qE used on 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 ("array subscript value %qE used on 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 "array subscript value '1' used on 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 "array subscript value '1' used on 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 "array subscript value '1' used on 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

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-01-31 18:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-24 23:50 [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993) Jakub Jelinek
2018-01-25 20:23 ` Martin Sebor
2018-01-25 23:13   ` Jakub Jelinek
2018-01-31 16:31     ` Jason Merrill
2018-01-31 18:16       ` Jakub Jelinek
2018-01-31 18:36         ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).