aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-03-03 02:27:15 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2000-03-03 02:27:15 +0000
commit834c6dff7ba7845c7fabeda67f711b5aa0f341d8 (patch)
treedb09bd0c5719c40d563da6f148b6e0c062ae1ce1 /gcc
parenta2b10a92a30b30c5f1fa5324daa7e41bc162db95 (diff)
downloadgcc-834c6dff7ba7845c7fabeda67f711b5aa0f341d8.zip
gcc-834c6dff7ba7845c7fabeda67f711b5aa0f341d8.tar.gz
gcc-834c6dff7ba7845c7fabeda67f711b5aa0f341d8.tar.bz2
* tree.h (TYPE_ALIGN_UNIT): New macro.
From-SVN: r32302
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/cp/ChangeLog61
-rw-r--r--gcc/cp/call.c25
-rw-r--r--gcc/cp/class.c51
-rw-r--r--gcc/cp/cp-tree.h60
-rw-r--r--gcc/cp/decl.c36
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/g++spec.c22
-rw-r--r--gcc/cp/init.c226
-rw-r--r--gcc/cp/lex.c2
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/cp/ptree.c6
-rw-r--r--gcc/cp/search.c4
-rw-r--r--gcc/cp/tree.c14
-rw-r--r--gcc/cp/typeck.c4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/arraynew.C127
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/inline7.C1
-rw-r--r--gcc/tree.h4
18 files changed, 502 insertions, 150 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 543b24e..d0eee38 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2000-03-02 Mark Mitchell <mark@codesourcery.com>
+
+ * tree.h (TYPE_ALIGN_UNIT): New macro.
+
2000-03-02 Clinton Popetz <cpopetz@cygnus.com>
* config/i386/i386.c: (constant_call_address_operand): Reject
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b3c5092..d9bb284 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,64 @@
+2000-03-02 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (TYPE_NEEDS_DESTRUCTOR): Rename to ...
+ (TYPE_HAS_NONTRIVIAL_DESTRUCTOR): ... this.
+ (TYPE_HAS_TRIVIAL_DESTRUCTOR): New macro.
+ (lang_type): Split gets_new into has_new and has_array_new.
+ (TYPE_VEC_NEW_USES_COOKIE): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
+ (TYPE_GETS_NEW): Split into ...
+ (TYPE_HAS_NEW_OPERATOR): ... this, and ...
+ (TYPE_HAS_ARRAY_NEW_OPERATOR): ... this.
+ (DECL_ARRAY_DELETE_OPERATOR_P): New macro
+ (build_op_new_call): Don't declare.
+ (build_new_1): Likewise.
+ * call.c (build_op_new_call): Remove.
+ * class.c (check_bases): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR
+ instead of TYPE_NEEDS_DESTRUCTOR.
+ (finish_struct_bits): Likewise.
+ (add_implicitly_declared_members): Likewise.
+ (check_field_decl): Likewise.
+ (check_methods): Set TYPE_VEC_DELETE_TAKES_SIZE here, and set it
+ correctly under the new ABI.
+ * decl.c (start_decl_1): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR
+ instead of TYPE_NEEDS_DESTRUCTOR.
+ (initialize_local_var): Likewise.
+ (destroy_local_var): Likewise.
+ (cp_finish_decl): Likewise.
+ (register_dtor_fn): Likewise.
+ (grok_op_properties): Set TYPE_HAS_NEW_OPERATOR and
+ TYPE_HAS_ARRAY_NEW_OPERATOR, not TYPE_HAS_NEW. Don't set
+ TYPE_VEC_DELETE_TAKES_SIZE here.
+ (xref_basetypes): Set TYPE_HAS_NEW_OPERATOR and
+ TYPE_HAS_ARRAY_NEW_OPERATOR, not TYPE_HAS_NEW.
+ (store_parm_decls): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
+ (finish_destructor_body): Likewise.
+ (maybe_build_cleanup_1): Likewise.
+ * decl2.c (do_static_destruction): Likewise.
+ * init.c (build_new_1): Make it static.
+ (perform_member_init): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
+ (expand_cleanup_for_base): Likewise.
+ (get_cookie_size): New function.
+ (build_new_1): Handle array-new cookies correctly under the new
+ ABI.
+ (build_vec_delete_1): Likewise.
+ (build_vec_init): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
+ (build_delete): Likewise.
+ (build_vec_delete): Handle array-new cookies correctly under the new
+ ABI.
+ * lex.c (do_identifier): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
+ * pt.c (instantiate_class_template): Set TYPE_HAS_NEW_OPERATOR and
+ TYPE_HAS_ARRAY_NEW_OPERATOR.
+ * ptree.c (print_lang_type): Check them.
+ * search.c (context_for_name_lookup): Fix typo in comment.
+ (tree_has_any_destructor_p): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
+ * tree.c (break_out_cleanups): Likewise.
+ (build_cplus_array_test_1): Likewise.
+ (cp_build_qualified_type_real): Likewise.
+ * typeck.c (complete_type): Likewise.
+
+ * g++spec.c (lang_specific_driver): Add -fnew-abi at the start of
+ the command-line, not the end.
+
2000-03-01 Jason Merrill <jason@casey.cygnus.com>
* pt.c (instantiate_decl): Clear TI_PENDING_TEMPLATE_FLAG.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8ced478..72c4ccb 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3452,31 +3452,6 @@ builtin:
}
}
-/* Build up a call to operator new. This has to be handled differently
- from other operators in the way lookup is handled; first members are
- considered, then globals. CODE is either NEW_EXPR or VEC_NEW_EXPR.
- TYPE is the type to be created. ARGS are any new-placement args.
- FLAGS are the usual overloading flags. */
-
-tree
-build_op_new_call (code, type, args, flags)
- enum tree_code code;
- tree type, args;
- int flags;
-{
- tree fnname = ansi_opname[code];
-
- if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
- && (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
- {
- return build_method_call (build_dummy_object (type),
- fnname, args, NULL_TREE, flags);
- }
- else
- return build_new_function_call
- (lookup_function_nonclass (fnname, args), args);
-}
-
/* Build a call to operator delete. This has to be handled very specially,
because the restrictions on what signatures match are different from all
other call instances. For a normal delete, only a delete taking (void *)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3f922ef..c76146a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1934,7 +1934,8 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
/* A lot of properties from the bases also apply to the derived
class. */
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype);
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
@@ -2079,7 +2080,8 @@ finish_struct_bits (t)
TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
- TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (variants)
= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);
@@ -3503,14 +3505,14 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
tree *f;
/* Destructor. */
- if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
{
default_fn = cons_up_default_function (t, name, 0);
check_for_override (default_fn, t);
/* If we couldn't make it work, then pretend we didn't need it. */
if (default_fn == void_type_node)
- TYPE_NEEDS_DESTRUCTOR (t) = 0;
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 0;
else
{
TREE_CHAIN (default_fn) = implicit_fns;
@@ -3520,7 +3522,9 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
virtual_dtor = default_fn;
}
}
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
+ else
+ /* Any non-implicit destructor is non-trivial. */
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
/* Default constructor. */
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
@@ -3744,7 +3748,7 @@ check_field_decl (field, t, cant_have_const_ctor,
if (TYPE_NEEDS_CONSTRUCTING (type))
cp_error_at ("member `%#D' with constructor not allowed in union",
field);
- if (TYPE_NEEDS_DESTRUCTOR (type))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
cp_error_at ("member `%#D' with destructor not allowed in union",
field);
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
@@ -3754,7 +3758,8 @@ check_field_decl (field, t, cant_have_const_ctor,
else
{
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
}
@@ -4268,6 +4273,7 @@ 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))
{
@@ -4291,6 +4297,37 @@ 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)));
+ /* This is overly conservative, but we must maintain this
+ behavior for backwards compatibility. */
+ if (!flag_new_abi && second_parm != void_list_node)
+ TYPE_VEC_DELETE_TAKES_SIZE (t) = 1;
+ /* Under the new ABI, we choose only those function that are
+ explicitly declared as `operator delete[] (void *,
+ size_t)'. */
+ else if (flag_new_abi
+ && !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;
+ }
}
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3c46940..ce2b94c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -81,7 +81,7 @@ Boston, MA 02111-1307, USA. */
1: TYPE_HAS_CONSTRUCTOR.
2: TYPE_HAS_DESTRUCTOR.
3: TYPE_FOR_JAVA.
- 4: TYPE_NEEDS_DESTRUCTOR.
+ 4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
5: IS_AGGR_TYPE.
6: TYPE_BUILT_IN.
@@ -1310,7 +1310,8 @@ struct lang_type
unsigned has_nonpublic_assign_ref : 2;
unsigned vtable_needs_writing : 1;
unsigned has_assign_ref : 1;
- unsigned gets_new : 2;
+ unsigned has_new : 1;
+ unsigned has_array_new : 1;
unsigned gets_delete : 2;
unsigned has_call_overloaded : 1;
@@ -1391,9 +1392,7 @@ struct lang_type
/* List of friends which were defined inline in this class definition. */
#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
-/* Nonzero for _CLASSTYPE means that operator new and delete are defined,
- respectively. */
-#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_new)
+/* Nonzero for _CLASSTYPE means that operator delete is defined. */
#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_delete)
#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
@@ -1401,9 +1400,15 @@ struct lang_type
takes the optional size_t argument. */
#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \
(TYPE_LANG_SPECIFIC(NODE)->vec_delete_takes_size)
-#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
- (TYPE_NEEDS_DESTRUCTOR (NODE) \
- || (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
+
+/* 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)))
/* Nonzero means that this _CLASSTYPE node defines ways of converting
itself to other types. */
@@ -1417,6 +1422,15 @@ struct lang_type
#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_init_ref)
#define TYPE_HAS_CONST_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_const_init_ref)
+/* Nonzero if this class defines an overloaded operator new. (An
+ operator new [] doesn't count.) */
+#define TYPE_HAS_NEW_OPERATOR(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE)->has_new)
+
+/* Nonzero if this class defines an overloaded operator new[]. */
+#define TYPE_HAS_ARRAY_NEW_OPERATOR(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE)->has_array_new)
+
/* Nonzero means that this type is being defined. I.e., the left brace
starting the definition of this type has been seen. */
#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->being_defined)
@@ -1916,6 +1930,10 @@ struct lang_decl
#define SET_DECL_TINFO_FN_P(NODE) \
(DECL_LANG_SPECIFIC((NODE))->decl_flags.mutable_flag = 1)
+/* Nonzero if NODE is an overloaded `operator delete[]' function. */
+#define DECL_ARRAY_DELETE_OPERATOR_P(NODE) \
+ (DECL_NAME (NODE) == ansi_opname[(int) VEC_DELETE_EXPR])
+
/* Nonzero for _DECL means that this decl appears in (or will appear
in) as a member in a RECORD_TYPE or UNION_TYPE node. It is also for
detecting circularity in case members are multiply defined. In the
@@ -2410,10 +2428,26 @@ extern int flag_new_for_scope;
#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_abstract_assign_ref)
#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_complex_init_ref)
-/* Nonzero for _TYPE node means that destroying an object of this type
- will involve a call to a destructor. This can apply to objects
- of ARRAY_TYPE is the type of the elements needs a destructor. */
-#define TYPE_NEEDS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4(NODE))
+/* Nonzero if TYPE has a trivial destructor. From [class.dtor]:
+
+ A destructor is trivial if it is an implicitly declared
+ destructor and if:
+
+ - all of the direct base classes of its class have trivial
+ destructors,
+
+ - for all of the non-static data members of its class that are
+ of class type (or array thereof), each such class has a
+ trivial destructor. */
+#define TYPE_HAS_TRIVIAL_DESTRUCTOR(NODE) \
+ (!TYPE_HAS_NONTRIVIAL_DESTRUCTOR (NODE))
+
+/* Nonzero for _TYPE node means that this type does not have a trivial
+ destructor. Therefore, destroying an object of this type will
+ involve a call to a destructor. This can apply to objects of
+ ARRAY_TYPE is the type of the elements needs a destructor. */
+#define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \
+ (TYPE_LANG_FLAG_4(NODE))
/* Nonzero for class type means that initialization of this type can use
a bitwise copy. */
@@ -3578,7 +3612,6 @@ extern tree type_decays_to PARAMS ((tree));
extern tree build_user_type_conversion PARAMS ((tree, tree, int));
extern tree build_new_function_call PARAMS ((tree, tree));
extern tree build_new_op PARAMS ((enum tree_code, int, tree, tree, tree));
-extern tree build_op_new_call PARAMS ((enum tree_code, tree, tree, int));
extern tree build_op_delete_call PARAMS ((enum tree_code, tree, tree, int, tree));
extern int can_convert PARAMS ((tree, tree));
extern int can_convert_arg PARAMS ((tree, tree, tree));
@@ -3922,7 +3955,6 @@ extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree));
extern tree decl_constant_value PARAMS ((tree));
extern tree build_new PARAMS ((tree, tree, tree, int));
-extern tree build_new_1 PARAMS ((tree));
extern tree build_vec_init PARAMS ((tree, tree, tree, tree, int));
extern tree build_x_delete PARAMS ((tree, int, tree));
extern tree build_delete PARAMS ((tree, tree, tree, int, int));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9d4301b..df8e008 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6844,7 +6844,7 @@ start_decl_1 (decl)
/* If this type of object needs a cleanup, but we're not allowed to
add any more objects with cleanups to the current scope, create a
new binding level. */
- if (TYPE_NEEDS_DESTRUCTOR (type)
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
&& current_binding_level->more_cleanups_ok == 0)
{
keep_next_level (2);
@@ -7490,7 +7490,7 @@ initialize_local_var (decl, init, flags)
if (TREE_STATIC (decl))
{
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
- || TYPE_NEEDS_DESTRUCTOR (type))
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
expand_static_init (decl, init);
return;
}
@@ -7522,7 +7522,7 @@ initialize_local_var (decl, init, flags)
marked used. (see TREE_USED, above.) */
if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used
- && !TYPE_NEEDS_DESTRUCTOR (type)
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
&& DECL_NAME (decl))
TREE_USED (decl) = 0;
else if (already_used)
@@ -7544,7 +7544,7 @@ destroy_local_var (decl)
return;
/* And only things with destructors need cleaning up. */
- if (!TYPE_NEEDS_DESTRUCTOR (type))
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
return;
if (TREE_CODE (decl) == VAR_DECL &&
@@ -7820,7 +7820,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
{
/* Cleanups for static variables are handled by `finish_file'. */
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
- || TYPE_NEEDS_DESTRUCTOR (type))
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
expand_static_init (decl, init);
}
finish_end0:
@@ -8054,7 +8054,7 @@ register_dtor_fn (decl)
int saved_flag_access_control;
- if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
/* Call build_cleanup before we enter the anonymous function so that
@@ -11856,11 +11856,11 @@ grok_op_properties (decl, virtualp, friendp)
|| name == ansi_opname[(int) MEMBER_REF])
TYPE_OVERLOADS_ARROW (current_class_type) = 1;
else if (name == ansi_opname[(int) NEW_EXPR])
- TYPE_GETS_NEW (current_class_type) |= 1;
+ TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
else if (name == ansi_opname[(int) DELETE_EXPR])
TYPE_GETS_DELETE (current_class_type) |= 1;
else if (name == ansi_opname[(int) VEC_NEW_EXPR])
- TYPE_GETS_NEW (current_class_type) |= 2;
+ TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
TYPE_GETS_DELETE (current_class_type) |= 2;
}
@@ -11894,14 +11894,7 @@ grok_op_properties (decl, virtualp, friendp)
hash_tree_chain (ptr_type_node,
void_list_node));
else
- {
- TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
-
- if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR]
- && (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
- != void_list_node))
- TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1;
- }
+ TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
}
else
{
@@ -12508,7 +12501,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
if (CLASS_TYPE_P (basetype))
{
- TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+ TYPE_HAS_NEW_OPERATOR (ref)
+ |= TYPE_HAS_NEW_OPERATOR (basetype);
+ TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
+ |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
/* If the base-class uses multiple inheritance, so do we. */
TYPE_USES_MULTIPLE_INHERITANCE (ref)
@@ -13387,7 +13383,7 @@ store_parm_decls ()
cleanups = tree_cons (parm, cleanup, cleanups);
}
else if (type != error_mark_node
- && TYPE_NEEDS_DESTRUCTOR (type))
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
parms_have_cleanups = 1;
}
else
@@ -13603,7 +13599,7 @@ finish_destructor_body ()
while (vbases)
{
- if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbases)))
{
tree vb = get_vbase
(BINFO_TYPE (vbases),
@@ -14286,7 +14282,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
tree decl, auto_delete;
{
tree type = TREE_TYPE (decl);
- if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
+ if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2f9c574..b961f26 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3238,7 +3238,7 @@ do_static_destruction (decl)
my_friendly_assert (!flag_use_cxa_atexit, 20000121);
/* If we don't need a destructor, there's nothing to do. */
- if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
/* Actually do the destruction. */
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index ca1ab68..b3bab5a 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -206,8 +206,21 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
real_arglist = (char **) xmalloc (num_args * sizeof (char *));
arglist = (const char **) real_arglist;
+ i = 0;
+ j = 0;
+
+ /* Copy the 0th argument, i.e., the name of the program itself. */
+ arglist[i++] = arglist[j++];
+
+#if ENABLE_NEW_GXX_ABI
+ /* If we should use the new ABI by default, add the appropriate flag
+ to cc1plus here. We put this first so that it can be overridden
+ by other command-line options. */
+ arglist[j++] = "-fnew-abi";
+#endif
+
/* NOTE: We start at 1 now, not 0. */
- for (i = 0, j = 0; i < argc; i++, j++)
+ while (i < argc)
{
arglist[j] = argv[i];
@@ -237,11 +250,10 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
arglist[j++] = argv[i];
arglist[j] = "-xnone";
}
- }
-#if ENABLE_NEW_GXX_ABI
- arglist[j++] = "-fnew-abi";
-#endif
+ i++;
+ j++;
+ }
/* Add `-lstdc++' if we haven't already done so. */
if (library)
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index e9f02d8..fb6c4e6 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -49,6 +49,8 @@ static tree initializing_context PARAMS ((tree));
static void expand_cleanup_for_base PARAMS ((tree, tree));
static tree get_temp_regvar PARAMS ((tree, tree));
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
+static tree build_new_1 PARAMS ((tree));
+static tree get_cookie_size PARAMS ((tree));
/* Set up local variable for this file. MUST BE CALLED AFTER
INIT_DECL_PROCESSING. */
@@ -225,7 +227,7 @@ perform_member_init (member, name, init, explicit)
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
}
- if (TYPE_NEEDS_DESTRUCTOR (type))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
tree expr;
@@ -701,7 +703,7 @@ expand_cleanup_for_base (binfo, flag)
{
tree expr;
- if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
return;
/* Call the destructor. */
@@ -2101,10 +2103,40 @@ build_java_class_ref (type)
return class_decl;
}
+/* Returns teh size of the cookie to use when allocating an array
+ whose elements have the indicated TYPE. Assumes that it is already
+ known that a cookie is needed. */
+
+static tree
+get_cookie_size (type)
+ tree type;
+{
+ tree cookie_size;
+
+ if (flag_new_abi)
+ {
+ /* Under the new ABI, we need to allocate an additional max
+ (sizeof (size_t), alignof (true_type)) bytes. */
+ tree sizetype_size;
+ tree type_align;
+
+ sizetype_size = size_in_bytes (sizetype);
+ type_align = size_int (TYPE_ALIGN_UNIT (type));
+ if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
+ cookie_size = sizetype_size;
+ else
+ cookie_size = type_align;
+ }
+ else
+ cookie_size = BI_header_size;
+
+ return cookie_size;
+}
+
/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
value is immediately handed to expand_expr. */
-tree
+static tree
build_new_1 (exp)
tree exp;
{
@@ -2113,15 +2145,23 @@ build_new_1 (exp)
tree nelts = NULL_TREE;
tree alloc_expr, alloc_node = NULL_TREE;
int has_array = 0;
- enum tree_code code = NEW_EXPR;
+ enum tree_code code;
int use_cookie, nothrow, check_new;
+ /* Nonzero if the user wrote `::new' rather than just `new'. */
+ int globally_qualified_p;
+ /* Nonzero if we're going to call a global operator new, rather than
+ a class-specific version. */
int use_global_new;
int use_java_new = 0;
+ /* If non-NULL, the number of extra bytes to allocate at the
+ beginning of the storage allocated for an array-new expression in
+ order to store the number of elements. */
+ tree cookie_size = NULL_TREE;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
init = TREE_OPERAND (exp, 2);
- use_global_new = NEW_EXPR_USE_GLOBAL (exp);
+ globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
if (TREE_CODE (type) == ARRAY_REF)
{
@@ -2131,6 +2171,8 @@ build_new_1 (exp)
}
true_type = type;
+ code = has_array ? VEC_NEW_EXPR : NEW_EXPR;
+
if (CP_TYPE_QUALS (type))
type = TYPE_MAIN_VARIANT (type);
@@ -2161,32 +2203,44 @@ build_new_1 (exp)
if (abstract_virtuals_error (NULL_TREE, true_type))
return error_mark_node;
- /* When we allocate an array, and the corresponding deallocation
- function takes a second argument of type size_t, and that's the
- "usual deallocation function", we allocate some extra space at
- the beginning of the array to store the size of the array.
-
- Well, that's what we should do. For backwards compatibility, we
- have to do this whenever there's a two-argument array-delete
- operator.
-
- FIXME: For -fnew-abi, we don't have to maintain backwards
- compatibility and we should fix this. */
- use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
- && ! (placement && ! TREE_CHAIN (placement)
- && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
+ /* Figure out whether or not we're going to use the global operator
+ new. */
+ if (!globally_qualified_p
+ && IS_AGGR_TYPE (true_type)
+ && ((!has_array && TYPE_HAS_NEW_OPERATOR (true_type))
+ || (has_array && TYPE_HAS_ARRAY_NEW_OPERATOR (true_type))))
+ use_global_new = 0;
+ else
+ use_global_new = 1;
+
+ /* We only need cookies for arrays containing types for which we
+ need cookies. */
+ if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type))
+ use_cookie = 0;
+ /* When using placement new, users may not realize that they need
+ the extra storage. Under the old ABI, we don't allocate the
+ cookie whenever they use one placement argument of type `void
+ *'. Under the new ABI, we require that the operator called be
+ the global placement operator delete[]. */
+ else if (placement && !TREE_CHAIN (placement)
+ && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
+ ptr_type_node))
+ use_cookie = (!flag_new_abi || !use_global_new);
+ /* Otherwise, we need the cookie. */
+ else
+ use_cookie = 1;
+ /* Compute the number of extra bytes to allocate, now that we know
+ whether or not we need the cookie. */
if (use_cookie)
- size = size_binop (PLUS_EXPR, size, BI_header_size);
-
- if (has_array)
{
- code = VEC_NEW_EXPR;
-
- if (init && pedantic)
- cp_pedwarn ("initialization in array new");
+ cookie_size = get_cookie_size (true_type);
+ size = size_binop (PLUS_EXPR, size, cookie_size);
}
+ if (has_array && init && pedantic)
+ cp_pedwarn ("initialization in array new");
+
/* Allocate the object. */
if (! placement && TYPE_FOR_JAVA (true_type))
@@ -2208,9 +2262,20 @@ build_new_1 (exp)
}
else
{
- rval = build_op_new_call
- (code, true_type, tree_cons (NULL_TREE, size, placement),
- LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL));
+ tree fnname;
+ tree args;
+
+ args = tree_cons (NULL_TREE, size, placement);
+ fnname = ansi_opname[code];
+
+ if (use_global_new)
+ rval = (build_new_function_call
+ (lookup_function_nonclass (fnname, args),
+ args));
+ else
+ rval = build_method_call (build_dummy_object (true_type),
+ fnname, args, NULL_TREE,
+ LOOKUP_NORMAL);
rval = cp_convert (build_pointer_type (true_type), rval);
}
@@ -2249,18 +2314,36 @@ build_new_1 (exp)
/* Finish up some magic for new'ed arrays */
if (use_cookie && rval != NULL_TREE)
{
- tree extra = BI_header_size;
tree cookie, exp1;
rval = convert (string_type_node, rval); /* for ptr arithmetic */
- rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra));
- /* Store header info. */
- cookie = build_indirect_ref (build (MINUS_EXPR,
- build_pointer_type (BI_header_type),
- rval, extra), NULL_PTR);
- exp1 = build (MODIFY_EXPR, void_type_node,
- build_component_ref (cookie, nelts_identifier,
- NULL_TREE, 0),
- nelts);
+ rval = save_expr (build_binary_op (PLUS_EXPR, rval, cookie_size));
+ /* Store the number of bytes allocated so that we can know how
+ many elements to destroy later. */
+ if (flag_new_abi)
+ {
+ /* Under the new ABI, we use the last sizeof (size_t) bytes
+ to store the number of elements. */
+ cookie = build_indirect_ref (build (MINUS_EXPR,
+ build_pointer_type (sizetype),
+ rval,
+ size_in_bytes (sizetype)),
+ NULL_PTR);
+ exp1 = build (MODIFY_EXPR, void_type_node, cookie, nelts);
+ }
+ else
+ {
+ cookie
+ = build_indirect_ref (build (MINUS_EXPR,
+ build_pointer_type (BI_header_type),
+ rval, cookie_size), NULL_PTR);
+ exp1 = build (MODIFY_EXPR, void_type_node,
+ build_component_ref (cookie, nelts_identifier,
+ NULL_TREE, 0),
+ nelts);
+ }
+
+ /* Build `(cookie = nelts, rval)' and use that as the complete
+ expression. */
rval = cp_convert (build_pointer_type (true_type), rval);
rval = build_compound_expr
(tree_cons (NULL_TREE, exp1,
@@ -2372,7 +2455,8 @@ build_new_1 (exp)
{
enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
tree cleanup, fn = NULL_TREE;
- int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL);
+ int flags = (LOOKUP_NORMAL
+ | (globally_qualified_p * LOOKUP_GLOBAL));
/* The Standard is unclear here, but the right thing to do
is to use the same method for finding deallocation
@@ -2475,7 +2559,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
This is also the containing expression returned by this function. */
tree controller = NULL_TREE;
- if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
+ if (! IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
{
loop = integer_zero_node;
goto no_destructor;
@@ -2534,12 +2618,16 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
base_tbd = base;
else
{
- base_tbd = cp_convert (ptype,
- build_binary_op (MINUS_EXPR,
- cp_convert (string_type_node, base),
- BI_header_size));
+ tree cookie_size;
+
+ cookie_size = get_cookie_size (type);
+ base_tbd
+ = cp_convert (ptype,
+ build_binary_op (MINUS_EXPR,
+ cp_convert (string_type_node, base),
+ cookie_size));
/* True size with header. */
- virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
+ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size);
}
deallocate_expr = build_x_delete (base_tbd,
2 | use_global_delete,
@@ -2708,7 +2796,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
/* Protect the entire array initialization so that we can destroy
the partially constructed array if an exception is thrown. */
- if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
+ if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
try_block = begin_try_block ();
try_body = begin_compound_stmt (/*has_no_scope=*/1);
@@ -2893,7 +2981,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
}
/* Make sure to cleanup any partially constructed elements. */
- if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
+ if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
tree e;
@@ -3029,7 +3117,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
my_friendly_assert (IS_AGGR_TYPE (type), 220);
- if (! TYPE_NEEDS_DESTRUCTOR (type))
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
{
if (auto_delete == integer_zero_node)
return void_zero_node;
@@ -3105,7 +3193,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (auto_delete == integer_zero_node)
cond = NULL_TREE;
else if (base_binfo == NULL_TREE
- || ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+ || TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
cond = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
@@ -3120,7 +3208,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (base_binfo
&& ! TREE_VIA_VIRTUAL (base_binfo)
- && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
tree this_auto_delete;
@@ -3139,7 +3227,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
for (i = 1; i < n_baseclasses; i++)
{
base_binfo = TREE_VEC_ELT (binfos, i);
- if (! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
|| TREE_VIA_VIRTUAL (base_binfo))
continue;
@@ -3154,7 +3242,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
if (TREE_CODE (member) != FIELD_DECL)
continue;
- if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member)))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{
tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0);
tree this_type = TREE_TYPE (member);
@@ -3234,20 +3322,34 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
if (TREE_CODE (type) == POINTER_TYPE)
{
/* Step back one from start of vector, and read dimension. */
- tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
- base, BI_header_size);
- tree cookie = build_indirect_ref (cookie_addr, NULL_PTR);
- maxindex = build_component_ref (cookie, nelts_identifier, NULL_TREE, 0);
- do
- type = TREE_TYPE (type);
- while (TREE_CODE (type) == ARRAY_TYPE);
+ tree cookie_addr;
+
+ if (flag_new_abi)
+ {
+ cookie_addr = build (MINUS_EXPR,
+ build_pointer_type (sizetype),
+ base,
+ TYPE_SIZE_UNIT (sizetype));
+ maxindex = build_indirect_ref (cookie_addr, NULL_PTR);
+ }
+ else
+ {
+ tree cookie;
+
+ cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
+ base, BI_header_size);
+ cookie = build_indirect_ref (cookie_addr, NULL_PTR);
+ maxindex = build_component_ref (cookie, nelts_identifier,
+ NULL_TREE, 0);
+ }
+
+ type = strip_array_types (TREE_TYPE (type));
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
/* get the total number of things in the array, maxindex is a bad name */
maxindex = array_type_nelts_total (type);
- while (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
+ type = strip_array_types (type);
base = build_unary_op (ADDR_EXPR, base, 1);
}
else
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 2e5a2e6..5c42a41 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -3147,7 +3147,7 @@ do_identifier (token, parsing, args)
else if (!DECL_ERROR_REPORTED (id))
{
DECL_ERROR_REPORTED (id) = 1;
- if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (id)))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (id)))
{
error ("name lookup of `%s' changed for new ISO `for' scoping",
IDENTIFIER_POINTER (token));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d5e52e8..e6e079c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4830,7 +4830,8 @@ instantiate_class_template (type)
TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
- TYPE_GETS_NEW (type) = TYPE_GETS_NEW (pattern);
+ 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);
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index 91f4ec4..aa72384 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -113,7 +113,7 @@ print_lang_type (file, node, indent)
if (TYPE_NEEDS_CONSTRUCTING (node))
fputs ( "needs-constructor", file);
- if (TYPE_NEEDS_DESTRUCTOR (node))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
fputs (" needs-destructor", file);
if (TYPE_HAS_DESTRUCTOR (node))
fputs (" ~X()", file);
@@ -128,9 +128,9 @@ print_lang_type (file, node, indent)
else
fputs (" X(X&)", file);
}
- if (TYPE_GETS_NEW (node) & 1)
+ if (TYPE_HAS_NEW_OPERATOR (node))
fputs (" new", file);
- if (TYPE_GETS_NEW (node) & 2)
+ if (TYPE_HAS_ARRAY_NEW_OPERATOR (node))
fputs (" new[]", file);
if (TYPE_GETS_DELETE (node) & 1)
fputs (" delete", file);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 56917eb..bc0ab26 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -725,7 +725,7 @@ context_for_name_lookup (decl)
For the purposes of name lookup, after the anonymous union
definition, the members of the anonymous union are considered to
- have been defined in the scope in which teh anonymous union is
+ have been defined in the scope in which the anonymous union is
declared. */
tree context = CP_DECL_CONTEXT (decl);
@@ -1955,7 +1955,7 @@ tree_has_any_destructor_p (binfo, data)
void *data ATTRIBUTE_UNUSED;
{
tree type = BINFO_TYPE (binfo);
- return TYPE_NEEDS_DESTRUCTOR (type) ? binfo : NULL_TREE;
+ return TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) ? binfo : NULL_TREE;
}
/* Returns > 0 if a function with type DRETTYPE overriding a function
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c739db7..57adf99 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -322,7 +322,7 @@ break_out_cleanups (exp)
tree tmp = exp;
if (TREE_CODE (tmp) == CALL_EXPR
- && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (tmp)))
return build_cplus_new (TREE_TYPE (tmp), tmp);
while (TREE_CODE (tmp) == NOP_EXPR
@@ -330,7 +330,7 @@ break_out_cleanups (exp)
|| TREE_CODE (tmp) == NON_LVALUE_EXPR)
{
if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR
- && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
{
TREE_OPERAND (tmp, 0)
= build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
@@ -505,8 +505,8 @@ build_cplus_array_type_1 (elt_type, index_type)
more easily. */
TYPE_NEEDS_CONSTRUCTING (t)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
- TYPE_NEEDS_DESTRUCTOR (t)
- = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
return t;
}
@@ -602,7 +602,7 @@ cp_build_qualified_type_real (type, type_quals, complain)
}
/* Even if we already had this variant, we update
- TYPE_NEEDS_CONSTRUCTING and TYPE_NEEDS_DESTRUCTOR in case
+ TYPE_NEEDS_CONSTRUCTING and TYPE_HAS_NONTRIVIAL_DESTRUCTOR in case
they changed since the variant was originally created.
This seems hokey; if there is some way to use a previous
@@ -610,8 +610,8 @@ cp_build_qualified_type_real (type, type_quals, complain)
TYPE_NEEDS_CONSTRUCTING will never be updated. */
TYPE_NEEDS_CONSTRUCTING (t)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
- TYPE_NEEDS_DESTRUCTOR (t)
- = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
return t;
}
else if (TYPE_PTRMEMFUNC_P (type))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 8fc3ab8..400d930 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -155,8 +155,8 @@ complete_type (type)
layout_type (type);
TYPE_NEEDS_CONSTRUCTING (type)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
- TYPE_NEEDS_DESTRUCTOR (type)
- = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
}
else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
instantiate_class_template (TYPE_MAIN_VARIANT (type));
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/arraynew.C b/gcc/testsuite/g++.old-deja/g++.abi/arraynew.C
new file mode 100644
index 0000000..3e39e37
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/arraynew.C
@@ -0,0 +1,127 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+#include <cstdlib>
+#include <new>
+
+extern "C" int printf (const char*, ...);
+
+void* p;
+
+void* operator new[](size_t s) throw (bad_alloc)
+{
+ // Record the base of the last array allocated.
+ p = malloc (s);
+ return p;
+}
+
+template <typename T>
+void check_no_cookie (int i)
+{
+ void* a = new T[7];
+ if (p != a)
+ exit (i);
+}
+
+template <typename T>
+void check_no_placement_cookie (int i)
+{
+ p = malloc (13 * sizeof (T));
+ void* a = new (p) T[13];
+ if (p != a)
+ exit (i);
+}
+
+template <typename T>
+void check_cookie (int i)
+{
+ void* a = new T[11];
+
+ // Compute the cookie location manually.
+ size_t x = __alignof__ (T);
+ if (x < sizeof (size_t))
+ x = sizeof (size_t);
+ if ((char *) a - x != (char *) p)
+ exit (i);
+
+ // Check the cookie value.
+ size_t *sp = ((size_t *) a) - 1;
+ if (*sp != 11)
+ exit (i);
+}
+
+template <typename T>
+void check_placement_cookie (int i)
+{
+ p = malloc (sizeof (T) * 11 + 100);
+ void* a = new (p) T[11];
+
+ printf ("%x %x\n", a, p);
+ // Compute the cookie location manually.
+ size_t x = __alignof__ (T);
+ if (x < sizeof (size_t))
+ x = sizeof (size_t);
+ if ((char *) a - x != (char *) p)
+ exit (i);
+
+ // Check the cookie value.
+ size_t *sp = ((size_t *) a) - 1;
+ if (*sp != 11)
+ exit (i);
+}
+
+struct X {};
+
+template <typename T>
+struct Y { int i; virtual void f () {}; };
+
+// A class with a non-trivial destructor -- it needs a cookie.
+struct Z { ~Z () {}; };
+// Likewise, but this class needs a bigger cookie so that the array
+// elements are correctly aligned.
+struct Z2 { ~Z2 () {}; long double d; };
+
+struct W1 { void operator delete[] (void *, size_t) {}; };
+struct W2 { void operator delete[] (void *) {};
+ void operator delete[] (void *, size_t) {}; };
+
+struct V { void *operator new[] (size_t s, void *p)
+ { return p; }
+ ~V () {}
+ };
+
+int main ()
+{
+ // There should be no cookies for types with trivial destructors.
+ check_no_cookie<int> (1);
+ check_no_cookie<X> (2);
+ check_no_cookie<Y<double> > (3);
+
+ // There should be no cookies for allocations using global placement
+ // new.
+ check_no_placement_cookie<int> (4);
+ check_no_placement_cookie<X> (5);
+ check_no_placement_cookie<Z> (6);
+
+ // There should be a cookie when using a non-trivial destructor.
+ check_cookie<Z> (7);
+ check_cookie<Z2> (8);
+
+ // There should be a cookie when using the two-argument array delete
+ // operator.
+ check_cookie<W1> (9);
+ // But not when the one-argument version is also available.
+ check_no_cookie<W2> (10);
+
+ // There should be a cookie when using a non-global placement new.
+ check_placement_cookie<V> (11);
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main ()
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
diff --git a/gcc/testsuite/g++.old-deja/g++.other/inline7.C b/gcc/testsuite/g++.old-deja/g++.other/inline7.C
index c3f5439..e6483ca 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/inline7.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/inline7.C
@@ -1,4 +1,5 @@
// Origin: Mark Mitchell <mark@codesourcery.com>
+// Special g++ Options: -O2
#include <list>
diff --git a/gcc/tree.h b/gcc/tree.h
index 51157c6..a59b5d2 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -880,6 +880,10 @@ struct tree_block
The value is an int, measured in bits. */
#define TYPE_ALIGN(NODE) (TYPE_CHECK (NODE)->type.align)
+/* The alignment for NODE, in bytes. */
+#define TYPE_ALIGN_UNIT(NODE) \
+ (TYPE_ALIGN (NODE) / BITS_PER_UNIT)
+
#define TYPE_STUB_DECL(NODE) (TREE_CHAIN (NODE))
/* In a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, it means the type