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>
Cesar Philippidis <cesar@codesourcery.com>
James Norris <jnorris@codesourcery.com>
......
......@@ -4235,10 +4235,13 @@ 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;
}
......
......@@ -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
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,
......@@ -2502,13 +2506,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. */
......@@ -2702,21 +2709,42 @@ 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;
......@@ -3290,6 +3318,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));
}
......
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>
* 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 @@
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" }
}
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