Commit 685c8340 by Martin Sebor Committed by Martin Sebor

PR c++/67913 - new expression with negative size not diagnosed

PR c++/67913 - new expression with negative size not diagnosed
PR c++/67927 - array new expression with excessive number of elements
               not diagnosed 

gcc/cp/
	* 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/
	* init/new45.C: New test to verify that operator new is invoked
	with or without overhead for a cookie.
	* init/new44.C: New test for placement new expressions for arrays
	with excessive number of elements.
	* 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.

From-SVN: r230081
parent 36fa0f5f
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.
2015-11-09 Thomas Schwinge <thomas@codesourcery.com> 2015-11-09 Thomas Schwinge <thomas@codesourcery.com>
Cesar Philippidis <cesar@codesourcery.com> Cesar Philippidis <cesar@codesourcery.com>
James Norris <jnorris@codesourcery.com> James Norris <jnorris@codesourcery.com>
......
...@@ -4235,10 +4235,13 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args, ...@@ -4235,10 +4235,13 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
{ {
/* Update the total size. */ /* Update the total size. */
*size = size_binop (PLUS_EXPR, original_size, *cookie_size); *size = size_binop (PLUS_EXPR, original_size, *cookie_size);
/* Set to (size_t)-1 if the size check fails. */ if (size_check)
gcc_assert (size_check != NULL_TREE); {
*size = fold_build3 (COND_EXPR, sizetype, size_check, /* Set to (size_t)-1 if the size check fails. */
*size, TYPE_MAX_VALUE (sizetype)); 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. */ /* Update the argument list to reflect the adjusted size. */
(**args)[0] = *size; (**args)[0] = *size;
} }
......
...@@ -2482,7 +2482,11 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper) ...@@ -2482,7 +2482,11 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
/* Generate code for a new-expression, including calling the "operator /* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for 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 static tree
build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
...@@ -2502,13 +2506,16 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, ...@@ -2502,13 +2506,16 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
type.) */ type.) */
tree pointer_type; tree pointer_type;
tree non_const_pointer_type; tree non_const_pointer_type;
/* The most significant array bound in int[OUTER_NELTS][inner]. */
tree outer_nelts = NULL_TREE; 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; tree outer_nelts_check = NULL_TREE;
bool outer_nelts_from_type = false; bool outer_nelts_from_type = false;
/* Number of the "inner" elements in "new T[OUTER_NELTS][inner]". */
offset_int inner_nelts_count = 1; offset_int inner_nelts_count = 1;
tree alloc_call, alloc_expr; 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; offset_int inner_size;
/* The address returned by the call to "operator new". This node is /* The address returned by the call to "operator new". This node is
a VAR_DECL and is therefore reusable. */ a VAR_DECL and is therefore reusable. */
...@@ -2702,20 +2709,41 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, ...@@ -2702,20 +2709,41 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
} }
max_outer_nelts = wi::udiv_trunc (max_size, inner_size); 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. */
{
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); max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
outer_nelts, if (TREE_CONSTANT (outer_nelts))
max_outer_nelts_tree); {
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);
outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
outer_nelts,
max_outer_nelts_tree);
}
} }
alloc_fn = NULL_TREE; alloc_fn = NULL_TREE;
...@@ -3290,6 +3318,23 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts, ...@@ -3290,6 +3318,23 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
else else
return error_mark_node; 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 = mark_rvalue_use (nelts);
nelts = cp_save_expr (cp_convert (sizetype, nelts, complain)); nelts = cp_save_expr (cp_convert (sizetype, nelts, complain));
} }
......
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.
2015-11-09 Nathan Sidwell <nathan@codesourcery.com> 2015-11-09 Nathan Sidwell <nathan@codesourcery.com>
* c-c++-common/goacc/routine-1.c: New. * c-c++-common/goacc/routine-1.c: New.
......
/* { 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" }
}
// { 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];
}
// { 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];
}
...@@ -5,6 +5,5 @@ ...@@ -5,6 +5,5 @@
const char* const char*
foo() 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" }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment