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: [PING] Re: [PATCH] c++/67913, 67917 - fix new expression with wrong number of elements


On 11/02/2015 09:55 PM, Jason Merrill wrote:
On 10/26/2015 10:06 PM, Martin Sebor wrote:
+      if (TREE_CONSTANT (maybe_constant_value (outer_nelts)))
+    {
+      if (tree_int_cst_lt (max_outer_nelts_tree, outer_nelts))

maybe_constant_value may return a constant, but that doesn't mean that
outer_nelts was already constant; if it wasn't, the call to
tree_int_cst_lt will fail.

Thanks for the hint. I wasn't able to trigger the failure. I suspect
outer_nelts must have already been folded at this point because the
maybe_constant_value call isn't necessary. I removed it.

Since we're moving toward delayed folding, I'd prefer to use the result
of maybe_constant_value only for this diagnostic, and then continue to
pass the unfolded value along.

Sure. Done in the attached patch.

Martin
gcc/cp/ChangeLog

2015-10-19  Martin Sebor  <msebor@redhat.com>

	PR c++/67913
	PR c++/67927
	* call.c (build_operator_new_call): Do not assume size_check
	is non-null, analogously to the top half of the function.
	* init.c (build_new_1): Detect and diagnose array sizes in
	excess of the maximum of roughly SIZE_MAX / 2.
	Insert a runtime check only for arrays with a non-constant size.
	(build_new): Detect and diagnose negative array sizes.

gcc/testsuite/ChangeLog

2015-10-19  Martin Sebor  <msebor@redhat.com>

	* init/new45.C: New test to verify that operator new is invoked
	with or without overhead for a cookie.

	PR c++/67927
	* init/new44.C: New test for placement new expressions for arrays
	with excessive number of elements.

	PR c++/67913
	* init/new43.C: New test for placement new expressions for arrays
	with negative number of elements.

	* other/new-size-type.C: Expect array new expression with
	an excessive number of elements to be rejected.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 367d42b..3f76198 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4228,10 +4228,12 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
 	 {
 	   /* Update the total size.  */
 	   *size = size_binop (PLUS_EXPR, original_size, *cookie_size);
+	   if (size_check)
+	     {
 	       /* Set to (size_t)-1 if the size check fails.  */
-	   gcc_assert (size_check != NULL_TREE);
 	       *size = fold_build3 (COND_EXPR, sizetype, size_check,
 				    *size, TYPE_MAX_VALUE (sizetype));
+	     }
 	   /* Update the argument list to reflect the adjusted size.  */
 	   (**args)[0] = *size;
 	 }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1ed8f6c..3b88098 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2272,7 +2272,11 @@ throw_bad_array_new_length (void)
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
-   build_raw_new_expr.  This may change PLACEMENT and INIT.  */
+   build_raw_new_expr.  This may change PLACEMENT and INIT.
+   TYPE is the type of the object being constructed, possibly an array
+   of NELTS elements when NELTS is non-null (in "new T[NELTS]", T may
+   be an array of the form U[inner], with the whole expression being
+   "new U[NELTS][inner]").  */

 static tree
 build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
@@ -2292,13 +2296,16 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
      type.)  */
   tree pointer_type;
   tree non_const_pointer_type;
+  /* The most significant array bound in int[OUTER_NELTS][inner].  */
   tree outer_nelts = NULL_TREE;
-  /* For arrays, a bounds checks on the NELTS parameter. */
+  /* For arrays with a non-constant number of elements, a bounds checks
+     on the NELTS parameter to avoid integer overflow at runtime. */
   tree outer_nelts_check = NULL_TREE;
   bool outer_nelts_from_type = false;
+  /* Number of the "inner" elements in "new T[OUTER_NELTS][inner]".  */
   offset_int inner_nelts_count = 1;
   tree alloc_call, alloc_expr;
-  /* Size of the inner array elements. */
+  /* Size of the inner array elements (those with constant dimensions). */
   offset_int inner_size;
   /* The address returned by the call to "operator new".  This node is
      a VAR_DECL and is therefore reusable.  */
@@ -2492,21 +2499,41 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	}

       max_outer_nelts = wi::udiv_trunc (max_size, inner_size);
-      /* Only keep the top-most seven bits, to simplify encoding the
-	 constant in the instruction stream.  */
+      max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
+
+      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
+
+      if (TREE_CONSTANT (outer_nelts))
+	{
+	  if (tree_int_cst_lt (max_outer_nelts_tree, outer_nelts))
+	    {
+	      /* When the array size is constant, check it at compile time
+		 to make sure it doesn't exceed the implementation-defined
+		 maximum, as required by C++ 14 (in C++ 11 this requirement
+		 isn't explicitly stated but it's enforced anyway -- see
+		 grokdeclarator in cp/decl.c).  */
+	      if (complain & tf_error)
+		error ("size of array is too large");
+	      return error_mark_node;
+	    }
+	}
+      else
 	{
+	  /* When a runtime check is necessary because the array size
+	     isn't constant, keep only the top-most seven bits (starting
+	     with the most significant non-zero bit) of the maximum size
+	     to compare the array size against, to simplify encoding the
+	     constant maximum size in the instruction stream.  */
 	  unsigned shift = (max_outer_nelts.get_precision ()) - 7
 	    - wi::clz (max_outer_nelts);
 	  max_outer_nelts = wi::lshift (wi::lrshift (max_outer_nelts, shift),
 					shift);
-      }
-      max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);

-      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
 	  outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
 					   outer_nelts,
 					   max_outer_nelts_tree);
 	}
+    }

   alloc_fn = NULL_TREE;

@@ -3066,6 +3093,23 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
           else
             return error_mark_node;
         }
+
+      /* Try to determine the constant value only for the purposes
+	 of the diagnostic below but continue to use the original
+	 value and handle const folding later.  */
+      const_tree cst_nelts = maybe_constant_value (nelts);
+
+      /* The expression in a noptr-new-declarator is erroneous if it's of
+	 non-class type and its value before converting to std::size_t is
+	 less than zero. ... If the expression is a constant expression,
+	 the program is ill-fomed.  */
+      if (TREE_CONSTANT (cst_nelts) && tree_int_cst_sgn (cst_nelts) == -1)
+	{
+	  if (complain & tf_error)
+	    error ("size of array is negative");
+	  return error_mark_node;
+	}
+
       nelts = mark_rvalue_use (nelts);
       nelts = cp_save_expr (cp_convert (sizetype, nelts, complain));
     }
diff --git a/gcc/testsuite/g++.dg/init/new43.C b/gcc/testsuite/g++.dg/init/new43.C
new file mode 100644
index 0000000..9b08667
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new43.C
@@ -0,0 +1,164 @@
+/* { dg-do compile } */
+
+// Test for PR c++/67913 - new expression with negative size not diagnosed.
+typedef __typeof__ (sizeof 0) size_t;
+
+void* operator new (size_t, void*);
+void* operator new[] (size_t, void*);
+
+struct A {
+    int a [4];
+};
+
+struct B {
+    int a [4];
+
+    void* operator new (size_t, void*);
+    void* operator new[] (size_t, void*);
+};
+
+void* operator new (size_t, B*);
+void* operator new[] (size_t, B*);
+
+void *p;
+
+void test_literal ()
+{
+    char c;
+    (void)c;
+
+    B b;
+
+    // Verify integer literal.
+    p = new char [-1];           // { dg-error "size of array is negative" }
+    p = new char [2][-3];        // { dg-error "size of array is negative" }
+    p = new char [-4][5];        // { dg-error "size of array is negative" }
+    p = new char [-6][-7];       // { dg-error "size of array is negative" }
+
+    p = new (p) char [-1];       // { dg-error "size of array is negative" }
+    p = new (p) char [2][-3];    // { dg-error "size of array is negative" }
+    p = new (p) char [-4][5];    // { dg-error "size of array is negative" }
+    p = new (p) char [-6][-7];   // { dg-error "size of array is negative" }
+
+    p = new (p) A [-1];          // { dg-error "size of array is negative" }
+    p = new (p) A [2][-3];       // { dg-error "size of array is negative" }
+    p = new (p) A [-4][5];       // { dg-error "size of array is negative" }
+    p = new (p) A [-6][-7];      // { dg-error "size of array is negative" }
+
+    p = new (p) B [-1];          // { dg-error "size of array is negative" }
+    p = new (p) B [2][-3];       // { dg-error "size of array is negative" }
+    p = new (p) B [-4][5];       // { dg-error "size of array is negative" }
+    p = new (p) B [-6][-7];      // { dg-error "size of array is negative" }
+
+    p = new (&b) B [-1];          // { dg-error "size of array is negative" }
+    p = new (&b) B [2][-3];       // { dg-error "size of array is negative" }
+    p = new (&b) B [-4][5];       // { dg-error "size of array is negative" }
+    p = new (&b) B [-6][-7];      // { dg-error "size of array is negative" }
+
+    p = new char [1 - 2];         // { dg-error "size of array is negative" }
+    p = new (p) char [2 - 3];     // { dg-error "size of array is negative" }
+    p = new A [2 < 1 ? -1 : -2];  // { dg-error "size of array is negative" }
+    p = new (p) B [2 - 3 * 2];    // { dg-error "size of array is negative" }
+    p = new (&b) B [1][2 - 3 * 2];// { dg-error "size of array is negative" }
+}
+
+void test_constant_expression ()
+{
+    char c;
+    (void)c;
+
+    B b;
+
+    static const signed char i1 = -1;
+    static const signed short i2 = -2;
+    static const signed int i3 = -3;
+    static const signed long i4 = -4;
+    static const signed long long i5 = -5;
+    static const int i6 = -6;
+    static const int i7 = -7;
+
+    // Verify constant expression.
+    p = new char [i1];           // { dg-error "size of array is negative" }
+    p = new char [2][i3];        // { dg-error "size of array is negative" }
+    p = new char [i4][5];        // { dg-error "size of array is negative" }
+    p = new char [i6][i7];       // { dg-error "size of array is negative" }
+
+    p = new (p) char [i1];       // { dg-error "size of array is negative" }
+    p = new (p) char [2][i3];    // { dg-error "size of array is negative" }
+    p = new (p) char [i4][5];    // { dg-error "size of array is negative" }
+    p = new (p) char [i6][i7];   // { dg-error "size of array is negative" }
+
+    p = new (p) A [i1];          // { dg-error "size of array is negative" }
+    p = new (p) A [2][i3];       // { dg-error "size of array is negative" }
+    p = new (p) A [i4][5];       // { dg-error "size of array is negative" }
+    p = new (p) A [i6][i7];      // { dg-error "size of array is negative" }
+
+    p = new (p) B [i1];          // { dg-error "size of array is negative" }
+    p = new (p) B [2][i3];       // { dg-error "size of array is negative" }
+    p = new (p) B [i4][5];       // { dg-error "size of array is negative" }
+    p = new (p) B [i6][i7];      // { dg-error "size of array is negative" }
+
+    p = new (&b) B [i1];          // { dg-error "size of array is negative" }
+    p = new (&b) B [2][i3];       // { dg-error "size of array is negative" }
+    p = new (&b) B [i4][5];       // { dg-error "size of array is negative" }
+    p = new (&b) B [i6][i7];      // { dg-error "size of array is negative" }
+
+    p = new short [i1 - 2];       // { dg-error "size of array is negative" }
+    p = new (p) bool [i2 - 3];    // { dg-error "size of array is negative" }
+    p = new A [2 < 1 ? i1 : i2];  // { dg-error "size of array is negative" }
+    p = new (p) B [2 + i3 * 2];   // { dg-error "size of array is negative" }
+    p = new (&b) B [1][i1 - 3 * 2];// { dg-error "size of array is negative" }
+}
+
+void test_constexpr ()
+{
+    B b;
+
+#if __cplusplus >= 201103L
+
+    // Verify that a constant expression that is "a prvalue core constant
+    // expression whose value is an object where, for that object and its
+    // subobjects each non-static data member of reference type refers to
+    // an object with static storage duration."
+    static constexpr struct S {
+        int i_;
+        constexpr S (int i): i_ (i) { }
+        constexpr operator int () const { return i_; }
+    } s1 (-1), s2 (-2), s3 (-3), s4 (-4), s5 (-5), s6 (-6), s7 (-7);
+#else
+    // C++ 11 constexpr is not available, fall back on plain ole enum.
+    enum { s1 = -1, s2 = -2, s3 = -3, s4 = -4, s5 = -5, s6 = -6, s7 = -7 };
+#endif
+
+    // Verify constant expression.
+    p = new char [s1];           // { dg-error "size of array is negative" }
+    p = new char [2][s3];        // { dg-error "size of array is negative" }
+    p = new char [s4][5];        // { dg-error "size of array is negative" }
+    p = new char [s6][s7];       // { dg-error "size of array is negative" }
+
+    p = new (p) char [s1];       // { dg-error "size of array is negative" }
+    p = new (p) char [2][s3];    // { dg-error "size of array is negative" }
+    p = new (p) char [s4][5];    // { dg-error "size of array is negative" }
+    p = new (p) char [s6][s7];   // { dg-error "size of array is negative" }
+
+    p = new (p) A [s1];          // { dg-error "size of array is negative" }
+    p = new (p) A [2][s3];       // { dg-error "size of array is negative" }
+    p = new (p) A [s4][5];       // { dg-error "size of array is negative" }
+    p = new (p) A [s6][s7];      // { dg-error "size of array is negative" }
+
+    p = new (p) B [s1];          // { dg-error "size of array is negative" }
+    p = new (p) B [2][s3];       // { dg-error "size of array is negative" }
+    p = new (p) B [s4][5];       // { dg-error "size of array is negative" }
+    p = new (p) B [s6][s7];      // { dg-error "size of array is negative" }
+
+    p = new (&b) B [s1];          // { dg-error "size of array is negative" }
+    p = new (&b) B [2][s3];       // { dg-error "size of array is negative" }
+    p = new (&b) B [s4][5];       // { dg-error "size of array is negative" }
+    p = new (&b) B [s6][s7];      // { dg-error "size of array is negative" }
+
+    p = new int [s1 + s2];           // { dg-error "size of array is negative" }
+    p = new (p) long [2 * s3];       // { dg-error "size of array is negative" }
+    p = new A [s2 < s1 ? s1 : s2];   // { dg-error "size of array is negative" }
+    p = new (p) B [s7 - s2 * 2];     // { dg-error "size of array is negative" }
+    p = new (&b) B [9][s4 - s1 * 2]; // { dg-error "size of array is negative" }
+}
diff --git a/gcc/testsuite/g++.dg/init/new44.C b/gcc/testsuite/g++.dg/init/new44.C
new file mode 100644
index 0000000..d6ff86a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new44.C
@@ -0,0 +1,532 @@
+// { dg-do compile }
+
+// Test for PR c++/67927 - array new expression with excessive number
+// of elements not diagnosed.
+
+// GCC uses a different maximum value at compile time and at runtime:
+// 1) The compile-time maximum, MAX, is SIZE_MAX / 2 minus the size
+//    of a cookie (sizeof (size_t)).  Exceeding the compile-time
+//    maximum is ill-formed and diagnosed.  This test verifies this
+//    diagnostic.
+// 2) The runtime runtime maximum is the most significant 7 bits,
+//    starting with the first most significant non-zero bit, of
+//    the dividend of the compile-time constant MAX and the product
+//    of the constant array dimensions and the element size, minus
+//    the size of the "cookie."  This is also roughly (though not
+//    exactly) SIZE_MAX / 2.  Exceeding the runtime maximum is
+//    diagnosed at runtime by throwing a bad_array_new_length
+//    exception.
+//    The cookie is the number of elements in the array, and is
+//    only added for non-POD types, but the its size factors into
+//    the maximum size formula regardless.
+
+// See also PR c++/19351 - integer overflow in operator new[].
+
+// For convenience.
+#define MAX __SIZE_MAX__
+
+typedef __typeof__ (sizeof 0) size_t;
+
+void* operator new (size_t, void*);
+void* operator new[] (size_t, void*);
+
+void *p;
+
+// Exercise new expression with one-dimensional arrays of char.
+static void __attribute__ ((used))
+test_one_dim_char_array ()
+{
+    p = new char [MAX];                 // { dg-error "size of array" }
+    p = new char [MAX - 1];             // { dg-error "size of array" }
+    p = new char [MAX - 2];             // { dg-error "size of array" }
+    p = new char [MAX - 99];            // { dg-error "size of array" }
+    p = new char [MAX / 2];             // { dg-error "size of array" }
+    p = new char [MAX / 2 - 1];         // { dg-error "size of array" }
+    p = new char [MAX / 2 - 2];         // { dg-error "size of array" }
+
+    // Avoid testing the expressions below since whether or not they
+    // are accepted depends on the precision of size_t (which also
+    // determines the size of the cookie).
+    // p = new char [MAX / 2 - 3];
+    // p = new char [MAX / 2 - 4];
+    // p = new char [MAX / 2 - 5];
+    // p = new char [MAX / 2 - 6];
+
+    // The following expressions are accepted on ILP32 as well LP64
+    // (they will be diagnosed on LP128 if there ever is such a data
+    // model).
+    p = new char [MAX / 2 - 7];         // okay
+    p = new char [MAX / 2 - 8];         // okay
+}
+
+static void __attribute__ ((used))
+test_one_dim_short_array ()
+{
+    p = new short [MAX];                // { dg-error "size of array" }
+    p = new short [MAX - 1];            // { dg-error "size of array" }
+    p = new short [MAX - 2];            // { dg-error "size of array" }
+    p = new short [MAX - 99];           // { dg-error "size of array" }
+    p = new short [MAX / 2];            // { dg-error "size of array" }
+    p = new short [MAX / 2 - 1];        // { dg-error "size of array" }
+    p = new short [MAX / 2 - 2];        // { dg-error "size of array" }
+    p = new short [MAX / 2 - 3];        // { dg-error "size of array" }
+    p = new short [MAX / 2 - 4];        // { dg-error "size of array" }
+    p = new short [MAX / 2 - 5];        // { dg-error "size of array" }
+    p = new short [MAX / 2 - 6];        // { dg-error "size of array" }
+    p = new short [MAX / 2 - 7];        // { dg-error "size of array" }
+    p = new short [MAX / 2 - 8];        // { dg-error "size of array" }
+    p = new short [MAX / 4];            // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new short [MAX / 4 - 1];
+
+    p = new short [MAX / 4 - 4];        // okay
+}
+
+// Exercise new expression with two-dimensional arrays or char.
+static void __attribute__ ((used))
+test_two_dim_char_array ()
+{
+    p = new char [1][MAX];              // { dg-error "size of array" }
+    p = new char [1][MAX - 1];          // { dg-error "size of array" }
+    p = new char [1][MAX - 2];          // { dg-error "size of array" }
+    p = new char [1][MAX - 99];         // { dg-error "size of array" }
+    p = new char [1][MAX / 2];          // { dg-error "size of array" }
+    p = new char [1][MAX / 2 - 1];      // { dg-error "size of array" }
+    p = new char [1][MAX / 2 - 2];      // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [1][MAX / 2 - 3];
+    // p = new char [1][MAX / 2 - 4];
+    // p = new char [1][MAX / 2 - 5];
+    // p = new char [1][MAX / 2 - 6];
+
+    p = new char [1][MAX / 2 - 7];      // okay
+    p = new char [1][MAX / 2 - 8];      // okay
+
+    p = new char [2][MAX];              // { dg-error "size of array" }
+    p = new char [2][MAX - 1];          // { dg-error "size of array" }
+    p = new char [2][MAX - 2];          // { dg-error "size of array" }
+    p = new char [2][MAX / 2];          // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 1];      // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 2];      // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 7];      // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 8];      // { dg-error "size of array" }
+
+    p = new char [MAX][MAX];            // { dg-error "size of array" }
+    p = new char [MAX][MAX - 1];        // { dg-error "size of array" }
+    p = new char [MAX][MAX - 2];        // { dg-error "size of array" }
+    p = new char [MAX][MAX / 2];        // { dg-error "size of array" }
+    p = new char [MAX][MAX / 2 - 1];    // { dg-error "size of array" }
+    p = new char [MAX][MAX / 2 - 2];    // { dg-error "size of array" }
+    p = new char [MAX][MAX / 2 - 7];    // { dg-error "size of array" }
+    p = new char [MAX][MAX / 2 - 8];    // { dg-error "size of array" }
+    p = new char [MAX][2];              // { dg-error "size of array" }
+    p = new char [MAX][1];              // { dg-error "size of array" }
+    p = new char [MAX / 2][1];          // { dg-error "size of array" }
+    p = new char [MAX / 2 - 1][1];      // { dg-error "size of array" }
+    p = new char [MAX / 2 - 2][1];      // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [MAX / 2 - 3][1];
+    // p = new char [MAX / 2 - 4][1];
+    // p = new char [MAX / 2 - 5][1];
+    // p = new char [MAX / 2 - 6][1];
+
+    p = new char [MAX / 2 - 7][1];      // okay
+    p = new char [MAX / 2 - 8][1];      // okay
+}
+
+
+// Exercise new expression with three-dimensional arrays.
+static __attribute__ ((used)) void
+test_three_dim_char_array ()
+{
+    p = new char [1][1][MAX];           // { dg-error "size of array" }
+    p = new char [1][1][MAX - 1];       // { dg-error "size of array" }
+    p = new char [1][1][MAX - 2];       // { dg-error "size of array" }
+    p = new char [1][1][MAX - 99];      // { dg-error "size of array" }
+    p = new char [1][1][MAX / 2];       // { dg-error "size of array" }
+    p = new char [1][1][MAX / 2 - 1];   // { dg-error "size of array" }
+    p = new char [1][1][MAX / 2 - 2];   // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [1][1][MAX / 2 - 3];
+    // p = new char [1][1][MAX / 2 - 4];
+    // p = new char [1][1][MAX / 2 - 5];
+    // p = new char [1][1][MAX / 2 - 6];
+
+    p = new char [1][1][MAX / 2 - 7];   // okay
+    p = new char [1][1][MAX / 2 - 8];   // okay
+
+    p = new char [1][2][MAX];           // { dg-error "size of array" }
+    p = new char [1][2][MAX - 1];       // { dg-error "size of array" }
+    p = new char [1][2][MAX - 2];       // { dg-error "size of array" }
+    p = new char [1][2][MAX - 99];      // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2];       // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 1];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 2];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 3];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 4];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 5];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 6];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 7];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 2 - 8];   // { dg-error "size of array" }
+    p = new char [1][2][MAX / 4];       // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [1][2][MAX / 4 - 1];
+    // p = new char [1][2][MAX / 4 - 2];
+
+    p = new char [1][2][MAX / 4 - 3];   // okay
+    p = new char [1][2][MAX / 4 - 4];   // okay
+
+    p = new char [2][1][MAX];           // { dg-error "size of array" }
+    p = new char [2][1][MAX - 1];       // { dg-error "size of array" }
+    p = new char [2][1][MAX - 2];       // { dg-error "size of array" }
+    p = new char [2][1][MAX - 99];      // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2];       // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 1];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 2];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 3];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 4];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 5];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 6];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 7];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 2 - 8];   // { dg-error "size of array" }
+    p = new char [2][1][MAX / 4];       // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [2][1][MAX / 4 - 1];
+    // p = new char [2][1][MAX / 4 - 2];
+
+    p = new char [2][1][MAX / 4 - 3];   // okay
+    p = new char [2][1][MAX / 4 - 4];   // okay
+
+    p = new char [2][2][MAX];           // { dg-error "size of array" }
+    p = new char [2][2][MAX - 1];       // { dg-error "size of array" }
+    p = new char [2][2][MAX - 2];       // { dg-error "size of array" }
+    p = new char [2][2][MAX - 99];      // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2];       // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 1];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 2];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 3];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 4];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 5];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 6];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 7];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 2 - 8];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 4];       // { dg-error "size of array" }
+    p = new char [2][2][MAX / 4 - 1];   // { dg-error "size of array" }
+    p = new char [2][2][MAX / 4 - 2];   // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [2][2][MAX / 8];
+    // p = new char [2][2][MAX / 8 - 1];
+
+    p = new char [2][2][MAX / 8 - 2];
+    p = new char [2][2][MAX / 8 - 3];
+
+    p = new char [2][MAX][2];           // { dg-error "size of array" }
+    p = new char [2][MAX - 1][2];       // { dg-error "size of array" }
+    p = new char [2][MAX - 2][2];       // { dg-error "size of array" }
+    p = new char [2][MAX - 99][2];      // { dg-error "size of array" }
+    p = new char [2][MAX / 2][2];       // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 1][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 2][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 3][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 4][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 5][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 6][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 7][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 2 - 8][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 4][2];       // { dg-error "size of array" }
+    p = new char [2][MAX / 4 - 1][2];   // { dg-error "size of array" }
+    p = new char [2][MAX / 4 - 2][2];   // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [2][MAX / 8][2];
+    // p = new char [2][MAX / 8 - 1][2];
+
+    p = new char [2][MAX / 8 - 2][2];
+    p = new char [2][MAX / 8 - 3][2];
+
+    p = new char [MAX][2][2];           // { dg-error "size of array" }
+    p = new char [MAX - 1][2][2];       // { dg-error "size of array" }
+    p = new char [MAX - 2][2][2];       // { dg-error "size of array" }
+    p = new char [MAX - 99][2][2];      // { dg-error "size of array" }
+    p = new char [MAX / 2][2][2];       // { dg-error "size of array" }
+    p = new char [MAX / 2 - 1][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 2 - 2][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 2 - 3][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 2 - 4][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 2 - 5][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 2 - 6][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 2 - 7][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 2 - 8][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 4][2][2];       // { dg-error "size of array" }
+    p = new char [MAX / 4 - 1][2][2];   // { dg-error "size of array" }
+    p = new char [MAX / 4 - 2][2][2];   // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new char [MAX / 8][2][2];
+    // p = new char [MAX / 8 - 1][2][2];
+
+    p = new char [MAX / 8 - 2][2][2];
+    p = new char [MAX / 8 - 3][2][2];
+
+    p = new char [MAX][MAX][MAX];         // { dg-error "size of array" }
+    p = new char [MAX][MAX][MAX / 2];     // { dg-error "size of array" }
+    p = new char [MAX][MAX / 2][MAX];     // { dg-error "size of array" }
+    p = new char [MAX][MAX / 2][MAX / 2]; // { dg-error "size of array" }
+    p = new char [MAX / 2][MAX / 2][MAX / 2]; // { dg-error "size of array" }
+}
+
+// Exercise new expression with N-dimensional arrays where N is
+// sizeof(size_t).
+static __attribute__ ((used)) void
+test_N_dim_char_array ()
+{
+#if __SIZEOF_SIZE_T__ == 8
+    enum { N = 256 };
+#else
+    enum { N = 16 };
+#endif
+
+    p = new char        [N][N][N][N][N][N][N];
+    p = new char [N / 2][2][N][N][N][N][N][N];
+    p = new char [N - 1][N / 2][N][N][N][N][N][N];
+    p = new char [N / 2][N][N][N][N][N][N][N];  // { dg-error "size of array" }
+    p = new char [N - 1][N][N][N][N][N][N][N];  // { dg-error "size of array" }
+    p = new char [N]    [N][N][N][N][N][N][N];  // { dg-error "size of array" }
+}
+
+typedef struct Byte {
+    char c;
+
+    void* operator new (size_t, void*);
+    void* operator new[] (size_t, void*);
+} B;
+
+void* operator new (size_t, B*);
+void* operator new[] (size_t, B*);
+
+// Exercise placement new expression with one-dimensional arrays of a struct.
+static void __attribute__ ((used))
+test_one_dim_byte_array (void *p)
+{
+    p = new (p) B [MAX];                // { dg-error "size of array" }
+    p = new (p) B [MAX - 1];            // { dg-error "size of array" }
+    p = new (p) B [MAX - 2];            // { dg-error "size of array" }
+    p = new (p) B [MAX - 99];           // { dg-error "size of array" }
+    p = new (p) B [MAX / 2];            // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 1];        // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 2];        // { dg-error "size of array" }
+
+    // Avoid testing the expressions below since whether or not they
+    // are accepted depends on the precision of size_t (which determines
+    // the size of the cookie).
+    // p = new (p) B [MAX / 2 - 3];
+    // p = new (p) B [MAX / 2 - 4];
+    // p = new (p) B [MAX / 2 - 5];
+    // p = new (p) B [MAX / 2 - 6];
+
+    // The following expressions are accepted on ILP32 as well LP64
+    // (they will be diagnosed on LP128 if there ever is such a data
+    // model).
+    p = new (p) B [MAX / 2 - 7];         // okay
+    p = new (p) B [MAX / 2 - 8];         // okay
+}
+
+// Exercise placement new expression with two-dimensional arrays.
+static void __attribute__ ((used))
+test_placement_two_dim_byte_struct_array (void *p)
+{
+    p = new (p) B [1][MAX];             // { dg-error "size of array" }
+    p = new (p) B [1][MAX - 1];         // { dg-error "size of array" }
+    p = new (p) B [1][MAX - 2];         // { dg-error "size of array" }
+    p = new (p) B [1][MAX - 99];        // { dg-error "size of array" }
+    p = new (p) B [1][MAX / 2];         // { dg-error "size of array" }
+    p = new (p) B [1][MAX / 2 - 1];     // { dg-error "size of array" }
+    p = new (p) B [1][MAX / 2 - 2];     // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [1][MAX / 2 - 3];
+    // p = new (p) B [1][MAX / 2 - 4];
+    // p = new (p) B [1][MAX / 2 - 5];
+    // p = new (p) B [1][MAX / 2 - 6];
+
+    p = new (p) B [1][MAX / 2 - 7];      // okay
+    p = new (p) B [1][MAX / 2 - 8];      // okay
+
+    p = new (p) B [2][MAX];             // { dg-error "size of array" }
+    p = new (p) B [2][MAX - 1];         // { dg-error "size of array" }
+    p = new (p) B [2][MAX - 2];         // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2];         // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 1];     // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 2];     // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 7];     // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 8];     // { dg-error "size of array" }
+
+    p = new (p) B [MAX][MAX];           // { dg-error "size of array" }
+    p = new (p) B [MAX][MAX - 1];       // { dg-error "size of array" }
+    p = new (p) B [MAX][MAX - 2];       // { dg-error "size of array" }
+    p = new (p) B [MAX][MAX / 2];       // { dg-error "size of array" }
+    p = new (p) B [MAX][MAX / 2 - 1];   // { dg-error "size of array" }
+    p = new (p) B [MAX][MAX / 2 - 2];   // { dg-error "size of array" }
+    p = new (p) B [MAX][MAX / 2 - 7];   // { dg-error "size of array" }
+    p = new (p) B [MAX][MAX / 2 - 8];   // { dg-error "size of array" }
+    p = new (p) B [MAX][2];             // { dg-error "size of array" }
+    p = new (p) B [MAX][1];             // { dg-error "size of array" }
+    p = new (p) B [MAX / 2][1];         // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 1][1];     // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 2][1];     // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [MAX / 2 - 3][1];
+    // p = new (p) B [MAX / 2 - 4][1];
+    // p = new (p) B [MAX / 2 - 5][1];
+    // p = new (p) B [MAX / 2 - 6][1];
+
+    p = new (p) B [MAX / 2 - 7][1];      // okay
+    p = new (p) B [MAX / 2 - 8][1];      // okay
+}
+
+
+// Exercise placement new expression with three-dimensional arrays.
+static __attribute__ ((used)) void
+test_placement_three_dim_byte_struct_array (void *p)
+{
+    p = new (p) B [1][1][MAX];          // { dg-error "size of array" }
+    p = new (p) B [1][1][MAX - 1];      // { dg-error "size of array" }
+    p = new (p) B [1][1][MAX - 2];      // { dg-error "size of array" }
+    p = new (p) B [1][1][MAX - 99];     // { dg-error "size of array" }
+    p = new (p) B [1][1][MAX / 2];      // { dg-error "size of array" }
+    p = new (p) B [1][1][MAX / 2 - 1];  // { dg-error "size of array" }
+    p = new (p) B [1][1][MAX / 2 - 2];  // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [1][1][MAX / 2 - 3];
+    // p = new (p) B [1][1][MAX / 2 - 4];
+    // p = new (p) B [1][1][MAX / 2 - 5];
+    // p = new (p) B [1][1][MAX / 2 - 6];
+
+    p = new (p) B [1][1][MAX / 2 - 7];   // okay
+    p = new (p) B [1][1][MAX / 2 - 8];   // okay
+
+    p = new (p) B [1][2][MAX];          // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX - 1];      // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX - 2];      // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX - 99];     // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2];      // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 1];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 2];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 3];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 4];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 5];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 6];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 7];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 2 - 8];  // { dg-error "size of array" }
+    p = new (p) B [1][2][MAX / 4];      // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [1][2][MAX / 4 - 1];
+    // p = new (p) B [1][2][MAX / 4 - 2];
+
+    p = new (p) B [1][2][MAX / 4 - 3];   // okay
+    p = new (p) B [1][2][MAX / 4 - 4];   // okay
+
+    p = new (p) B [2][1][MAX];          // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX - 1];      // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX - 2];      // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX - 99];     // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2];      // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 1];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 2];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 3];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 4];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 5];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 6];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 7];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 2 - 8];  // { dg-error "size of array" }
+    p = new (p) B [2][1][MAX / 4];      // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [2][1][MAX / 4 - 1];
+    // p = new (p) B [2][1][MAX / 4 - 2];
+
+    p = new (p) B [2][1][MAX / 4 - 3];   // okay
+    p = new (p) B [2][1][MAX / 4 - 4];   // okay
+
+    p = new (p) B [2][2][MAX];          // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX - 1];      // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX - 2];      // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX - 99];     // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2];      // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 1];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 2];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 3];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 4];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 5];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 6];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 7];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 2 - 8];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 4];      // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 4 - 1];  // { dg-error "size of array" }
+    p = new (p) B [2][2][MAX / 4 - 2];  // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [2][2][MAX / 8];
+    // p = new (p) B [2][2][MAX / 8 - 1];
+
+    p = new (p) B [2][2][MAX / 8 - 2];
+    p = new (p) B [2][2][MAX / 8 - 3];
+
+    p = new (p) B [2][MAX][2];          // { dg-error "size of array" }
+    p = new (p) B [2][MAX - 1][2];      // { dg-error "size of array" }
+    p = new (p) B [2][MAX - 2][2];      // { dg-error "size of array" }
+    p = new (p) B [2][MAX - 99][2];     // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2][2];      // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 1][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 2][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 3][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 4][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 5][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 6][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 7][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 2 - 8][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 4][2];      // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 4 - 1][2];  // { dg-error "size of array" }
+    p = new (p) B [2][MAX / 4 - 2][2];  // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [2][MAX / 8][2];
+    // p = new (p) B [2][MAX / 8 - 1][2];
+
+    p = new (p) B [2][MAX / 8 - 2][2];
+    p = new (p) B [2][MAX / 8 - 3][2];
+
+    p = new (p) B [MAX][2][2];          // { dg-error "size of array" }
+    p = new (p) B [MAX - 1][2][2];      // { dg-error "size of array" }
+    p = new (p) B [MAX - 2][2][2];      // { dg-error "size of array" }
+    p = new (p) B [MAX - 99][2][2];     // { dg-error "size of array" }
+    p = new (p) B [MAX / 2][2][2];      // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 1][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 2][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 3][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 4][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 5][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 6][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 7][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 2 - 8][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 4][2][2];      // { dg-error "size of array" }
+    p = new (p) B [MAX / 4 - 1][2][2];  // { dg-error "size of array" }
+    p = new (p) B [MAX / 4 - 2][2][2];  // { dg-error "size of array" }
+
+    // Avoid exercising data model-dependent expressions.
+    // p = new (p) B [MAX / 8][2][2];
+    // p = new (p) B [MAX / 8 - 1][2][2];
+
+    p = new (p) B [MAX / 8 - 2][2][2];
+    p = new (p) B [MAX / 8 - 3][2][2];
+}
diff --git a/gcc/testsuite/g++.dg/init/new45.C b/gcc/testsuite/g++.dg/init/new45.C
new file mode 100644
index 0000000..92dac18
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new45.C
@@ -0,0 +1,106 @@
+// { dg-do compile }
+// { dg-options "-O1" }
+// { dg-final { scan-assembler-not "abort" } }
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+    void abort ();
+    void* malloc (size_t);
+}
+
+struct UDClass {
+    static int n;
+    UDClass () { ++n; }
+    virtual ~UDClass () { --n; }
+};
+
+int UDClass::n;
+
+struct POD {
+    char buf [sizeof (UDClass)];
+};
+
+enum { N = 123 };
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n)
+{
+    // Verify that array new is invoked with an argument large enough
+    // for the array and a size_t cookie to store the number of elements.
+    // (This holds for classes with user-defined types but not POD types).
+    if (n != N * sizeof (UDClass) + sizeof n) abort ();
+    return malloc (n);
+}
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n, void *p)
+{
+    // Verify that the default placement array new is invoked with
+    // an argument just large enough for the array (and no cookie),
+    // regardless of whether the type is a POD or class with a user
+    // defined ctor.
+    if (n != N * sizeof (UDClass)) abort ();
+    return p;
+}
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n, POD *p)
+{
+    // Verify that placement array new overload for a POD type is
+    // invoked with an argument large enough for the array and
+    // a cookie.
+    if (n != N * sizeof (POD)) abort ();
+    return p;
+}
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n, UDClass *p)
+{
+    // Verify that placement array new overload for a class type with
+    // a user-defined ctor and dtor is invoked with an argument large
+    // enough for the array and a cookie.
+    if (n != N * sizeof (UDClass) + sizeof n) abort ();
+    return p;
+}
+
+// UDClassllocate a sufficiently large buffer to construct arrays into.
+static unsigned char buf [N * N];
+
+POD* test_new_POD ()
+{
+    // Avoid testing PODs since for those, the global new is invoked
+    // without the overhead of a cookie.
+    // return new POD [N];
+    return 0;
+}
+
+POD* test_default_placement_new_POD ()
+{
+    // Vefify that no overhead is allocated.
+    return new (buf) POD [N];
+}
+
+POD* test_overloaded_placement_new_POD ()
+{
+    // Vefify that no overhead is allocated.
+    return new ((POD*)buf) POD [N];
+}
+
+UDClass* test_new_UDClass ()
+{
+    // Vefify that space for a cookie is allocated.
+    return new UDClass [N];
+}
+
+UDClass* test_default_placement_new_UDClass ()
+{
+    // Vefify that no overhead is allocated.
+    return new (buf) UDClass [N];
+}
+
+UDClass* test_overloaded_placement_new_UDClass ()
+{
+    // Vefify that space for a cookie is allocated.
+    return new ((UDClass*)buf) UDClass [N];
+}
diff --git a/gcc/testsuite/g++.dg/other/new-size-type.C b/gcc/testsuite/g++.dg/other/new-size-type.C
index 04933fd..ad4dc10 100644
--- a/gcc/testsuite/g++.dg/other/new-size-type.C
+++ b/gcc/testsuite/g++.dg/other/new-size-type.C
@@ -5,6 +5,5 @@
 const char*
 foo()
 {
-    return new char[~static_cast<size_t>(0)];// { dg-bogus "large" }
+    return new char[~static_cast<size_t>(0)];// { dg-error "size of array" }
 }
-

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