cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.

* cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.
	(complete_dtor_identifier): New macro.
	(CLASSTYPE_FIRST_CONVERSION): Remove.
	(CLASSTYPE_CONSTRUCTOR_SLOT): New macro.
	(CLASSTYPE_DESTRUCTOR_SLOT): Likewise.
	(CLASSTYPE_FIRST_CONVERSION_SLOT): Likewise.
	(CLASSTYPE_CONSTRUCTORS): Likewise.
	(CLASSTYPE_DESTRUCTORS): Likewise.
	(lang_decl): Add cloned_function.
	(DECL_COMPLETE_CONSTRUCTOR_P): New macro.
	(DECL_BASE_CONSTRUCTOR_P): Likewise.
	(DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P): Likewise.
	(DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P): Likewise.
	(DECL_CLONED_FUNCTION_P): Likewise.
	(DECL_CLONED_FUNCTION): Likewise.
	(clone_function_decl): Declare.
	(maybe_clone_body): Likewise.
	* call.c (build_user_type_conversion_1): Call complete object
	constructors in the new ABI.
	(build_new_method_call): Don't add in-charge parameters under the
	new ABI.
	* class.c (add_method): Use DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P,
	DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P, CLASSTYPE_CONSTRUCTOR_SLOT, and
	CLASSTYPE_DESTRUCTOR_SLOT.
	(build_clone): New function.
	(clone_function_decl): Likewise.
	(clone_constructors_and_destructors): Likewise.
	(check_bases_and_members): Use it.
	* decl.c (iniitialize_predefined_identifiers): Initialize
	complete_dtor_identifier.
	(finish_function): Don't add extra code to a clone.
	(lang_mark_tree): Mark cloned_function.
	* decl2.c (mark_used): Don't bother trying to instantiate things
	we synthesized.
	* dump.c (dequeue_and_dump): Don't dump CP_DECL_CONTEXT twice.
	* method.c (set_mangled_name_for_decl): Don't treat clones as
	constructors.
	(synthesize_method): Sythesize cloned functions, not the clones.
	* optimize.c (inline_data): Update comment on ret_label.
	(remap_block): Don't assume DECL_INITIAL exists.
	(copy_body_r): Allow ret_label to be NULL.
	(maybe_clone_body): Define.
	* pt.c (tsubst_decl): Handle clones.
	(instantiate_clone): New function.
	(instantiate_template): Use it.
	(set_mangled_name_for_template_decl): Don't treat clones as
	constructors.
	* search.c (lookup_fnfields_1): Use CLASSTYPE_CONSTRUCTOR_SLOT,
	CLASSTYPE_DESTRUCTOR_SLOT, and CLASSTYPE_FIRST_CONVERSION_SLOT.
	* semantics.c (expand_body): Clone function bodies as necessary.

From-SVN: r33084
This commit is contained in:
Mark Mitchell 2000-04-11 20:16:36 +00:00 committed by Mark Mitchell
parent c23c855f38
commit db9b217498
12 changed files with 515 additions and 46 deletions

View File

@ -1,5 +1,56 @@
2000-04-11 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.
(complete_dtor_identifier): New macro.
(CLASSTYPE_FIRST_CONVERSION): Remove.
(CLASSTYPE_CONSTRUCTOR_SLOT): New macro.
(CLASSTYPE_DESTRUCTOR_SLOT): Likewise.
(CLASSTYPE_FIRST_CONVERSION_SLOT): Likewise.
(CLASSTYPE_CONSTRUCTORS): Likewise.
(CLASSTYPE_DESTRUCTORS): Likewise.
(lang_decl): Add cloned_function.
(DECL_COMPLETE_CONSTRUCTOR_P): New macro.
(DECL_BASE_CONSTRUCTOR_P): Likewise.
(DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P): Likewise.
(DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P): Likewise.
(DECL_CLONED_FUNCTION_P): Likewise.
(DECL_CLONED_FUNCTION): Likewise.
(clone_function_decl): Declare.
(maybe_clone_body): Likewise.
* call.c (build_user_type_conversion_1): Call complete object
constructors in the new ABI.
(build_new_method_call): Don't add in-charge parameters under the
new ABI.
* class.c (add_method): Use DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P,
DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P, CLASSTYPE_CONSTRUCTOR_SLOT, and
CLASSTYPE_DESTRUCTOR_SLOT.
(build_clone): New function.
(clone_function_decl): Likewise.
(clone_constructors_and_destructors): Likewise.
(check_bases_and_members): Use it.
* decl.c (iniitialize_predefined_identifiers): Initialize
complete_dtor_identifier.
(finish_function): Don't add extra code to a clone.
(lang_mark_tree): Mark cloned_function.
* decl2.c (mark_used): Don't bother trying to instantiate things
we synthesized.
* dump.c (dequeue_and_dump): Don't dump CP_DECL_CONTEXT twice.
* method.c (set_mangled_name_for_decl): Don't treat clones as
constructors.
(synthesize_method): Sythesize cloned functions, not the clones.
* optimize.c (inline_data): Update comment on ret_label.
(remap_block): Don't assume DECL_INITIAL exists.
(copy_body_r): Allow ret_label to be NULL.
(maybe_clone_body): Define.
* pt.c (tsubst_decl): Handle clones.
(instantiate_clone): New function.
(instantiate_template): Use it.
(set_mangled_name_for_template_decl): Don't treat clones as
constructors.
* search.c (lookup_fnfields_1): Use CLASSTYPE_CONSTRUCTOR_SLOT,
CLASSTYPE_DESTRUCTOR_SLOT, and CLASSTYPE_FIRST_CONVERSION_SLOT.
* semantics.c (expand_body): Clone function bodies as necessary.
* optimize.c (remap_decl): Avoid sharing structure for arrays
whose size is only known at run-time.
* tree.c (copy_tree_r): Don't copy PARM_DECLs.

View File

@ -2277,7 +2277,12 @@ build_user_type_conversion_1 (totype, expr, flags)
tree templates = NULL_TREE;
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
ctors = lookup_fnfields (TYPE_BINFO (totype),
(flag_new_abi
? complete_ctor_identifier
: ctor_identifier),
0);
if (IS_AGGR_TYPE (fromtype)
&& (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
convs = lookup_conversions (fromtype);
@ -4253,22 +4258,26 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|| name == base_ctor_identifier)
{
pretty_name = constructor_name (basetype);
/* Add the in-charge parameter as an implicit first argument. */
if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
if (!flag_new_abi)
{
tree in_charge;
/* Add the in-charge parameter as an implicit first argument. */
if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
tree in_charge;
if (name == complete_ctor_identifier)
in_charge = integer_one_node;
else
in_charge = integer_zero_node;
if (name == complete_ctor_identifier)
in_charge = integer_one_node;
else
in_charge = integer_zero_node;
args = tree_cons (NULL_TREE, in_charge, args);
args = tree_cons (NULL_TREE, in_charge, args);
}
/* We want to call the normal constructor function under the
old ABI. */
name = ctor_identifier;
}
/* We want to call the normal constructor function under the old
ABI. */
name = ctor_identifier;
}
else
pretty_name = name;

View File

@ -174,6 +174,8 @@ static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
vcall_offset_data *));
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
static void mark_primary_bases PARAMS ((tree));
static void clone_constructors_and_destructors PARAMS ((tree));
static tree build_clone PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
@ -1150,14 +1152,15 @@ add_method (type, fields, method)
method_vec = CLASSTYPE_METHOD_VEC (type);
len = TREE_VEC_LENGTH (method_vec);
if (DECL_NAME (method) == constructor_name (type))
/* A new constructor or destructor. Constructors go in
slot 0; destructors go in slot 1. */
slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
/* Constructors and destructors go in special slots. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
slot = CLASSTYPE_CONSTRUCTOR_SLOT;
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
slot = CLASSTYPE_DESTRUCTOR_SLOT;
else
{
/* See if we already have an entry with this name. */
for (slot = 2; slot < len; ++slot)
for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
if (!TREE_VEC_ELT (method_vec, slot)
|| (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
slot)))
@ -3855,6 +3858,151 @@ check_methods (t)
}
}
/* FN is a constructor or destructor. Clone the declaration to create
a specialized in-charge or not-in-charge version, as indicated by
NAME. */
static tree
build_clone (fn, name)
tree fn;
tree name;
{
tree parms;
tree clone;
/* Copy the function. */
clone = copy_decl (fn);
/* Remember where this function came from. */
DECL_CLONED_FUNCTION (clone) = fn;
/* Reset the function name. */
DECL_NAME (clone) = name;
DECL_ASSEMBLER_NAME (clone) = DECL_NAME (clone);
/* There's no pending inline data for this function. */
DECL_PENDING_INLINE_INFO (clone) = NULL;
DECL_PENDING_INLINE_P (clone) = 0;
/* And it hasn't yet been deferred. */
DECL_DEFERRED_FN (clone) = 0;
/* If there was an in-charge paramter, drop it from the function
type. */
if (DECL_HAS_IN_CHARGE_PARM_P (clone))
{
tree basetype;
tree parmtypes;
tree exceptions;
exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone));
/* Skip the `this' parameter. */
parmtypes = TREE_CHAIN (parmtypes);
/* Skip the in-charge parameter. */
parmtypes = TREE_CHAIN (parmtypes);
TREE_TYPE (clone)
= build_cplus_method_type (basetype,
TREE_TYPE (TREE_TYPE (clone)),
parmtypes);
if (exceptions)
TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
exceptions);
}
/* Copy the function parameters. But, DECL_ARGUMENTS aren't
function parameters; instead, those are the template parameters. */
if (TREE_CODE (clone) != TEMPLATE_DECL)
{
DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone));
/* Remove the in-charge parameter. */
if (DECL_HAS_IN_CHARGE_PARM_P (clone))
{
TREE_CHAIN (DECL_ARGUMENTS (clone))
= TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
}
for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
{
DECL_CONTEXT (parms) = clone;
copy_lang_decl (parms);
}
}
/* Mangle the function name. */
set_mangled_name_for_decl (clone);
/* Create the RTL for this function. */
DECL_RTL (clone) = NULL_RTX;
rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof);
/* Make it easy to find the CLONE given the FN. */
TREE_CHAIN (clone) = TREE_CHAIN (fn);
TREE_CHAIN (fn) = clone;
/* If this is a template, handle the DECL_TEMPLATE_RESULT as well. */
if (TREE_CODE (clone) == TEMPLATE_DECL)
{
tree result;
DECL_TEMPLATE_RESULT (clone)
= build_clone (DECL_TEMPLATE_RESULT (clone), name);
result = DECL_TEMPLATE_RESULT (clone);
DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result));
DECL_TI_TEMPLATE (result) = clone;
}
return clone;
}
/* Produce declarations for all appropriate clones of FN. If
UPDATE_METHOD_VEC_P is non-zero, the clones are added to the
CLASTYPE_METHOD_VEC as well. */
void
clone_function_decl (fn, update_method_vec_p)
tree fn;
int update_method_vec_p;
{
tree clone;
if (DECL_CONSTRUCTOR_P (fn))
{
clone = build_clone (fn, complete_ctor_identifier);
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), NULL, clone);
clone = build_clone (fn, base_ctor_identifier);
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), NULL, clone);
}
else
/* We don't do destructors yet. */
my_friendly_abort (20000411);
}
/* For each of the constructors and destructors in T, create an
in-charge and not-in-charge variant. */
static void
clone_constructors_and_destructors (t)
tree t;
{
tree fns;
/* We only clone constructors and destructors under the new ABI. */
if (!flag_new_abi)
return;
/* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail
out now. */
if (!CLASSTYPE_METHOD_VEC (t))
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))
clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
/* For now, we don't do the destructors. */
}
/* Remove all zero-width bit-fields from T. */
static void
@ -3950,6 +4098,10 @@ check_bases_and_members (t, empty_p)
cant_have_const_ctor,
no_const_asn_ref);
/* Create the in-charge and not-in-charge variants of constructors
and destructors. */
clone_constructors_and_destructors (t);
/* Process the using-declarations. */
for (; access_decls; access_decls = TREE_CHAIN (access_decls))
handle_using_decl (TREE_VALUE (access_decls), t);

View File

@ -559,6 +559,7 @@ enum cp_tree_index
CPTI_COMPLETE_CTOR_IDENTIFIER,
CPTI_BASE_CTOR_IDENTIFIER,
CPTI_DTOR_IDENTIFIER,
CPTI_COMPLETE_DTOR_IDENTIFIER,
CPTI_BASE_DTOR_IDENTIFIER,
CPTI_DELETING_DTOR_IDENTIFIER,
CPTI_DELTA2_IDENTIFIER,
@ -653,14 +654,18 @@ extern tree cp_global_trees[CPTI_MAX];
frequently. */
/* The name of a constructor that takes an in-charge parameter to
decide whether or not to call virtual base classes. */
decide whether or not to construct virtual base classes. */
#define ctor_identifier cp_global_trees[CPTI_CTOR_IDENTIFIER]
/* The name of a constructor that constructs virtual base classes. */
#define complete_ctor_identifier cp_global_trees[CPTI_COMPLETE_CTOR_IDENTIFIER]
/* The name of a constructor that does not construct virtual base classes. */
#define base_ctor_identifier cp_global_trees[CPTI_BASE_CTOR_IDENTIFIER]
/* The name of a destructor that destroys virtual base classes. */
/* The name of a destructor that takes an in-charge parameter to
decide whether or not to destroy virtual base classes and whether
or not to delete the object. */
#define dtor_identifier cp_global_trees[CPTI_DTOR_IDENTIFIER]
/* The name of a destructor that destroys virtual base classes. */
#define complete_dtor_identifier cp_global_trees[CPTI_COMPLETE_DTOR_IDENTIFIER]
/* The name of a destructor that does not destroy virtual base
classes. */
#define base_dtor_identifier cp_global_trees[CPTI_BASE_DTOR_IDENTIFIER]
@ -1475,17 +1480,29 @@ struct lang_type
either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
functions with the same name end up in the same slot. The first
two elements are for constructors, and destructors, respectively.
These are followed by ordinary member functions. There may be
empty entries at the end of the vector. */
Any conversion operators are next, followed by ordinary member
functions. There may be empty entries at the end of the vector. */
#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* The first type conversion operator in the class (the others can be
searched with TREE_CHAIN), or the first non-constructor function if
there are no type conversion operators. */
#define CLASSTYPE_FIRST_CONVERSION(NODE) \
TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 2 \
? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \
: NULL_TREE;
/* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */
#define CLASSTYPE_CONSTRUCTOR_SLOT 0
/* The slot in the CLASSTYPE_METHOD_VEC where destructors go. */
#define CLASSTYPE_DESTRUCTOR_SLOT 1
/* The first slot in the CLASSTYPE_METHOD_VEC where conversion
operators can appear. */
#define CLASSTYPE_FIRST_CONVERSION_SLOT 2
/* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These
are the constructors that take an in-charge parameter. */
#define CLASSTYPE_CONSTRUCTORS(NODE) \
(TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT))
/* A FUNCTION_DECL for the destructor for NODE. These are te
destructors that take an in-charge parameter. */
#define CLASSTYPE_DESTRUCTORS(NODE) \
(TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT))
/* Mark bits for depth-first and breath-first searches. */
@ -1882,6 +1899,9 @@ struct lang_decl
/* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
tree saved_tree;
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
tree cloned_function;
union
{
tree sorted_fields;
@ -1909,6 +1929,24 @@ struct lang_decl
/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */
#define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr)
/* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a complete
object. */
#define DECL_COMPLETE_CONSTRUCTOR_P(NODE) \
(DECL_CONSTRUCTOR_P (NODE) \
&& DECL_NAME (NODE) == complete_ctor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a base
object. */
#define DECL_BASE_CONSTRUCTOR_P(NODE) \
(DECL_CONSTRUCTOR_P (NODE) \
&& DECL_NAME (NODE) == base_ctor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a constructor, but not either the
specialized in-charge constructor or the specialized not-in-charge
constructor. */
#define DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P(NODE) \
(DECL_CONSTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE))
/* Nonzero if NODE (a FUNCTION_DECL) is a copy constructor. */
#define DECL_COPY_CONSTRUCTOR_P(NODE) \
(DECL_CONSTRUCTOR_P (NODE) && copy_args_p (NODE))
@ -1919,6 +1957,22 @@ struct lang_decl
(DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE)) \
&& DECL_LANGUAGE (NODE) == lang_cplusplus)
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the
specialized in-charge constructor, in-charge deleting constructor,
or the the base destructor. */
#define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE) \
(DECL_DESTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE))
/* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or
destructor. */
#define DECL_CLONED_FUNCTION_P(NODE) \
(DECL_CLONED_FUNCTION (NODE) != NULL_TREE)
/* If DECL_CLONED_FUNCTION_P holds, this is the function that was
cloned. */
#define DECL_CLONED_FUNCTION(NODE) \
(DECL_LANG_SPECIFIC (NODE)->cloned_function)
/* Non-zero if NODE is a user-defined conversion operator. */
#define DECL_CONV_FN_P(NODE) \
(IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE)))
@ -3723,6 +3777,7 @@ extern tree build_type_conversion PARAMS ((tree, tree, int));
extern tree build_expr_type_conversion PARAMS ((int, tree, int));
extern tree type_promotes_to PARAMS ((tree));
extern tree perform_qualification_conversions PARAMS ((tree, tree));
extern void clone_function_decl PARAMS ((tree, int));
/* decl.c */
/* resume_binding_level */
@ -4093,6 +4148,7 @@ extern tree implicitly_declare_fn PARAMS ((special_function_kind,
/* In optimize.c */
extern void optimize_function PARAMS ((tree));
extern int calls_setjmp_p PARAMS ((tree));
extern int maybe_clone_body PARAMS ((tree));
/* in pt.c */
extern void init_pt PARAMS ((void));

View File

@ -6063,6 +6063,7 @@ initialize_predefined_identifiers ()
{ "__base_ctor", &base_ctor_identifier },
{ "__comp_ctor", &complete_ctor_identifier },
{ DTOR_NAME, &dtor_identifier },
{ "__comp_dtor", &complete_dtor_identifier },
{ "__base_dtor", &base_dtor_identifier },
{ "__deleting_dtor", &deleting_dtor_identifier },
{ VTABLE_DELTA2_NAME, &delta2_identifier },
@ -13966,7 +13967,11 @@ finish_function (flags)
store_parm_decls ();
}
if (building_stmt_tree ())
/* For a cloned function, we've already got all the code we need;
there's no need to add any extra bits. */
if (building_stmt_tree () && DECL_CLONED_FUNCTION_P (fndecl))
;
else if (building_stmt_tree ())
{
if (DECL_CONSTRUCTOR_P (fndecl))
{
@ -14763,6 +14768,7 @@ lang_mark_tree (t)
{
ggc_mark_tree (ld->befriending_classes);
ggc_mark_tree (ld->saved_tree);
ggc_mark_tree (ld->cloned_function);
if (TREE_CODE (t) == TYPE_DECL)
ggc_mark_tree (ld->u.sorted_fields);
else if (TREE_CODE (t) == FUNCTION_DECL

View File

@ -5228,7 +5228,12 @@ mark_used (decl)
&& ! DECL_INITIAL (decl)
/* Kludge: don't synthesize for default args. */
&& current_function_decl)
synthesize_method (decl);
{
synthesize_method (decl);
/* If we've already synthesized the method we don't need to
instantiate it, so we can return right away. */
return;
}
/* If this is a function or variable that is an instance of some
template, we now know that we will need to actually do the

View File

@ -557,7 +557,6 @@ dequeue_and_dump (di)
case FUNCTION_DECL:
case THUNK_DECL:
dump_child ("scpe", CP_DECL_CONTEXT (t));
dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
dump_child ("args", DECL_ARGUMENTS (t));
if (DECL_EXTERNAL (t))

View File

@ -1748,7 +1748,7 @@ set_mangled_name_for_decl (decl)
DECL_ASSEMBLER_NAME (decl)
= build_decl_overload (DECL_NAME (decl), parm_types,
DECL_FUNCTION_MEMBER_P (decl)
+ DECL_CONSTRUCTOR_P (decl));
+ DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
}
/* Build an overload name for the type expression TYPE. */
@ -2359,6 +2359,15 @@ synthesize_method (fndecl)
if (at_eof)
import_export_decl (fndecl);
/* If we've been asked to synthesize a clone, just synthesize the
cloned function instead. Doing so will automatically fill in the
body for the clone. */
if (DECL_CLONED_FUNCTION_P (fndecl))
{
synthesize_method (DECL_CLONED_FUNCTION (fndecl));
return;
}
if (! context)
push_to_top_level ();
else if (nested)

View File

@ -50,7 +50,9 @@ typedef struct inline_data
inlining the body of `h', the stack will contain, `h', followed
by `g', followed by `f'. */
varray_type fns;
/* The label to jump to when a return statement is encountered. */
/* The label to jump to when a return statement is encountered. If
this value is NULL, then return statements will simply be
remapped as return statements, rather than as jumps. */
tree ret_label;
/* The map from local declarations in the inlined function to
equivalents in the function into which it is being inlined. */
@ -157,6 +159,7 @@ remap_block (scope_stmt, decls, id)
tree old_block;
tree new_block;
tree old_var;
tree *first_block;
tree fn;
/* Make the new block. */
@ -175,9 +178,12 @@ remap_block (scope_stmt, decls, id)
/* Remap the variable. */
new_var = remap_decl (old_var, id);
if (!new_var)
/* We didn't remap this variable, so we can't mess with
its TREE_CHAIN. */
/* If we didn't remap this variable, so we can't mess with
its TREE_CHAIN. If we remapped this variable to
something other than a declaration (say, if we mapped it
to a constant), then we must similarly omit any mention
of it here. */
if (!new_var || !DECL_P (new_var))
;
else
{
@ -191,8 +197,12 @@ remap_block (scope_stmt, decls, id)
function into which this block is being inlined. In
rest_of_compilation we will straighten out the BLOCK tree. */
fn = VARRAY_TREE (id->fns, 0);
BLOCK_CHAIN (new_block) = BLOCK_CHAIN (DECL_INITIAL (fn));
BLOCK_CHAIN (DECL_INITIAL (fn)) = new_block;
if (DECL_INITIAL (fn))
first_block = &BLOCK_CHAIN (DECL_INITIAL (fn));
else
first_block = &DECL_INITIAL (fn);
BLOCK_CHAIN (new_block) = *first_block;
*first_block = new_block;
/* Remember the remapped block. */
splay_tree_insert (id->decl_map,
(splay_tree_key) old_block,
@ -261,7 +271,7 @@ copy_body_r (tp, walk_subtrees, data)
/* If this is a RETURN_STMT, change it into an EXPR_STMT and a
GOTO_STMT with the RET_LABEL as its target. */
if (TREE_CODE (*tp) == RETURN_STMT)
if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label)
{
tree return_stmt = *tp;
tree goto_stmt;
@ -774,3 +784,106 @@ calls_setjmp_p (fn)
!= NULL_TREE);
}
/* FN is a function that has a complete body. Clone the body as
necessary. Returns non-zero if there's no longer any need to
process the main body. */
int
maybe_clone_body (fn)
tree fn;
{
inline_data id;
tree clone;
/* We don't clone constructors and destructors under the old ABI. */
if (!flag_new_abi)
return 0;
/* We only clone constructors and destructors. */
if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
&& !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
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
list. */
for (clone = TREE_CHAIN (fn);
clone && DECL_CLONED_FUNCTION_P (clone);
clone = TREE_CHAIN (clone))
{
tree parm;
tree clone_parm;
int parmno;
/* Update CLONE's source position information to match FN's. */
DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
/* Start processing the function. */
push_to_top_level ();
start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
store_parm_decls ();
/* Just clone the body, as if we were making an inline call.
But, remap the parameters in the callee to the parameters of
caller. If there's an in-charge parameter, map it to an
appropriate constant. */
memset (&id, 0, sizeof (id));
VARRAY_TREE_INIT (id.fns, 2, "fns");
VARRAY_PUSH_TREE (id.fns, clone);
VARRAY_PUSH_TREE (id.fns, fn);
/* Remap the parameters. */
id.decl_map = splay_tree_new (splay_tree_compare_pointers,
NULL, NULL);
for (parmno = 0,
parm = DECL_ARGUMENTS (fn),
clone_parm = DECL_ARGUMENTS (clone);
parm;
++parmno,
parm = TREE_CHAIN (parm))
{
/* Map the in-charge parameter to an appropriate constant. */
if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
{
tree in_charge;
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_key) parm,
(splay_tree_key) in_charge);
}
/* Map other parameters to their equivalents in the cloned
function. */
else
{
splay_tree_insert (id.decl_map,
(splay_tree_key) parm,
(splay_tree_value) clone_parm);
clone_parm = TREE_CHAIN (clone_parm);
}
}
/* Actually copy the body. */
TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
/* Clean up. */
splay_tree_delete (id.decl_map);
VARRAY_FREE (id.fns);
/* Now, expand this function into RTL, if appropriate. */
current_function_name_declared = 1;
expand_body (finish_function (0));
pop_from_top_level ();
}
/* We don't need to process the original function any further. */
return 1;
}

View File

@ -159,6 +159,7 @@ static int template_args_equal PARAMS ((tree, tree));
static void print_template_context PARAMS ((int));
static void tsubst_default_arguments PARAMS ((tree));
static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
static tree instantiate_clone PARAMS ((tree, tree));
/* Called once to initialize pt.c. */
@ -5708,6 +5709,13 @@ tsubst_decl (t, args, type, in_decl)
DECL_PENDING_INLINE_INFO (r) = 0;
DECL_PENDING_INLINE_P (r) = 0;
TREE_USED (r) = 0;
if (DECL_CLONED_FUNCTION (r))
{
DECL_CLONED_FUNCTION (r) = tsubst (DECL_CLONED_FUNCTION (t),
args, /*complain=*/1, t);
TREE_CHAIN (r) = TREE_CHAIN (DECL_CLONED_FUNCTION (r));
TREE_CHAIN (DECL_CLONED_FUNCTION (r)) = r;
}
/* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
name. There's no need to do this in the special friend
@ -7367,6 +7375,43 @@ tsubst_expr (t, args, complain, in_decl)
return NULL_TREE;
}
/* TMPL is a TEMPLATE_DECL for a cloned constructor or destructor.
Instantiate it with the ARGS. */
static tree
instantiate_clone (tmpl, args)
tree tmpl;
tree args;
{
tree spec;
tree clone;
/* Instantiated the cloned function, rather than the clone. */
spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), args);
/* Then, see if we've already cloned the instantiation. */
for (clone = TREE_CHAIN (spec);
clone && DECL_CLONED_FUNCTION_P (clone);
clone = TREE_CHAIN (clone))
if (DECL_NAME (clone) == DECL_NAME (tmpl))
return clone;
/* If we haven't, do so know. */
if (!clone)
clone_function_decl (spec, /*update_method_vec_p=*/0);
/* Look again. */
for (clone = TREE_CHAIN (spec);
clone && DECL_CLONED_FUNCTION_P (clone);
clone = TREE_CHAIN (clone))
if (DECL_NAME (clone) == DECL_NAME (tmpl))
return clone;
/* We should always have found the clone by now. */
my_friendly_abort (20000411);
return NULL_TREE;
}
/* Instantiate the indicated variable or function template TMPL with
the template arguments in TARG_PTR. */
@ -7385,6 +7430,10 @@ instantiate_template (tmpl, targ_ptr)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
/* If this function is a clone, handle it specially. */
if (DECL_CLONED_FUNCTION_P (tmpl))
return instantiate_clone (tmpl, targ_ptr);
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (tmpl, targ_ptr);
if (spec != NULL_TREE)
@ -9389,6 +9438,11 @@ instantiate_decl (d, defer_ok)
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|| TREE_CODE (d) == VAR_DECL, 0);
/* Don't instantiate cloned functions. Instead, instantiate the
functions they cloned. */
if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
d = DECL_CLONED_FUNCTION (d);
if (DECL_TEMPLATE_INSTANTIATED (d))
/* D has already been instantiated. It might seem reasonable to
check whether or not D is an explict instantiation, and, if so,
@ -9935,7 +9989,7 @@ set_mangled_name_for_template_decl (decl)
= build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
tparms, targs,
DECL_FUNCTION_MEMBER_P (decl)
+ DECL_CONSTRUCTOR_P (decl));
+ DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
/* Restore the previously active namespace. */
current_namespace = saved_namespace;

View File

@ -1688,13 +1688,16 @@ lookup_fnfields_1 (type, name)
/* Constructors are first... */
if (name == ctor_identifier)
return methods[0] ? 0 : -1;
return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
/* and destructors are second. */
if (name == dtor_identifier)
return methods[1] ? 1 : -1;
return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
? CLASSTYPE_DESTRUCTOR_SLOT : -1);
for (i = 2; i < len && methods[i]; ++i)
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
i < len && methods[i];
++i)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
@ -1737,7 +1740,9 @@ lookup_fnfields_1 (type, name)
above so that we will always find specializations first.) */
if (IDENTIFIER_TYPENAME_P (name))
{
for (i = 2; i < len && methods[i]; ++i)
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
i < len && methods[i];
++i)
{
tmp = OVL_CURRENT (methods[i]);
if (! DECL_CONV_FN_P (tmp))

View File

@ -2717,6 +2717,16 @@ expand_body (fn)
/* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs. */
walk_tree (&DECL_SAVED_TREE (fn), simplify_aggr_init_exprs_r, NULL);
/* If this is a constructor or destructor body, we have to clone it
under the new ABI. */
if (maybe_clone_body (fn))
{
/* We don't want to process FN again, so pretend we've written
it out, even though we haven't. */
TREE_ASM_WRITTEN (fn) = 1;
return;
}
/* There's no reason to do any of the work here if we're only doing
semantic analysis; this code just generates RTL. */
if (flag_syntax_only)