This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] c++/67376 Comparison with pointer to past-the-end, of array fails inside constant expression


+           /* Avoid folding references to struct members at offset
0 to
+          prevent tests like '&ptr->firstmember == 0' from getting
+          eliminated.  When ptr is null, although the -> expression
+          is strictly speaking invalid, GCC retains it as a matter
+          of QoI.  See PR c/44555. */
+           && (TREE_CODE (op0) != ADDR_EXPR
+           || TREE_CODE (TREE_OPERAND (op0, 0)) != COMPONENT_REF
+           || compare_tree_int (DECL_FIELD_OFFSET ((TREE_OPERAND
+                           (TREE_OPERAND (op0, 0), 1))), 0))

Can we look at offset/bitpos here rather than examine the tree structure
of op0?  get_inner_reference already examined it for us.

Good suggestion, thanks!

But you're still examining the tree structure:

+           && (TREE_CODE (op0) != ADDR_EXPR
+           || TREE_CODE (TREE_OPERAND (op0, 0)) != COMPONENT_REF
+           || bitpos0 != 0)

Here instead of looking at op0 we can check (offset0 == NULL_TREE &&
bitpos0 != 0), which indicates a constant non-zero offset.

+           && TREE_CODE (arg1) == INTEGER_CST
+           && integer_zerop (arg1))

And here you don't need the check for INTEGER_CST.

I've updated the patch to simplify the tests.

I have to confess I don't yet find it straightforward to tell
exactly which tests are essential to avoid an ICE and which
ones can safely be simplified.

Martin
PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
	of array fails inside constant expression
PR c++/70170 - [6 regression] bogus not a constant expression error comparing
	pointer to array to null
PR c++/70172 - incorrect reinterpret_cast from integer to pointer error
	on invalid constexpr initialization
PR c++/70228 - insufficient detail in diagnostics for a constexpr out of bounds
	array subscript

gcc/testsuite/ChangeLog:
2016-03-31  Martin Sebor  <msebor@redhat.com>

	PR c++/67376
	PR c++/70170
	PR c++/70172
	PR c++/70228
	* g++.dg/cpp0x/constexpr-array-ptr10.C: New test.
	* g++.dg/cpp0x/constexpr-array-ptr9.C: New test.
	* g++.dg/cpp0x/constexpr-nullptr-1.C: New test.
	* g++.dg/cpp0x/constexpr-array5.C: Adjust text of expected diagnostic.
	* g++.dg/cpp0x/constexpr-string.C: Same.
	* g++.dg/cpp0x/constexpr-wstring2.C: Same.
	* g++.dg/cpp0x/pr65398.C: Same.
	* g++.dg/ext/constexpr-vla1.C: Same.
	* g++.dg/ext/constexpr-vla2.C: Same.
	* g++.dg/ext/constexpr-vla3.C: Same.
	* g++.dg/ubsan/pr63956.C: Same.

gcc/cp/ChangeLog:
2016-03-31  Martin Sebor  <msebor@redhat.com>

	PR c++/67376
	PR c++/70170
	PR c++/70172
	PR c++/70228
	* constexpr.c (diag_array_subscript): New function.
	(cxx_eval_array_reference): Detect out of bounds array indices.

gcc/ChangeLog:
2016-03-31  Martin Sebor  <msebor@redhat.com>

	PR c++/67376
	* fold-const.c (maybe_nonzero_address): New function.
	(fold_comparison): Call it.  Fold equality and relational
	expressions involving null pointers.
	(tree_single_nonzero_warnv_p): Call maybe_nonzero_address.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 8ea7111..5d1b8b3 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1837,6 +1837,30 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert = false)
   return -1;
 }
 
+/* Under the control of CTX, issue a detailed diagnostic for
+   an out-of-bounds subscript INDEX into the expression ARRAY.  */
+
+static void
+diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
+{
+  if (!ctx->quiet)
+    {
+      tree arraytype = TREE_TYPE (array);
+
+      /* Convert the unsigned array subscript to a signed integer to avoid
+	 printing huge numbers for small negative values.  */
+      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);
+	  inform (DECL_SOURCE_LOCATION (array), "declared here");
+	}
+      else
+	error ("array subscript value %qE is outside the bounds "
+	       "of array type %qT", sidx, arraytype);
+    }
+}
 
 /* Subroutine of cxx_eval_constant_expression.
    Attempt to reduce a reference to an array slot.  */
@@ -1885,8 +1909,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
   if (!tree_fits_shwi_p (index)
       || (i = tree_to_shwi (index)) < 0)
     {
-      if (!ctx->quiet)
-	error ("negative array subscript");
+      diag_array_subscript (ctx, ary, index);
       *non_constant_p = true;
       return t;
     }
@@ -1898,8 +1921,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
   VERIFY_CONSTANT (nelts);
   if (!tree_int_cst_lt (index, nelts))
     {
-      if (!ctx->quiet)
-	error ("array subscript out of bound");
+      diag_array_subscript (ctx, ary, index);
       *non_constant_p = true;
       return t;
     }
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 44fe2a2..eb66143 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8336,6 +8336,20 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
   return total.to_uhwi () > (unsigned HOST_WIDE_INT) size;
 }
 
+/* Return a positive integer when the symbol DECL is known to have
+   a nonzero address, zero when it's known not to (e.g., it's a weak
+   symbol), and a negative integer when the symbol is not yet in the
+   symbol table and so whether or not its address is zero is unknown.  */
+static int
+maybe_nonzero_address (tree decl)
+{
+  if (DECL_P (decl) && decl_in_symtab_p (decl))
+    if (struct symtab_node *symbol = symtab_node::get_create (decl))
+      return symbol->nonzero_address ();
+
+  return -1;
+}
+
 /* Subroutine of fold_binary.  This routine performs all of the
    transformations that are common to the equality/inequality
    operators (EQ_EXPR and NE_EXPR) and the ordering operators
@@ -8636,6 +8650,39 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
 	    base1 = build_fold_addr_expr_loc (loc, base1);
 	  return fold_build2_loc (loc, code, type, base0, base1);
 	}
+      /* Comparison between an ordinary (non-weak) symbol and a null
+	 pointer can be eliminated since such symbols must have a non
+	 null address.  In C, relational expressions between pointers
+	 to objects and null pointers are undefined.  The results
+	 below follow the C++ rules with the additional property that
+	 every object pointer compares greater than a null pointer.
+      */
+      else if (DECL_P (base0)
+	       && maybe_nonzero_address (base0) > 0
+	       /* Avoid folding references to struct members at offset 0 to
+		  prevent tests like '&ptr->firstmember == 0' from getting
+		  eliminated.  When ptr is null, although the -> expression
+		  is strictly speaking invalid, GCC retains it as a matter
+		  of QoI.  See PR c/44555. */
+	       && (offset0 == NULL_TREE && bitpos0 != 0)
+	       /* The caller guarantees that when one of the arguments is
+		  constant (i.e., null in this case) it is second.  */
+	       && integer_zerop (arg1))
+	{
+	  switch (code)
+	    {
+	    case EQ_EXPR:
+	    case LE_EXPR:
+	    case LT_EXPR:
+	      return boolean_false_node;
+	    case GE_EXPR:
+	    case GT_EXPR:
+	    case NE_EXPR:
+	      return boolean_true_node;
+	    default:
+	      gcc_unreachable ();
+	    }
+	}
     }
 
   /* Transform comparisons of the form X +- C1 CMP Y +- C2 to
@@ -13506,16 +13553,9 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
 	/* For objects in symbol table check if we know they are non-zero.
 	   Don't do anything for variables and functions before symtab is built;
 	   it is quite possible that they will be declared weak later.  */
-	if (DECL_P (base) && decl_in_symtab_p (base))
-	  {
-	    struct symtab_node *symbol;
-
-	    symbol = symtab_node::get_create (base);
-	    if (symbol)
-	      return symbol->nonzero_address ();
-	    else
-	      return false;
-	  }
+	int nonzero_addr = maybe_nonzero_address (base);
+	if (nonzero_addr >= 0)
+	  return nonzero_addr;
 
 	/* Function local objects are never NULL.  */
 	if (DECL_P (base)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
new file mode 100644
index 0000000..f75b3c3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
@@ -0,0 +1,112 @@
+// PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
+//                of array fails inside constant expression
+// This test verifies the aspect of the bug raised in comment #10,
+// specifically comparing pointers to null.  The basic regression test
+// is in g++.dg/cpp0x/constexpr-67376.C.
+// Note also that while the description of the bug talks about pointers
+// pointing past the end of arrays but the prolem is more general than
+// that and involves all constexpr object pointers.
+
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wall -Wextra" }
+
+namespace A {
+
+extern int i;
+
+constexpr int *p0 = &i;
+
+constexpr bool b0  = p0;        // { dg-warning "address of .A::i." }
+constexpr bool b1  = p0 == 0;   // { dg-warning "address of .A::i." }
+constexpr bool b2  = p0 != 0;   // { dg-warning "address of .A::i." }
+constexpr bool b3  = p0 <  0;   // { dg-warning "ordered comparison" }
+constexpr bool b4  = p0 <= 0;   // { dg-warning "ordered comparison" }
+constexpr bool b5  = p0 >  0;   // { dg-warning "ordered comparison" }
+constexpr bool b6  = p0 >= 0;   // { dg-warning "ordered comparison" }
+
+constexpr bool b7  = !p0;       // { dg-warning "address of .A::i." }
+constexpr bool b8  = 0 == p0;   // { dg-warning "address of .A::i." }
+constexpr bool b9  = 0 != p0;   // { dg-warning "address of .A::i." }
+constexpr bool b10 = 0 <  p0;   // { dg-warning "ordered comparison" }
+constexpr bool b11 = 0 <= p0;   // { dg-warning "ordered comparison" }
+constexpr bool b12 = 0 >  p0;   // { dg-warning "ordered comparison" }
+constexpr bool b13 = 0 >= p0;   // { dg-warning "ordered comparison" }
+
+}
+
+namespace B {
+
+// PR c++/70172 - incorrect reinterpret_cast from integer to pointer
+// error on invalid constexpr initialization
+
+struct S { int a, b[1]; } s;
+
+constexpr S *p0 = &s;
+
+constexpr int *q0 = p0->b;      // { dg-bogus "reinterpret_cast from integer to pointer" }
+
+}
+
+namespace WeakRefTest1 {
+
+extern __attribute__ ((weak)) int i;
+
+constexpr int *p0 = &i;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wextra"
+// Suppress warning: ordered comparison of pointer with integer zero
+
+constexpr bool b0  = p0;        // { dg-error "not a constant expression" }
+constexpr bool b1  = p0 == 0;   // { dg-error "not a constant expression" }
+constexpr bool b2  = p0 != 0;   // { dg-error "not a constant expression" }
+constexpr bool b4  = p0 <= 0;   // { dg-error "not a constant expression" }
+constexpr bool b5  = p0 >  0;   // { dg-error "not a constant expression" }
+
+constexpr bool b7  = !p0;       // { dg-error "not a constant expression" }
+constexpr bool b8  = 0 == p0;   // { dg-error "not a constant expression" }
+constexpr bool b9  = 0 != p0;   // { dg-error "not a constant expression" }
+constexpr bool b10 = 0 <  p0;   // { dg-error "not a constant expression" }
+constexpr bool b13 = 0 >= p0;   // { dg-error "not a constant expression" }
+
+// The following are accepted as constant expressions due to bug c++/70196.
+constexpr bool b3  = p0 <  0;
+constexpr bool b6  = p0 >= 0;
+constexpr bool b11 = 0 <= p0;
+constexpr bool b12 = 0 >  p0;
+
+#pragma GCC diagnostic pop
+
+}
+
+namespace WeakRefTest2 {
+
+extern __attribute__ ((weak)) int i;
+
+constexpr int *p1 = &i + 1;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wextra"
+// Suppress warning: ordered comparison of pointer with integer zero
+
+constexpr bool b0  = p1;        // { dg-error "not a constant expression" }
+constexpr bool b1  = p1 == 0;   // { dg-error "not a constant expression" }
+constexpr bool b2  = p1 != 0;   // { dg-error "not a constant expression" }
+constexpr bool b4  = p1 <= 0;   // { dg-error "not a constant expression" }
+constexpr bool b5  = p1 >  0;   // { dg-error "not a constant expression" }
+
+constexpr bool b7  = !p1;       // { dg-error "not a constant expression" }
+constexpr bool b8  = 0 == p1;   // { dg-error "not a constant expression" }
+constexpr bool b9  = 0 != p1;   // { dg-error "not a constant expression" }
+constexpr bool b10 = 0 <  p1;   // { dg-error "not a constant expression" }
+constexpr bool b13 = 0 >= p1;   // { dg-error "not a constant expression" }
+
+// The following are accepted as constant expressions due to bug c++/70196.
+// constexpr bool b3  = p1 <  0;
+// constexpr bool b6  = p1 >= 0;
+// constexpr bool b11 = 0 <= p1;
+// constexpr bool b12 = 0 >  p1;
+
+#pragma GCC diagnostic pop
+
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr9.C
new file mode 100644
index 0000000..f0250cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr9.C
@@ -0,0 +1,57 @@
+// PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
+//     of array fails inside constant expression
+// { dg-do compile { target c++11 } }
+
+int a [2];
+
+constexpr const int* pa[] = {
+  a,
+  a + 0,
+  a + 1,
+  a + 2,
+  &a [0],
+  &a [0] + 0,
+  &a [0] + 1,
+  &a [0] + 2,
+  &a [1],
+  &a [1] - 1,
+  &a [1] + 0,
+  &a [1] + 1,
+  &a [2] - 2,
+  &a [2] - 1,
+  &a [2] + 0
+};
+
+#define Assert(e) static_assert ((e), #e)
+
+Assert (!(a == 0));
+Assert (!(a == (int*)0));
+Assert (!(a == nullptr));
+
+Assert (a != 0);
+Assert (a != (int*)0);
+Assert (a != nullptr);
+
+Assert (!(0 == a));
+Assert (!((int*)0 == a));
+Assert (!(nullptr == a));
+
+Assert (0 != a);
+Assert ((int*)0 != a);
+Assert (nullptr != a);
+
+bool constexpr test_eq (unsigned inx)
+{
+  return inx ? pa [inx - 1] == 0 && 0 == pa [inx - 1]
+    && test_eq (inx - 1) : pa [inx] == 0 && 0 == pa [inx];
+}
+
+Assert (!test_eq (sizeof pa / sizeof *pa));
+
+bool constexpr test_ne (unsigned inx)
+{
+  return inx ? pa [inx - 1] != 0 && 0 != pa [inx - 1]
+    && test_ne (inx - 1) : pa [inx] != 0 && 0 != pa [inx];
+}
+
+Assert (test_ne (sizeof pa / sizeof *pa));
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C
index 4605b4b..00dfd6d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C
@@ -3,7 +3,7 @@
 
 // Reliable ICE
 constexpr int n[3] = {};
-constexpr int k = n[-1];            // { dg-error "negative" }
+constexpr int k = n[-1];            // { dg-error "array subscript" }
 
 // Some random byte
-constexpr char c = "foo"[-1000];    // { dg-error "negative" }
+constexpr char c = "foo"[-1000];    // { dg-error "array subscript" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C
new file mode 100644
index 0000000..420a04b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C
@@ -0,0 +1,125 @@
+// Verify the correctness of folding relational expressions involving
+// pointers to array elements and struct data members and null pointers.
+// Although the C semantics of relational expressions are only defined
+// for pointers to objects, C++ makes them well-defined when
+// (nullptr < p) yields true.  See the discussion of the patch for
+// c++/67376 on gcc-patches for additional background.
+
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-optimized" }
+
+// Runtime assert.  Used for potentially invalid expressions.
+#define RA(e)  ((e) ? (void)0 : __builtin_abort ())
+
+// Static assert.  Used for valid core constant expressions.
+#define SA(e)  static_assert ((e), #e)
+
+void test_first_array_element ()
+{
+  static constexpr int a[] = { 0 };
+  constexpr const int *null = 0;
+  constexpr const int *pi = a;
+
+  // The following are valid constant expressions since in &*pi
+  // the '&*' "cancel each other out."
+  SA (!(null == &*pi));
+  SA ( (null != &*pi));
+
+  // The validity of the relational expressions involving null
+  // pointers in a constexpr context is questionable.  Use a run
+  // time assertion to verify these.
+  RA ( (null <  &*pi));
+  RA ( (null <= &*pi));
+  RA (!(null >  &*pi));
+  RA (!(null >= &*pi));
+
+  SA (!(&*pi == null));
+  SA ( (&*pi != null));
+  RA (!(&*pi <  null));
+  RA (!(&*pi <= null));
+  RA ( (&*pi >  null));
+  RA ( (&*pi >= null));
+
+  // The following are valid constant expressions since &pi [0] is
+  // equivalent to &*pi.
+  SA (!(null == &pi [0]));
+  SA ( (null != &pi [0]));
+  RA ( (null <  &pi [0]));
+  RA ( (null <= &pi [0]));
+  RA (!(null >  &pi [0]));
+  RA (!(null >= &pi [0]));
+
+  SA (!(&pi [0] == null));
+  SA ( (&pi [0] != null));
+  RA (!(&pi [0] <  null));
+  RA (!(&pi [0] <= null));
+  RA ( (&pi [0] >  null));
+  RA ( (&pi [0] >= null));
+}
+
+void test_first_null_array_element ()
+{
+  constexpr const int *pi = 0;
+  constexpr const int *qi = 0;
+
+  // The following are valid constant expressions since in &*qi
+  // the '&*' "cancel each other out."
+  SA ( (pi == &*qi));
+  SA (!(pi != &*qi));
+
+  // The validity of the relational expressions involving null
+  // pointers in a constexpr context is questionable.
+  RA (!(pi <  &*qi));
+  RA ( (pi <= &*qi));
+  RA (!(pi >  &*qi));
+  RA ( (pi >= &*qi));
+
+  SA ( (&*qi == pi));
+  SA (!(&*qi != pi));
+  RA (!(&*qi <  pi));
+  RA ( (&*qi <= pi));
+  RA (!(&*qi >  pi));
+  RA ( (&*qi >= pi));
+
+  // The following are valid constant expressions since &qi [0] is
+  // equivalent to &*qi.
+  SA ( (pi == &qi [0]));
+  SA (!(pi != &qi [0]));
+  RA (!(pi <  &qi [0]));
+  RA ( (pi <= &qi [0]));
+  RA (!(pi >  &qi [0]));
+  RA ( (pi >= &qi [0]));
+
+  SA ( (&qi [0] == pi));
+  SA (!(&qi [0] != pi));
+  RA (!(&qi [0] <  pi));
+  RA ( (&qi [0] <= pi));
+  RA (!(&qi [0] >  pi));
+  RA ( (&qi [0] >= pi));
+}
+
+void test_first_struct_member ()
+{
+  static struct S { int a, b; } s = { 0, 0 };
+
+  constexpr const int *p = 0;
+  constexpr const S   *q = &s;
+
+  SA (!(p == &q->b));
+  SA ( (p != &q->b));
+  RA ( (p <  &q->b));
+  RA ( (p <= &q->b));
+  RA (!(p >  &q->b));
+  RA (!(p >= &q->b));
+
+  SA (!(&q->b == p));
+  SA ( (&q->b != p));
+  RA (!(&q->b <  p));
+  RA (!(&q->b <= p));
+  RA ( (&q->b >  p));
+  RA ( (&q->b >= p));
+}
+
+// Expect all runtime asserts to have been eliminated as a result
+// of the tested expressions constant folded into true.
+// { dg-final { scan-assembler-not "abort" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C
index 0f561a4..41fa466 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C
@@ -2,4 +2,4 @@
 
 constexpr char c1 = "hi"[1];
 constexpr char c2 = "hi"[2];
-constexpr char c3 = "hi"[3];	// { dg-error "out of bound" }
+constexpr char c3 = "hi"[3];	// { dg-error "array subscript" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C
index db79a9c..4055e0e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C
@@ -1,6 +1,6 @@
 // PR c++/48570
 // { dg-do compile { target c++11 } }
 
-constexpr wchar_t c1 = L"hi"[3];	// { dg-error "out of bound" }
-constexpr char16_t c2 = u"hi"[3];	// { dg-error "out of bound" }
-constexpr char32_t c3 = U"hi"[3];	// { dg-error "out of bound" }
+constexpr wchar_t c1 = L"hi"[3];	// { dg-error "array subscript" }
+constexpr char16_t c2 = u"hi"[3];	// { dg-error "array subscript" }
+constexpr char32_t c3 = U"hi"[3];	// { dg-error "array subscript" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr65398.C b/gcc/testsuite/g++.dg/cpp0x/pr65398.C
index a4aeba5..6bd34a4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr65398.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr65398.C
@@ -12,12 +12,12 @@ constexpr char c5 = *(&s[2] + 0);
 constexpr char c6 = *(&s[0] + 2);
 constexpr char c7 = *(&s[2] + 1);
 
-constexpr char d1 = *(&s[4] - 0); // { dg-error "array subscript out of bound" }
+constexpr char d1 = *(&s[4] - 0); // { dg-error "array subscript" }
 constexpr char d2 = *(&s[4] - 1);
 constexpr char d3 = *(&s[4] - 2);
 constexpr char d4 = *(&s[4] - 3);
 constexpr char d5 = *(&s[4] - 4);
-constexpr char d6 = *(&s[4] - 5);  // { dg-error "negative array subscript" }
+constexpr char d6 = *(&s[4] - 5);  // { dg-error "array subscript" }
 
 /* Don't accept invalid stuff.  */
 constexpr char e1 = *(&s[5] - 1); // { dg-error "is not a constant expression" }
@@ -45,12 +45,12 @@ constexpr int i5 = *(&l[2] + 0);
 constexpr int i6 = *(&l[0] + 2);
 constexpr int i7 = *(&l[2] + 1);
 
-constexpr char j1 = *(&l[4] - 0); // { dg-error "array subscript out of bound" }
+constexpr char j1 = *(&l[4] - 0); // { dg-error "array subscript" }
 constexpr char j2 = *(&l[4] - 1);
 constexpr char j3 = *(&l[4] - 2);
 constexpr char j4 = *(&l[4] - 3);
 constexpr char j5 = *(&l[4] - 4);
-constexpr char j6 = *(&l[4] - 5);  // { dg-error "negative array subscript" }
+constexpr char j6 = *(&l[4] - 5);  // { dg-error "array subscript" }
 
 /* Don't accept invalid stuff.  */
 constexpr char k1 = *(&l[5] - 1); // { dg-error "is not a constant expression" }
diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla1.C b/gcc/testsuite/g++.dg/ext/constexpr-vla1.C
index a5615bb..21eb93d 100644
--- a/gcc/testsuite/g++.dg/ext/constexpr-vla1.C
+++ b/gcc/testsuite/g++.dg/ext/constexpr-vla1.C
@@ -27,4 +27,4 @@ fn_not_ok (int n)
 }
 
 constexpr int n1 = fn_ok (3);
-constexpr int n2 = fn_not_ok (3); // { dg-error "array subscript out of bound" }
+constexpr int n2 = fn_not_ok (3); // { dg-error "array subscript" }
diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C
index 6cb1f70..6aab184 100644
--- a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C
+++ b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C
@@ -18,4 +18,4 @@ fn_ok (int n)
 }
 
 constexpr int i1 = fn_ok (3);
-constexpr int i2 = fn_bad (3); // { dg-error "array subscript out of bound" }
+constexpr int i2 = fn_bad (3); // { dg-error "array subscript" }
diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C
index ba4eb50..33fc968 100644
--- a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C
+++ b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C
@@ -11,4 +11,4 @@ foo (int n)
   return z;
 }
 
-constexpr int n = foo (3); // { dg-error "array subscript out of bound" }
+constexpr int n = foo (3); // { dg-error "array subscript" }
diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C
index b265631..90360be 100644
--- a/gcc/testsuite/g++.dg/ubsan/pr63956.C
+++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C
@@ -86,7 +86,7 @@ fn5 (const int *a, int b)
 
 constexpr int m1[4] = { 1, 2, 3, 4 };
 constexpr int m2 = fn5 (m1, 3);
-constexpr int m3 = fn5 (m1, 4); // { dg-error "array subscript out of bound" }
+constexpr int m3 = fn5 (m1, 4); // { dg-error "array subscript" }
 
 constexpr int
 fn6 (const int &a, int b)
@@ -116,7 +116,7 @@ fn8 (int i)
 }
 
 constexpr int o1 = fn8 (9);
-constexpr int o2 = fn8 (10); // { dg-error "array subscript out of bound" }
+constexpr int o2 = fn8 (10); // { dg-error "array subscript" }
 
 constexpr int
 fn9 (int a, int b)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]