177 lines
4.2 KiB
Diff
177 lines
4.2 KiB
Diff
2012-10-31 Florian Weimer <fweimer@redhat.com>
|
|
|
|
* init.c (build_new_1): Do not check for arithmetic overflow if
|
|
inner array size is 1.
|
|
|
|
* g++.dg/init/new40.C: New.
|
|
|
|
--- gcc/cp/init.c (revision 193033)
|
|
+++ gcc/cp/init.c (working copy)
|
|
@@ -2176,6 +2176,8 @@ build_new_1 (VEC(tree,gc) **placement, t
|
|
double_int inner_nelts_count = double_int_one;
|
|
tree inner_nelts = NULL_TREE;
|
|
tree alloc_call, alloc_expr;
|
|
+ /* Size of the inner array elements. */
|
|
+ double_int inner_size;
|
|
/* The address returned by the call to "operator new". This node is
|
|
a VAR_DECL and is therefore reusable. */
|
|
tree alloc_node;
|
|
@@ -2318,8 +2320,6 @@ build_new_1 (VEC(tree,gc) **placement, t
|
|
double_int max_size
|
|
= double_int_lshift (double_int_one, TYPE_PRECISION (sizetype) - 1,
|
|
HOST_BITS_PER_DOUBLE_INT, false);
|
|
- /* Size of the inner array elements. */
|
|
- double_int inner_size;
|
|
/* Maximum number of outer elements which can be allocated. */
|
|
double_int max_outer_nelts;
|
|
tree max_outer_nelts_tree;
|
|
@@ -2438,7 +2438,15 @@ build_new_1 (VEC(tree,gc) **placement, t
|
|
if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
|
|
size = size_binop (PLUS_EXPR, size, cookie_size);
|
|
else
|
|
- cookie_size = NULL_TREE;
|
|
+ {
|
|
+ cookie_size = NULL_TREE;
|
|
+ /* No size arithmetic necessary, so the size check is
|
|
+ not needed. */
|
|
+ if (outer_nelts_check != NULL
|
|
+ && double_int_one_p (inner_size)
|
|
+ && inner_nelts == NULL_TREE)
|
|
+ outer_nelts_check = NULL_TREE;
|
|
+ }
|
|
/* Perform the overflow check. */
|
|
if (outer_nelts_check != NULL_TREE)
|
|
size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check,
|
|
@@ -2474,7 +2482,15 @@ build_new_1 (VEC(tree,gc) **placement, t
|
|
/* Use a global operator new. */
|
|
/* See if a cookie might be required. */
|
|
if (!(array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)))
|
|
- cookie_size = NULL_TREE;
|
|
+ {
|
|
+ cookie_size = NULL_TREE;
|
|
+ /* No size arithmetic necessary, so the size check is
|
|
+ not needed. */
|
|
+ if (outer_nelts_check != NULL
|
|
+ && double_int_one_p (inner_size)
|
|
+ && inner_nelts == NULL_TREE)
|
|
+ outer_nelts_check = NULL_TREE;
|
|
+ }
|
|
|
|
alloc_call = build_operator_new_call (fnname, placement,
|
|
&size, &cookie_size,
|
|
--- gcc/testsuite/g++.dg/init/new40.C (revision 0)
|
|
+++ gcc/testsuite/g++.dg/init/new40.C (working copy)
|
|
@@ -0,0 +1,112 @@
|
|
+// Testcase for overflow handling in operator new[].
|
|
+// Optimization of unnecessary overflow checks.
|
|
+// { dg-do run }
|
|
+
|
|
+#include <assert.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdexcept>
|
|
+
|
|
+static size_t magic_allocation_size
|
|
+ = 1 + (size_t (1) << (sizeof (size_t) * 8 - 1));
|
|
+
|
|
+struct exc : std::bad_alloc {
|
|
+};
|
|
+
|
|
+static size_t expected_size;
|
|
+
|
|
+struct pod_with_new {
|
|
+ char ch;
|
|
+ void *operator new[] (size_t sz)
|
|
+ {
|
|
+ if (sz != expected_size)
|
|
+ abort ();
|
|
+ throw exc ();
|
|
+ }
|
|
+};
|
|
+
|
|
+struct with_new {
|
|
+ char ch;
|
|
+ with_new () { }
|
|
+ ~with_new () { }
|
|
+ void *operator new[] (size_t sz)
|
|
+ {
|
|
+ if (sz != size_t (-1))
|
|
+ abort ();
|
|
+ throw exc ();
|
|
+ }
|
|
+};
|
|
+
|
|
+struct non_pod {
|
|
+ char ch;
|
|
+ non_pod () { }
|
|
+ ~non_pod () { }
|
|
+};
|
|
+
|
|
+void *
|
|
+operator new (size_t sz) _GLIBCXX_THROW (std::bad_alloc)
|
|
+{
|
|
+ if (sz != expected_size)
|
|
+ abort ();
|
|
+ throw exc ();
|
|
+}
|
|
+
|
|
+int
|
|
+main ()
|
|
+{
|
|
+ if (sizeof (pod_with_new) == 1)
|
|
+ expected_size = magic_allocation_size;
|
|
+ else
|
|
+ expected_size = -1;
|
|
+
|
|
+ try {
|
|
+ new pod_with_new[magic_allocation_size];
|
|
+ abort ();
|
|
+ } catch (exc &) {
|
|
+ }
|
|
+
|
|
+ if (sizeof (with_new) == 1)
|
|
+ expected_size = magic_allocation_size;
|
|
+ else
|
|
+ expected_size = -1;
|
|
+
|
|
+ try {
|
|
+ new with_new[magic_allocation_size];
|
|
+ abort ();
|
|
+ } catch (exc &) {
|
|
+ }
|
|
+
|
|
+ expected_size = magic_allocation_size;
|
|
+ try {
|
|
+ new char[magic_allocation_size];
|
|
+ abort ();
|
|
+ } catch (exc &) {
|
|
+ }
|
|
+
|
|
+ expected_size = -1;
|
|
+
|
|
+ try {
|
|
+ new pod_with_new[magic_allocation_size][2];
|
|
+ abort ();
|
|
+ } catch (exc &) {
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ new with_new[magic_allocation_size][2];
|
|
+ abort ();
|
|
+ } catch (exc &) {
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ new char[magic_allocation_size][2];
|
|
+ abort ();
|
|
+ } catch (exc &) {
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ new non_pod[magic_allocation_size];
|
|
+ abort ();
|
|
+ } catch (exc &) {
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|