This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PING] Re: [PATCH] c++/67913, 67917 - fix new expression with wrong number of elements
- From: Martin Sebor <msebor at gmail dot com>
- To: Jason Merrill <jason at redhat dot com>, Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 05 Nov 2015 12:30:08 -0700
- Subject: Re: [PING] Re: [PATCH] c++/67913, 67917 - fix new expression with wrong number of elements
- Authentication-results: sourceware.org; auth=none
- References: <562573AF dot 7080105 at gmail dot com> <562EDC2C dot 7080507 at gmail dot com> <56383E4E dot 4040005 at redhat dot com>
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" }
}
-