diff mbox

c++/67376 Comparison with pointer to past-the-end, of array fails inside constant expression

Message ID 56F9AA63.4090201@gmail.com
State New
Headers show

Commit Message

Martin Sebor March 28, 2016, 10:04 p.m. UTC
>>> I think let's defer the fix for c++/60760 (i.e. the nullptr_p bits)
>>> until stage 1, when it can be combined with the POINTER_PLUS_EXPR fix,
>>> and put the rest of this patch in now.
>>
>> I can split up the patch into two and post the subset without
>> the fix for c++/60760, though I don't expect to be done with
>> it after I get back (next week).
>>
>> I'd like to understand your concern with the fix for c++/60760.
>> Is it that it's incomplete (doesn't reject taking the address
>> of the first member of a struct, as in &null->first_member),
>> or are you worried that the changes may not be stable enough?
>
> More the latter; it seems like significant new code and doesn't fix a
> regression.

Attached is an updated patch without the fix for c++/60760, retested
on x86_64.

Martin

Comments

Jason Merrill March 29, 2016, 6:54 p.m. UTC | #1
On 03/28/2016 06:04 PM, Martin Sebor wrote:
> +	       && compare_tree_int (arg1, 0) == 0)

This can be integer_zerop.

> +	    case GE_EXPR:
> +	    case EQ_EXPR:
> +	    case LE_EXPR:
> +	      return boolean_false_node;
> +	    case GT_EXPR:
> +	    case LT_EXPR:
> +	    case NE_EXPR:
> +	      return boolean_true_node;

EQ and NE make sense, but I would expect both > and >= to be true, < and 
<= to be false.

Are we confident that arr[0] won't make it here as POINTER_PLUS_EXPR or 
some such?

Jason
diff mbox

Patch

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-18  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-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-18  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-18  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 7776cac..c900080 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.  */
@@ -1861,6 +1885,7 @@  cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
 					false,
 					non_constant_p, overflow_p);
   VERIFY_CONSTANT (index);
+
   if (lval && ary == oldary && index == oldidx)
     return t;
   else if (lval)
@@ -1885,8 +1910,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 +1922,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..3f65243 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,38 @@  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 sybols must have a non
+	 null address.  */
+      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. */
+	       && (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))
+	       && TREE_CODE (arg1) == INTEGER_CST
+	       && compare_tree_int (arg1, 0) == 0)
+	{
+	  switch (code)
+	    {
+	    case GE_EXPR:
+	    case EQ_EXPR:
+	    case LE_EXPR:
+	      return boolean_false_node;
+	    case GT_EXPR:
+	    case LT_EXPR:
+	    case NE_EXPR:
+	      return boolean_true_node;
+	    default:
+	      gcc_unreachable ();
+	    }
+	}
     }
 
   /* Transform comparisons of the form X +- C1 CMP Y +- C2 to
@@ -13506,16 +13552,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-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..bab875c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr65398.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr65398.C
@@ -12,17 +12,17 @@  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" }
-constexpr char e2 = *(&s[5] - 2); // { dg-error "is not a constant expression" }
-constexpr char e3 = *(&s[5] - 3); // { dg-error "is not a constant expression" }
+constexpr char e1 = *(&s[5] - 1); // { dg-error "array subscript" }
+constexpr char e2 = *(&s[5] - 2); // { dg-error "array subscript" }
+constexpr char e3 = *(&s[5] - 3); // { dg-error "array subscript" }
 
 SA (c1 == 'a');
 SA (c2 == 'b');
@@ -45,17 +45,17 @@  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" }
-constexpr char k2 = *(&l[5] - 2); // { dg-error "is not a constant expression" }
-constexpr char k3 = *(&l[5] - 3); // { dg-error "is not a constant expression" }
+constexpr char k1 = *(&l[5] - 1); // { dg-error "array subscript" }
+constexpr char k2 = *(&l[5] - 2); // { dg-error "array subscript" }
+constexpr char k3 = *(&l[5] - 3); // { dg-error "array subscript" }
 
 SA (i1 == 'c');
 SA (i2 == 'd');
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)