aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2001-07-19 04:27:16 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2001-07-19 04:27:16 +0000
commitdbc957f103982bd3d8cb973beb26439d4e99ad8c (patch)
tree55d1f67ed10772a2950b1029d8cfb2d9fe75bb8e /gcc/cp
parent8458e9540166e45e4e9501cf2ae5a9aeb49b1468 (diff)
downloadgcc-dbc957f103982bd3d8cb973beb26439d4e99ad8c.zip
gcc-dbc957f103982bd3d8cb973beb26439d4e99ad8c.tar.gz
gcc-dbc957f103982bd3d8cb973beb26439d4e99ad8c.tar.bz2
class.c (type_requires_array_cookie): New function.
* class.c (type_requires_array_cookie): New function. (check_methods): Don't try to figure out whether the type needs a cookie here. (check_bases_and_members): Set TYPE_VEC_NEW_USES_COOKIE here. * cp-tree.h (TYPE_VEC_DELETE_TAKES_SIZE): Remove. (TYPE_VEC_NEW_USES_COOKIE): Reimplement. * pt.c (instantiate_class_template): Don't set TYPE_VEC_DELETE_TAKES_SIZE. * NEWS: Document ABI changes from GCC 3.0. From-SVN: r44142
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/NEWS36
-rw-r--r--gcc/cp/class.c86
-rw-r--r--gcc/cp/cp-tree.h18
-rw-r--r--gcc/cp/pt.c1
5 files changed, 112 insertions, 41 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 78602c7..6825721 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2001-07-18 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (type_requires_array_cookie): New function.
+ (check_methods): Don't try to figure out whether the type needs a
+ cookie here.
+ (check_bases_and_members): Set TYPE_VEC_NEW_USES_COOKIE here.
+ * cp-tree.h (TYPE_VEC_DELETE_TAKES_SIZE): Remove.
+ (TYPE_VEC_NEW_USES_COOKIE): Reimplement.
+ * pt.c (instantiate_class_template): Don't set
+ TYPE_VEC_DELETE_TAKES_SIZE.
+ * NEWS: Document ABI changes from GCC 3.0.
+
2001-07-18 Xavier Delacour <xavier@fmaudio.net>,
Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
diff --git a/gcc/cp/NEWS b/gcc/cp/NEWS
index 966572c..69b6fb4 100644
--- a/gcc/cp/NEWS
+++ b/gcc/cp/NEWS
@@ -1,5 +1,41 @@
*** Changes in GCC 3.1:
+* The C++ ABI has been changed to correctly handle this code:
+
+ struct A {
+ void operator delete[] (void *, size_t);
+ };
+
+ struct B : public A {
+ };
+
+ new B[10];
+
+ The amount of storage allocated for the array will be greater than
+ it was in 3.0, in order to store the number of elements in the
+ array, so that the correct size can be passed to `operator delete[]'
+ when the array is deleted. Previously, the value passed to
+ `operator delete[]' was unpredictable.
+
+ This change will only affect code that declares a two-argument
+ `operator delete[]' with a second parameter of type `size_t'
+ in a base class, and does not override that definition in a
+ derived class.
+
+* The C++ ABI has been changed so that:
+
+ struct A {
+ void operator delete[] (void *, size_t);
+ void operator delete[] (void *);
+ };
+
+ does not cause unncessary storage to be allocated when an array of
+ `A' objects is allocated.
+
+ This change will only affect code that declares both of these
+ forms of `operator delete[]', and declared the two-argument form
+ before the one-argument form.
+
*** Changes in GCC 3.0:
* Support for guiding declarations has been removed.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 2ec3448..c3aa297 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -218,6 +218,7 @@ static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
static void warn_about_ambiguous_direct_bases PARAMS ((tree));
+static bool type_requires_array_cookie PARAMS ((tree));
/* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
@@ -4210,7 +4211,6 @@ check_methods (t)
tree t;
{
tree x;
- int seen_one_arg_array_delete_p = 0;
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
@@ -4234,32 +4234,6 @@ check_methods (t)
CLASSTYPE_PURE_VIRTUALS (t)
= tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t));
}
-
- if (DECL_ARRAY_DELETE_OPERATOR_P (x))
- {
- tree second_parm;
-
- /* When dynamically allocating an array of this type, we
- need a "cookie" to record how many elements we allocated,
- even if the array elements have no non-trivial
- destructor, if the usual array deallocation function
- takes a second argument of type size_t. The standard (in
- [class.free]) requires that the second argument be set
- correctly. */
- second_parm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (x)));
- /* Under the new ABI, we choose only those function that are
- explicitly declared as `operator delete[] (void *,
- size_t)'. */
- if (!seen_one_arg_array_delete_p
- && second_parm
- && TREE_CHAIN (second_parm) == void_list_node
- && same_type_p (TREE_VALUE (second_parm), sizetype))
- TYPE_VEC_DELETE_TAKES_SIZE (t) = 1;
- /* If there's no second parameter, then this is the usual
- deallocation function. */
- else if (second_parm == void_list_node)
- seen_one_arg_array_delete_p = 1;
- }
}
}
@@ -4556,6 +4530,59 @@ remove_zero_width_bit_fields (t)
}
}
+/* Returns TRUE iff we need a cookie when dynamically allocating an
+ array whose elements have the indicated class TYPE. */
+
+static bool
+type_requires_array_cookie (type)
+ tree type;
+{
+ tree fns;
+ bool has_two_argument_delete_p;
+
+ my_friendly_assert (CLASS_TYPE_P (type), 20010712);
+
+ /* If there's a non-trivial destructor, we need a cookie. In order
+ to iterate through the array calling the destructor for each
+ element, we'll have to know how many elements there are. */
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ return true;
+
+ /* If the usual deallocation function is a two-argument whose second
+ argument is of type `size_t', then we have to pass the size of
+ the array to the deallocation function, so we will need to store
+ a cookie. */
+ fns = lookup_fnfields (TYPE_BINFO (type),
+ ansi_opname (VEC_DELETE_EXPR),
+ /*protect=*/0);
+ /* If there are no `operator []' members, or the lookup is
+ ambiguous, then we don't need a cookie. */
+ if (!fns || fns == error_mark_node)
+ return false;
+ /* Loop through all of the functions. */
+ for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn;
+ tree second_parm;
+
+ /* Select the current function. */
+ fn = OVL_CURRENT (fns);
+ /* See if this function is a one-argument delete function. If
+ it is, then it will be the usual deallocation function. */
+ second_parm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
+ if (second_parm == void_list_node)
+ return false;
+ /* Otherwise, if we have a two-argument function and the second
+ argument is `size_t', it will be the usual deallocation
+ function -- unless there is one-argument function, too. */
+ if (TREE_CHAIN (second_parm) == void_list_node
+ && same_type_p (TREE_VALUE (second_parm), sizetype))
+ has_two_argument_delete_p = true;
+ }
+
+ return has_two_argument_delete_p;
+}
+
/* Check the validity of the bases and members declared in T. Add any
implicitly-generated functions (like copy-constructors and
assignment operators). Compute various flag bits (like
@@ -4641,6 +4668,11 @@ check_bases_and_members (t, empty_p)
/* Build and sort the CLASSTYPE_METHOD_VEC. */
finish_struct_methods (t);
+
+ /* Figure out whether or not we will need a cookie when dynamically
+ allocating an array of this type. */
+ TYPE_LANG_SPECIFIC (t)->vec_new_uses_cookie
+ = type_requires_array_cookie (t);
}
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e8a61a8..b32bd0c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1291,7 +1291,7 @@ struct lang_type
unsigned needs_virtual_reinit : 1;
unsigned marks: 6;
- unsigned vec_delete_takes_size : 1;
+ unsigned vec_new_uses_cookie : 1;
unsigned declared_class : 1;
unsigned being_defined : 1;
@@ -1353,19 +1353,11 @@ struct lang_type
#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_delete)
#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
-/* Nonzero for _CLASSTYPE means that operator vec delete is defined and
- takes the optional size_t argument. */
-#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \
- (TYPE_LANG_SPECIFIC(NODE)->vec_delete_takes_size)
-
/* Nonzero if `new NODE[x]' should cause the allocation of extra
- storage to indicate how many array elements are in use. The old
- ABI had a bug in that we always allocate the extra storage if NODE
- has a two-argument array operator delete. */
-#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
- (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (NODE) \
- || (TYPE_LANG_SPECIFIC (NODE) \
- && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
+ storage to indicate how many array elements are in use. */
+#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
+ (CLASS_TYPE_P (NODE) \
+ && TYPE_LANG_SPECIFIC (NODE)->vec_new_uses_cookie)
/* Nonzero means that this _CLASSTYPE node defines ways of converting
itself to other types. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3d6279a..d09ce8f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4988,7 +4988,6 @@ instantiate_class_template (type)
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
- TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);