Commit 298d6f60 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (IDENTIFIER_CTOR_OR_DTOR_P): New macro.

	* cp-tree.h (IDENTIFIER_CTOR_OR_DTOR_P): New macro.
	(cp_tree_index): Add CPTI_PUSH_EXCEPTION_IDENTIFIER.
	(cp_push_exception_identifier): New macro.
	(DECL_COMPLETE_DESTRUCTOR_P): New macro.
	(DECL_BASE_DESTRUCTOR_P): Likewise.
	(DECL_DELETING_DESTRUCTOR_P): Likewise.
	(get_vtbl_decl_for_binfo): Fix formatting.
	(in_charge_arg_for_name): New macro.
	(maybe_build_cleanup_and_delete): Remove declaration.
	* call.c (build_field_call): Use IDENTIFIER_CTOR_OR_DTOR_P.
	(in_charge_arg_for_name): New function.
	(build_new_method_call): Use it.  Handle cloned destructors.
	(build_clone): Don't make the base constructor virtual.
	Automatically defer generated functions.
	(clone_function_decl): Handle destructors, too.
	(clone_constructors_and_destructors): Likewise.
	(create_vtable_ptr): Don't create a vtable entry for a cloned
	function.
	* decl.c (predefined_identifier): Add ctor_or_dtor_p.
	(initialize_predefined_identifiers): Update appropriately.
	(finish_destructor_body): Simplify.
	(maybe_build_cleanup_and_delete): Remove.
	* except.c (expand_throw): Handle new-ABI destructors.
	* init.c (expand_cleanup_for_base): Use base_dtor_identifier.
	(build_dtor_call): New function.
	(build_delete): Use it.  Simplify.
	* optimize.c (maybe_clone_body): Handle destructors.
	* search.c (lookup_field_queue_p): Use IDENTIFIER_CTOR_OR_DTOR_P.

From-SVN: r33096
parent 1ba82fb2
2000-04-12 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (IDENTIFIER_CTOR_OR_DTOR_P): New macro.
(cp_tree_index): Add CPTI_PUSH_EXCEPTION_IDENTIFIER.
(cp_push_exception_identifier): New macro.
(DECL_COMPLETE_DESTRUCTOR_P): New macro.
(DECL_BASE_DESTRUCTOR_P): Likewise.
(DECL_DELETING_DESTRUCTOR_P): Likewise.
(get_vtbl_decl_for_binfo): Fix formatting.
(in_charge_arg_for_name): New macro.
(maybe_build_cleanup_and_delete): Remove declaration.
* call.c (build_field_call): Use IDENTIFIER_CTOR_OR_DTOR_P.
(in_charge_arg_for_name): New function.
(build_new_method_call): Use it. Handle cloned destructors.
(build_clone): Don't make the base constructor virtual.
Automatically defer generated functions.
(clone_function_decl): Handle destructors, too.
(clone_constructors_and_destructors): Likewise.
(create_vtable_ptr): Don't create a vtable entry for a cloned
function.
* decl.c (predefined_identifier): Add ctor_or_dtor_p.
(initialize_predefined_identifiers): Update appropriately.
(finish_destructor_body): Simplify.
(maybe_build_cleanup_and_delete): Remove.
* except.c (expand_throw): Handle new-ABI destructors.
* init.c (expand_cleanup_for_base): Use base_dtor_identifier.
(build_dtor_call): New function.
(build_delete): Use it. Simplify.
* optimize.c (maybe_clone_body): Handle destructors.
* search.c (lookup_field_queue_p): Use IDENTIFIER_CTOR_OR_DTOR_P.
* exception.cc (cleanup_fn): New typedef.
(CALL_CLEANUP): New macro.
(cp_eh_info): Use them.
(__cp_push_exception): Likewise.
(__cp_pop_exception): Likewise.
2000-04-11 Mark Mitchell <mark@codesourcery.com> 2000-04-11 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER. * cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.
......
...@@ -130,7 +130,7 @@ build_field_call (basetype_path, instance_ptr, name, parms) ...@@ -130,7 +130,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
{ {
tree field, instance; tree field, instance;
if (name == ctor_identifier || name == dtor_identifier) if (IDENTIFIER_CTOR_OR_DTOR_P (name))
return NULL_TREE; return NULL_TREE;
/* Speed up the common case. */ /* Speed up the common case. */
...@@ -4172,6 +4172,29 @@ build_over_call (cand, args, flags) ...@@ -4172,6 +4172,29 @@ build_over_call (cand, args, flags)
return convert_from_reference (fn); return convert_from_reference (fn);
} }
/* Returns the value to use for the in-charge parameter when making a
call to a function with the indicated NAME. */
tree
in_charge_arg_for_name (name)
tree name;
{
if (name == base_ctor_identifier
|| name == base_dtor_identifier)
return integer_zero_node;
else if (name == complete_ctor_identifier)
return integer_one_node;
else if (name == complete_dtor_identifier)
return integer_two_node;
else if (name == deleting_dtor_identifier)
return integer_three_node;
/* This function should only be called with one of the names listed
above. */
my_friendly_abort (20000411);
return NULL_TREE;
}
static tree static tree
build_new_method_call (instance, name, args, basetype_path, flags) build_new_method_call (instance, name, args, basetype_path, flags)
tree instance, name, args, basetype_path; tree instance, name, args, basetype_path;
...@@ -4253,30 +4276,30 @@ build_new_method_call (instance, name, args, basetype_path, flags) ...@@ -4253,30 +4276,30 @@ build_new_method_call (instance, name, args, basetype_path, flags)
/* Callers should explicitly indicate whether they want to construct /* Callers should explicitly indicate whether they want to construct
the complete object or just the part without virtual bases. */ the complete object or just the part without virtual bases. */
my_friendly_assert (name != ctor_identifier, 20000408); my_friendly_assert (name != ctor_identifier, 20000408);
/* Similarly for destructors. */
my_friendly_assert (name != dtor_identifier, 20000408);
if (name == complete_ctor_identifier if (IDENTIFIER_CTOR_OR_DTOR_P (name))
|| name == base_ctor_identifier)
{ {
pretty_name = constructor_name (basetype); int constructor_p;
constructor_p = (name == complete_ctor_identifier
|| name == base_ctor_identifier);
pretty_name = (constructor_p
? constructor_name (basetype) : dtor_identifier);
if (!flag_new_abi) if (!flag_new_abi)
{ {
/* Add the in-charge parameter as an implicit first argument. */ /* Add the in-charge parameter as an implicit first argument. */
if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)) if (!constructor_p
{ || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
tree in_charge; args = tree_cons (NULL_TREE,
in_charge_arg_for_name (name),
if (name == complete_ctor_identifier) args);
in_charge = integer_one_node;
else
in_charge = integer_zero_node;
args = tree_cons (NULL_TREE, in_charge, args);
}
/* We want to call the normal constructor function under the /* We want to call the normal constructor function under the
old ABI. */ old ABI. */
name = ctor_identifier; name = constructor_p ? ctor_identifier : dtor_identifier;
} }
} }
else else
......
...@@ -3883,6 +3883,14 @@ build_clone (fn, name) ...@@ -3883,6 +3883,14 @@ build_clone (fn, name)
/* And it hasn't yet been deferred. */ /* And it hasn't yet been deferred. */
DECL_DEFERRED_FN (clone) = 0; DECL_DEFERRED_FN (clone) = 0;
/* The base-class destructor is not virtual. */
if (name == base_dtor_identifier)
{
DECL_VIRTUAL_P (clone) = 0;
if (TREE_CODE (clone) != TEMPLATE_DECL)
DECL_VINDEX (clone) = NULL_TREE;
}
/* If there was an in-charge paramter, drop it from the function /* If there was an in-charge paramter, drop it from the function
type. */ type. */
if (DECL_HAS_IN_CHARGE_PARM_P (clone)) if (DECL_HAS_IN_CHARGE_PARM_P (clone))
...@@ -3948,6 +3956,8 @@ build_clone (fn, name) ...@@ -3948,6 +3956,8 @@ build_clone (fn, name)
DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result)); DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result));
DECL_TI_TEMPLATE (result) = clone; DECL_TI_TEMPLATE (result) = clone;
} }
else if (DECL_DEFERRED_FN (fn))
defer_fn (clone);
return clone; return clone;
} }
...@@ -3963,8 +3973,10 @@ clone_function_decl (fn, update_method_vec_p) ...@@ -3963,8 +3973,10 @@ clone_function_decl (fn, update_method_vec_p)
{ {
tree clone; tree clone;
if (DECL_CONSTRUCTOR_P (fn)) if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
{ {
/* For each constructor, we need two variants: an in-charge version
and a not-in-charge version. */
clone = build_clone (fn, complete_ctor_identifier); clone = build_clone (fn, complete_ctor_identifier);
if (update_method_vec_p) if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), NULL, clone); add_method (DECL_CONTEXT (clone), NULL, clone);
...@@ -3973,8 +3985,22 @@ clone_function_decl (fn, update_method_vec_p) ...@@ -3973,8 +3985,22 @@ clone_function_decl (fn, update_method_vec_p)
add_method (DECL_CONTEXT (clone), NULL, clone); add_method (DECL_CONTEXT (clone), NULL, clone);
} }
else else
/* We don't do destructors yet. */ {
my_friendly_abort (20000411); my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
/* For each destructor, we need two variants: an in-charge
version, a not-in-charge version, and an in-charge deleting
version. */
clone = build_clone (fn, complete_dtor_identifier);
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), NULL, clone);
clone = build_clone (fn, deleting_dtor_identifier);
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), NULL, clone);
clone = build_clone (fn, base_dtor_identifier);
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), NULL, clone);
}
} }
/* For each of the constructors and destructors in T, create an /* For each of the constructors and destructors in T, create an
...@@ -3995,12 +4021,10 @@ clone_constructors_and_destructors (t) ...@@ -3995,12 +4021,10 @@ clone_constructors_and_destructors (t)
if (!CLASSTYPE_METHOD_VEC (t)) if (!CLASSTYPE_METHOD_VEC (t))
return; return;
/* For each constructor, we need two variants: an in-charge version
and a not-in-charge version. */
for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns)) for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1); clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
for (fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
/* For now, we don't do the destructors. */ clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
} }
/* Remove all zero-width bit-fields from T. */ /* Remove all zero-width bit-fields from T. */
...@@ -4130,7 +4154,8 @@ create_vtable_ptr (t, empty_p, vfuns_p, ...@@ -4130,7 +4154,8 @@ create_vtable_ptr (t, empty_p, vfuns_p,
/* Loop over the virtual functions, adding them to our various /* Loop over the virtual functions, adding them to our various
vtables. */ vtables. */
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
if (DECL_VINDEX (fn)) if (DECL_VINDEX (fn)
&& !(flag_new_abi && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)))
add_virtual_function (new_virtuals_p, overridden_virtuals_p, add_virtual_function (new_virtuals_p, overridden_virtuals_p,
vfuns_p, fn, t); vfuns_p, fn, t);
......
...@@ -66,6 +66,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -66,6 +66,7 @@ Boston, MA 02111-1307, USA. */
ICS_BAD_FLAG (in _CONV) ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK) FN_TRY_BLOCK_P (in TRY_BLOCK)
SCOPE_NO_CLEANUPS_P (in SCOPE_STMT) SCOPE_NO_CLEANUPS_P (in SCOPE_STMT)
IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE)
4: BINFO_NEW_VTABLE_MARKED. 4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL). or FIELD_DECL).
...@@ -482,6 +483,11 @@ struct tree_srcloc ...@@ -482,6 +483,11 @@ struct tree_srcloc
OPERATOR_TYPENAME_FORMAT, \ OPERATOR_TYPENAME_FORMAT, \
strlen (OPERATOR_TYPENAME_FORMAT))) strlen (OPERATOR_TYPENAME_FORMAT)))
/* Nonzero if this identifier is the name of a constructor or
destructor. */
#define IDENTIFIER_CTOR_OR_DTOR_P(NODE) \
TREE_LANG_FLAG_3 (NODE)
/* Nonzero means reject anything that ISO standard C++ forbids. */ /* Nonzero means reject anything that ISO standard C++ forbids. */
extern int pedantic; extern int pedantic;
...@@ -571,6 +577,7 @@ enum cp_tree_index ...@@ -571,6 +577,7 @@ enum cp_tree_index
CPTI_PFN_IDENTIFIER, CPTI_PFN_IDENTIFIER,
CPTI_PFN_OR_DELTA2_IDENTIFIER, CPTI_PFN_OR_DELTA2_IDENTIFIER,
CPTI_VPTR_IDENTIFIER, CPTI_VPTR_IDENTIFIER,
CPTI_PUSH_EXCEPTION_IDENTIFIER,
CPTI_LANG_NAME_C, CPTI_LANG_NAME_C,
CPTI_LANG_NAME_CPLUSPLUS, CPTI_LANG_NAME_CPLUSPLUS,
...@@ -682,6 +689,9 @@ extern tree cp_global_trees[CPTI_MAX]; ...@@ -682,6 +689,9 @@ extern tree cp_global_trees[CPTI_MAX];
#define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER] #define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER]
#define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER] #define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER]
#define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER] #define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER]
/* The name of the function to call to push an exception onto the
exception stack. */
#define cp_push_exception_identifier cp_global_trees[CPTI_PUSH_EXCEPTION_IDENTIFIER]
#define lang_name_c cp_global_trees[CPTI_LANG_NAME_C] #define lang_name_c cp_global_trees[CPTI_LANG_NAME_C]
#define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS] #define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS]
...@@ -1963,6 +1973,24 @@ struct lang_decl ...@@ -1963,6 +1973,24 @@ struct lang_decl
#define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE) \ #define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE) \
(DECL_DESTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE)) (DECL_DESTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE))
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor for a complete
object. */
#define DECL_COMPLETE_DESTRUCTOR_P(NODE) \
(DECL_DESTRUCTOR_P (NODE) \
&& DECL_NAME (NODE) == complete_dtor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor for a base
object. */
#define DECL_BASE_DESTRUCTOR_P(NODE) \
(DECL_DESTRUCTOR_P (NODE) \
&& DECL_NAME (NODE) == base_dtor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor for a complete
object. */
#define DECL_DELETING_DESTRUCTOR_P(NODE) \
(DECL_DESTRUCTOR_P (NODE) \
&& DECL_NAME (NODE) == deleting_dtor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or /* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or
destructor. */ destructor. */
#define DECL_CLONED_FUNCTION_P(NODE) \ #define DECL_CLONED_FUNCTION_P(NODE) \
...@@ -3761,7 +3789,8 @@ extern void unreverse_member_declarations PARAMS ((tree)); ...@@ -3761,7 +3789,8 @@ extern void unreverse_member_declarations PARAMS ((tree));
extern void invalidate_class_lookup_cache PARAMS ((void)); extern void invalidate_class_lookup_cache PARAMS ((void));
extern void maybe_note_name_used_in_class PARAMS ((tree, tree)); extern void maybe_note_name_used_in_class PARAMS ((tree, tree));
extern void note_name_declared_in_class PARAMS ((tree, tree)); extern void note_name_declared_in_class PARAMS ((tree, tree));
extern tree get_vtbl_decl_for_binfo PARAMS ((tree)); extern tree get_vtbl_decl_for_binfo PARAMS ((tree));
extern tree in_charge_arg_for_name PARAMS ((tree));
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree)); extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
...@@ -3898,7 +3927,6 @@ extern tree finish_function PARAMS ((int)); ...@@ -3898,7 +3927,6 @@ extern tree finish_function PARAMS ((int));
extern tree start_method PARAMS ((tree, tree, tree)); extern tree start_method PARAMS ((tree, tree, tree));
extern tree finish_method PARAMS ((tree)); extern tree finish_method PARAMS ((tree));
extern void hack_incomplete_structures PARAMS ((tree)); extern void hack_incomplete_structures PARAMS ((tree));
extern tree maybe_build_cleanup_and_delete PARAMS ((tree));
extern tree maybe_build_cleanup PARAMS ((tree)); extern tree maybe_build_cleanup PARAMS ((tree));
extern void cplus_expand_expr_stmt PARAMS ((tree)); extern void cplus_expand_expr_stmt PARAMS ((tree));
extern void finish_stmt PARAMS ((void)); extern void finish_stmt PARAMS ((void));
......
...@@ -6045,6 +6045,8 @@ typedef struct predefined_identifier ...@@ -6045,6 +6045,8 @@ typedef struct predefined_identifier
const char *name; const char *name;
/* The place where the IDENTIFIER_NODE should be stored. */ /* The place where the IDENTIFIER_NODE should be stored. */
tree *node; tree *node;
/* Non-zero if this is the name of a constructor or destructor. */
int ctor_or_dtor_p;
} predefined_identifier; } predefined_identifier;
/* Create all the predefined identifiers. */ /* Create all the predefined identifiers. */
...@@ -6056,30 +6058,35 @@ initialize_predefined_identifiers () ...@@ -6056,30 +6058,35 @@ initialize_predefined_identifiers ()
/* A table of identifiers to create at startup. */ /* A table of identifiers to create at startup. */
static predefined_identifier predefined_identifiers[] = { static predefined_identifier predefined_identifiers[] = {
{ "C++", &lang_name_cplusplus }, { "C++", &lang_name_cplusplus, 0 },
{ "C", &lang_name_c }, { "C", &lang_name_c, 0 },
{ "Java", &lang_name_java }, { "Java", &lang_name_java, 0 },
{ CTOR_NAME, &ctor_identifier }, { CTOR_NAME, &ctor_identifier, 1 },
{ "__base_ctor", &base_ctor_identifier }, { "__base_ctor", &base_ctor_identifier, 1 },
{ "__comp_ctor", &complete_ctor_identifier }, { "__comp_ctor", &complete_ctor_identifier, 1 },
{ DTOR_NAME, &dtor_identifier }, { DTOR_NAME, &dtor_identifier, 1 },
{ "__comp_dtor", &complete_dtor_identifier }, { "__comp_dtor", &complete_dtor_identifier, 1 },
{ "__base_dtor", &base_dtor_identifier }, { "__base_dtor", &base_dtor_identifier, 1 },
{ "__deleting_dtor", &deleting_dtor_identifier }, { "__deleting_dtor", &deleting_dtor_identifier, 1 },
{ VTABLE_DELTA2_NAME, &delta2_identifier }, { VTABLE_DELTA2_NAME, &delta2_identifier, 0 },
{ VTABLE_DELTA_NAME, &delta_identifier }, { VTABLE_DELTA_NAME, &delta_identifier, 0 },
{ IN_CHARGE_NAME, &in_charge_identifier }, { IN_CHARGE_NAME, &in_charge_identifier, 0 },
{ VTABLE_INDEX_NAME, &index_identifier }, { VTABLE_INDEX_NAME, &index_identifier, 0 },
{ "nelts", &nelts_identifier }, { "nelts", &nelts_identifier, 0 },
{ THIS_NAME, &this_identifier }, { THIS_NAME, &this_identifier, 0 },
{ VTABLE_PFN_NAME, &pfn_identifier }, { VTABLE_PFN_NAME, &pfn_identifier, 0 },
{ "__pfn_or_delta2", &pfn_or_delta2_identifier }, { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
{ "_vptr", &vptr_identifier }, { "_vptr", &vptr_identifier, 0 },
{ NULL, NULL } { "__cp_push_exception", &cp_push_exception_identifier, 0 },
{ NULL, NULL, 0 }
}; };
for (pid = predefined_identifiers; pid->name; ++pid) for (pid = predefined_identifiers; pid->name; ++pid)
*pid->node = get_identifier (pid->name); {
*pid->node = get_identifier (pid->name);
if (pid->ctor_or_dtor_p)
IDENTIFIER_CTOR_OR_DTOR_P (*pid->node) = 1;
}
} }
/* Create the predefined scalar types of C, /* Create the predefined scalar types of C,
...@@ -13811,9 +13818,9 @@ static void ...@@ -13811,9 +13818,9 @@ static void
finish_destructor_body () finish_destructor_body ()
{ {
tree compound_stmt; tree compound_stmt;
tree in_charge;
tree virtual_size; tree virtual_size;
tree exprstmt; tree exprstmt;
tree if_stmt;
/* Create a block to contain all the extra code. */ /* Create a block to contain all the extra code. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
...@@ -13831,16 +13838,9 @@ finish_destructor_body () ...@@ -13831,16 +13838,9 @@ finish_destructor_body ()
will set the flag again. */ will set the flag again. */
TYPE_HAS_DESTRUCTOR (current_class_type) = 0; TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
/* These are two cases where we cannot delegate deletion. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
|| TYPE_GETS_REG_DELETE (current_class_type))
in_charge = integer_zero_node;
else
in_charge = current_in_charge_parm;
exprstmt = build_delete (current_class_type, exprstmt = build_delete (current_class_type,
current_class_ref, current_class_ref,
in_charge, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
0); 0);
...@@ -13873,8 +13873,8 @@ finish_destructor_body () ...@@ -13873,8 +13873,8 @@ finish_destructor_body ()
TYPE_BINFO (current_class_type)); TYPE_BINFO (current_class_type));
finish_expr_stmt finish_expr_stmt
(build_scoped_method_call (build_scoped_method_call
(current_class_ref, vb, dtor_identifier, (current_class_ref, vb, complete_dtor_identifier,
build_tree_list (NULL_TREE, integer_zero_node))); NULL_TREE));
} }
vbases = TREE_CHAIN (vbases); vbases = TREE_CHAIN (vbases);
} }
...@@ -13897,24 +13897,18 @@ finish_destructor_body () ...@@ -13897,24 +13897,18 @@ finish_destructor_body ()
only defines placement deletes we don't do anything here. So we only defines placement deletes we don't do anything here. So we
pass LOOKUP_SPECULATIVELY; delete_sanity will complain for us if pass LOOKUP_SPECULATIVELY; delete_sanity will complain for us if
they ever try to delete one of these. */ they ever try to delete one of these. */
if (TYPE_GETS_REG_DELETE (current_class_type) exprstmt = build_op_delete_call
|| TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) (DELETE_EXPR, current_class_ptr, virtual_size,
{ LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
tree if_stmt;
if_stmt = begin_if_stmt ();
exprstmt = build_op_delete_call finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
(DELETE_EXPR, current_class_ptr, virtual_size, current_in_charge_parm,
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); integer_one_node),
if_stmt);
if_stmt = begin_if_stmt (); finish_expr_stmt (exprstmt);
finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node, finish_then_clause (if_stmt);
current_in_charge_parm, finish_if_stmt ();
integer_one_node),
if_stmt);
finish_expr_stmt (exprstmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
}
/* Close the block we started above. */ /* Close the block we started above. */
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
...@@ -14560,16 +14554,6 @@ maybe_build_cleanup_1 (decl, auto_delete) ...@@ -14560,16 +14554,6 @@ maybe_build_cleanup_1 (decl, auto_delete)
} }
/* If DECL is of a type which needs a cleanup, build that cleanup /* If DECL is of a type which needs a cleanup, build that cleanup
here. The cleanup does free the storage with a call to delete. */
tree
maybe_build_cleanup_and_delete (decl)
tree decl;
{
return maybe_build_cleanup_1 (decl, integer_three_node);
}
/* If DECL is of a type which needs a cleanup, build that cleanup
here. The cleanup does not free the storage with a call a delete. */ here. The cleanup does not free the storage with a call a delete. */
tree tree
......
...@@ -888,14 +888,20 @@ expand_throw (exp) ...@@ -888,14 +888,20 @@ expand_throw (exp)
/* First, decay it. */ /* First, decay it. */
exp = decay_conversion (exp); exp = decay_conversion (exp);
/* cleanup_type is void (*)(void *, int), /* The CLEANUP_TYPE is the internal type of a destructor. Under
the internal type of a destructor. */ the old ABI, destructors are two-argument functions; under
the new ABI they take only one argument. */
if (cleanup_type == NULL_TREE) if (cleanup_type == NULL_TREE)
cleanup_type = build_pointer_type {
(build_function_type tree arg_types;
(void_type_node, tree_cons
(NULL_TREE, ptr_type_node, tree_cons arg_types = void_list_node;
(NULL_TREE, integer_type_node, void_list_node)))); if (!flag_new_abi)
arg_types = tree_cons (NULL_TREE, integer_type_node, arg_types);
arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
cleanup_type = (build_pointer_type
(build_function_type (void_type_node, arg_types)));
}
if (TYPE_PTR_P (TREE_TYPE (exp))) if (TYPE_PTR_P (TREE_TYPE (exp)))
throw_type = build_eh_type_type (TREE_TYPE (exp)); throw_type = build_eh_type_type (TREE_TYPE (exp));
...@@ -949,7 +955,10 @@ expand_throw (exp) ...@@ -949,7 +955,10 @@ expand_throw (exp)
if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object))) if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
{ {
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
dtor_identifier, 0); (flag_new_abi
? complete_dtor_identifier
: dtor_identifier),
0);
cleanup = TREE_VALUE (cleanup); cleanup = TREE_VALUE (cleanup);
mark_used (cleanup); mark_used (cleanup);
mark_addressable (cleanup); mark_addressable (cleanup);
...@@ -970,7 +979,7 @@ expand_throw (exp) ...@@ -970,7 +979,7 @@ expand_throw (exp)
TREE_TYPE (cleanup) = cleanup_type; TREE_TYPE (cleanup) = cleanup_type;
} }
fn = get_identifier ("__cp_push_exception"); fn = cp_push_exception_identifier;
if (IDENTIFIER_GLOBAL_VALUE (fn)) if (IDENTIFIER_GLOBAL_VALUE (fn))
fn = IDENTIFIER_GLOBAL_VALUE (fn); fn = IDENTIFIER_GLOBAL_VALUE (fn);
else else
......
...@@ -78,6 +78,21 @@ std::unexpected () ...@@ -78,6 +78,21 @@ std::unexpected ()
__unexpected_func (); __unexpected_func ();
} }
/* The type of a function called to clean up an exception object.
(These will be destructors.) Under the old ABI, these take a
second argument (the `in-charge' argument), that indicates whether
or not do delete the object, and whether or not to destroy virtual
bases. Under the new ABI, there is no second argument. */
#if !defined (__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
typedef void (*cleanup_fn)(void *, int);
/* The `2' is the value for the in-charge parameter that indicates
that virtual bases should be destroyed. */
#define CALL_CLEANUP(FN, THIS) FN (THIS, 2)
#else
typedef void (*cleanup_fn)(void *);
#define CALL_CLEANUP(FN, THIS) FN (THIS)
#endif
/* C++-specific state about the current exception. /* C++-specific state about the current exception.
This must match init_exception_processing(). This must match init_exception_processing().
...@@ -90,7 +105,7 @@ struct cp_eh_info ...@@ -90,7 +105,7 @@ struct cp_eh_info
__eh_info eh_info; __eh_info eh_info;
void *value; void *value;
void *type; void *type;
void (*cleanup)(void *, int); cleanup_fn cleanup;
bool caught; bool caught;
cp_eh_info *next; cp_eh_info *next;
long handlers; long handlers;
...@@ -202,7 +217,7 @@ __cplus_type_matcher (__eh_info *info_, void *match_info, ...@@ -202,7 +217,7 @@ __cplus_type_matcher (__eh_info *info_, void *match_info,
Used by expand_throw(). */ Used by expand_throw(). */
extern "C" void extern "C" void
__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int)) __cp_push_exception (void *value, void *type, cleanup_fn cleanup)
{ {
cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info)); cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info));
...@@ -251,8 +266,8 @@ __cp_pop_exception (cp_eh_info *p) ...@@ -251,8 +266,8 @@ __cp_pop_exception (cp_eh_info *p)
*q = p->next; *q = p->next;
if (p->cleanup) if (p->cleanup)
/* 2 is a magic value for destructors; see build_delete(). */ // value may have been adjusted.
p->cleanup (p->original_value, 2); // value may have been adjusted. CALL_CLEANUP (p->cleanup, p->original_value);
if (! __is_pointer (p->type)) if (! __is_pointer (p->type))
__eh_free (p->original_value); // value may have been adjusted. __eh_free (p->original_value); // value may have been adjusted.
......
...@@ -51,6 +51,7 @@ static tree get_temp_regvar PARAMS ((tree, tree)); ...@@ -51,6 +51,7 @@ static tree get_temp_regvar PARAMS ((tree, tree));
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *)); static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
static tree build_new_1 PARAMS ((tree)); static tree build_new_1 PARAMS ((tree));
static tree get_cookie_size PARAMS ((tree)); static tree get_cookie_size PARAMS ((tree));
static tree build_dtor_call PARAMS ((tree, tree, int));
/* Set up local variable for this file. MUST BE CALLED AFTER /* Set up local variable for this file. MUST BE CALLED AFTER
INIT_DECL_PROCESSING. */ INIT_DECL_PROCESSING. */
...@@ -713,8 +714,7 @@ expand_cleanup_for_base (binfo, flag) ...@@ -713,8 +714,7 @@ expand_cleanup_for_base (binfo, flag)
/* Call the destructor. */ /* Call the destructor. */
expr = (build_scoped_method_call expr = (build_scoped_method_call
(current_class_ref, binfo, dtor_identifier, (current_class_ref, binfo, base_dtor_identifier, NULL_TREE));
build_tree_list (NULL_TREE, integer_zero_node)));
if (flag) if (flag)
expr = fold (build (COND_EXPR, void_type_node, expr = fold (build (COND_EXPR, void_type_node,
truthvalue_conversion (flag), truthvalue_conversion (flag),
...@@ -2963,6 +2963,71 @@ build_x_delete (addr, which_delete, virtual_size) ...@@ -2963,6 +2963,71 @@ build_x_delete (addr, which_delete, virtual_size)
return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE); return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE);
} }
/* Call the destructor for EXP using the IN_CHARGE parameter. FLAGS
are as for build_delete. */
static tree
build_dtor_call (exp, in_charge, flags)
tree exp;
tree in_charge;
int flags;
{
tree name = NULL_TREE;
tree call1;
tree call2;
tree call3;
tree result;
/* First, try to figure out statically which function to call. */
in_charge = fold (in_charge);
if (tree_int_cst_equal (in_charge, integer_zero_node))
name = base_dtor_identifier;
else if (tree_int_cst_equal (in_charge, integer_one_node))
name = deleting_dtor_identifier;
else if (tree_int_cst_equal (in_charge, integer_two_node))
name = complete_dtor_identifier;
if (name)
{
if (!binfo)
return build_method_call (exp, name, NULL_TREE, NULL_TREE, flags);
else
return build_scoped_method_call (exp, binfo, name, NULL_TREE);
}
/* If that didn't work, build the various alternatives. */
if (!binfo)
{
call1 = build_method_call (exp, complete_dtor_identifier,
NULL_TREE, NULL_TREE, flags);
call2 = build_method_call (exp, deleting_dtor_identifier,
NULL_TREE, NULL_TREE, flags);
call3 = build_method_call (exp, base_dtor_identifier,
NULL_TREE, NULL_TREE, flags);
}
else
{
call1 = build_scoped_method_call (exp, binfo,
complete_dtor_identifier, NULL_TREE);
call2 = build_scoped_method_call (exp, binfo,
deleting_dtor_identifier, NULL_TREE);
call3 = build_scoped_method_call (exp, binfo,
base_dtor_identifier, NULL_TREE);
}
/* Build the conditionals. */
result = build (COND_EXPR, void_type_node,
fold (build (BIT_AND_EXPR, integer_type_node,
in_charge, integer_two_node)),
call1,
call3);
result = build (COND_EXPR, void_type_node,
fold (build (BIT_AND_EXPR, integer_type_node,
in_charge, integer_one_node)),
call2,
result);
return result;
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to. /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
ADDR is an expression which yields the store to be destroyed. ADDR is an expression which yields the store to be destroyed.
AUTO_DELETE is nonzero if a call to DELETE should be made or not. AUTO_DELETE is nonzero if a call to DELETE should be made or not.
...@@ -3084,10 +3149,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3084,10 +3149,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else else
passed_auto_delete = auto_delete; passed_auto_delete = auto_delete;
expr = build_method_call expr = build_dtor_call (ref, passed_auto_delete, NULL_TREE, flags);
(ref, dtor_identifier, build_tree_list (NULL_TREE, passed_auto_delete),
NULL_TREE, flags);
if (do_delete) if (do_delete)
expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
...@@ -3111,8 +3173,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3111,8 +3173,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type); int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE; tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
tree exprstmt = NULL_TREE; tree exprstmt = NULL_TREE;
tree parent_auto_delete = auto_delete;
tree cond;
/* Set this again before we call anything, as we might get called /* Set this again before we call anything, as we might get called
recursively. */ recursively. */
...@@ -3120,50 +3180,19 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3120,50 +3180,19 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* If we have member delete or vbases, we call delete in /* If we have member delete or vbases, we call delete in
finish_function. */ finish_function. */
if (auto_delete == integer_zero_node) my_friendly_assert (auto_delete == integer_zero_node, 20000411);
cond = NULL_TREE;
else if (base_binfo == NULL_TREE
|| 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),
build_builtin_delete_call (addr),
void_zero_node);
}
else
cond = NULL_TREE;
if (cond)
exprstmt = build_tree_list (NULL_TREE, cond);
if (base_binfo
&& ! TREE_VIA_VIRTUAL (base_binfo)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
tree this_auto_delete;
if (BINFO_OFFSET_ZEROP (base_binfo))
this_auto_delete = parent_auto_delete;
else
this_auto_delete = integer_zero_node;
expr = build_scoped_method_call
(ref, base_binfo, dtor_identifier,
build_tree_list (NULL_TREE, this_auto_delete));
exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
}
/* Take care of the remaining baseclasses. */ /* Take care of the remaining baseclasses. */
for (i = 1; i < n_baseclasses; i++) for (i = 0; i < n_baseclasses; i++)
{ {
base_binfo = TREE_VEC_ELT (binfos, i); base_binfo = TREE_VEC_ELT (binfos, i);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)) if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
|| TREE_VIA_VIRTUAL (base_binfo)) || TREE_VIA_VIRTUAL (base_binfo))
continue; continue;
expr = build_scoped_method_call expr = build_scoped_method_call (ref, base_binfo,
(ref, base_binfo, dtor_identifier, base_dtor_identifier,
build_tree_list (NULL_TREE, integer_zero_node)); NULL_TREE);
exprstmt = tree_cons (NULL_TREE, expr, exprstmt); exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
} }
......
...@@ -804,10 +804,6 @@ maybe_clone_body (fn) ...@@ -804,10 +804,6 @@ maybe_clone_body (fn)
&& !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
return 0; return 0;
/* We don't yet handle destructors. */
if (DECL_DESTRUCTOR_P (fn))
return 0;
/* We know that any clones immediately follow FN in the TYPE_METHODS /* We know that any clones immediately follow FN in the TYPE_METHODS
list. */ list. */
for (clone = TREE_CHAIN (fn); for (clone = TREE_CHAIN (fn);
...@@ -850,12 +846,7 @@ maybe_clone_body (fn) ...@@ -850,12 +846,7 @@ maybe_clone_body (fn)
if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
{ {
tree in_charge; tree in_charge;
in_charge = in_charge_arg_for_name (DECL_NAME (clone));
if (DECL_COMPLETE_CONSTRUCTOR_P (clone))
in_charge = integer_one_node;
else
in_charge = integer_zero_node;
splay_tree_insert (id.decl_map, splay_tree_insert (id.decl_map,
(splay_tree_key) parm, (splay_tree_key) parm,
(splay_tree_key) in_charge); (splay_tree_key) in_charge);
......
...@@ -1337,7 +1337,7 @@ lookup_field_queue_p (binfo, data) ...@@ -1337,7 +1337,7 @@ lookup_field_queue_p (binfo, data)
struct lookup_field_info *lfi = (struct lookup_field_info *) data; struct lookup_field_info *lfi = (struct lookup_field_info *) data;
/* Don't look for constructors or destructors in base classes. */ /* Don't look for constructors or destructors in base classes. */
if (lfi->name == ctor_identifier || lfi->name == dtor_identifier) if (IDENTIFIER_CTOR_OR_DTOR_P (lfi->name))
return NULL_TREE; return NULL_TREE;
/* If this base class is hidden by the best-known value so far, we /* If this base class is hidden by the best-known value so far, we
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment