PR c++/67913 - new expression with negative size not diagnosed
authorMartin Sebor <msebor@redhat.com>
Tue, 10 Nov 2015 02:23:34 +0000 (02:23 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Tue, 10 Nov 2015 02:23:34 +0000 (19:23 -0700)
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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/new43.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/new44.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/new45.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/new-size-type.C

index 91cbf067dba3a83f47e056629e73b6c9cfc180f0..fee374a9953b631b3968133ed360038fa21d4dd9 100644 (file)
@@ -1,3 +1,14 @@
+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>
index 0b7d143c557684ccf91830fc4c35b53a59848dca..13d84384462f2bdf1182e125edf135f17b204f42 100644 (file)
@@ -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);
-          /* 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));
+          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;
         }
index b45281f517db704ff11c8806380e71af4c89adb0..2e11acb6a67d0cc769f977187d62a71f72905061 100644 (file)
@@ -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,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);
-      /* 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);
 
       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);
+
+      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);
+
+          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));
     }
index 0da08e4db41d162f2fafa8d4392f63b9a4bbb744..a6f6ed839978f24dd0e52ee53b30b33900a58a89 100644 (file)
@@ -1,3 +1,19 @@
+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.
diff --git a/gcc/testsuite/g++.dg/init/new43.C b/gcc/testsuite/g++.dg/init/new43.C
new file mode 100644 (file)
index 0000000..9b08667
--- /dev/null
@@ -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 (file)
index 0000000..d6ff86a
--- /dev/null
@@ -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 (file)
index 0000000..92dac18
--- /dev/null
@@ -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];
+}
index 04933fd4a2c1d7d94cbed6cd2c0d3dc45a2129a5..ad4dc102c3bd0518bba89cc2255b1cda7c9732d2 100644 (file)
@@ -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" }
 }
-