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:
parent
c23c855f38
commit
db9b217498
|
@ -1,5 +1,56 @@
|
||||||
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.
|
||||||
|
(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
|
* optimize.c (remap_decl): Avoid sharing structure for arrays
|
||||||
whose size is only known at run-time.
|
whose size is only known at run-time.
|
||||||
* tree.c (copy_tree_r): Don't copy PARM_DECLs.
|
* tree.c (copy_tree_r): Don't copy PARM_DECLs.
|
||||||
|
|
|
@ -2277,7 +2277,12 @@ build_user_type_conversion_1 (totype, expr, flags)
|
||||||
tree templates = NULL_TREE;
|
tree templates = NULL_TREE;
|
||||||
|
|
||||||
if (IS_AGGR_TYPE (totype))
|
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)
|
if (IS_AGGR_TYPE (fromtype)
|
||||||
&& (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
|
&& (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
|
||||||
convs = lookup_conversions (fromtype);
|
convs = lookup_conversions (fromtype);
|
||||||
|
@ -4253,22 +4258,26 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
||||||
|| name == base_ctor_identifier)
|
|| name == base_ctor_identifier)
|
||||||
{
|
{
|
||||||
pretty_name = constructor_name (basetype);
|
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)
|
if (name == complete_ctor_identifier)
|
||||||
in_charge = integer_one_node;
|
in_charge = integer_one_node;
|
||||||
else
|
else
|
||||||
in_charge = integer_zero_node;
|
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
|
else
|
||||||
pretty_name = name;
|
pretty_name = name;
|
||||||
|
|
162
gcc/cp/class.c
162
gcc/cp/class.c
|
@ -174,6 +174,8 @@ static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
|
||||||
vcall_offset_data *));
|
vcall_offset_data *));
|
||||||
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
|
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
|
||||||
static void mark_primary_bases PARAMS ((tree));
|
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. */
|
/* Variables shared between class.c and call.c. */
|
||||||
|
|
||||||
|
@ -1150,14 +1152,15 @@ add_method (type, fields, method)
|
||||||
method_vec = CLASSTYPE_METHOD_VEC (type);
|
method_vec = CLASSTYPE_METHOD_VEC (type);
|
||||||
len = TREE_VEC_LENGTH (method_vec);
|
len = TREE_VEC_LENGTH (method_vec);
|
||||||
|
|
||||||
if (DECL_NAME (method) == constructor_name (type))
|
/* Constructors and destructors go in special slots. */
|
||||||
/* A new constructor or destructor. Constructors go in
|
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
|
||||||
slot 0; destructors go in slot 1. */
|
slot = CLASSTYPE_CONSTRUCTOR_SLOT;
|
||||||
slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
|
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
|
||||||
|
slot = CLASSTYPE_DESTRUCTOR_SLOT;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* See if we already have an entry with this name. */
|
/* 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)
|
if (!TREE_VEC_ELT (method_vec, slot)
|
||||||
|| (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
|
|| (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
|
||||||
slot)))
|
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. */
|
/* Remove all zero-width bit-fields from T. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -3950,6 +4098,10 @@ check_bases_and_members (t, empty_p)
|
||||||
cant_have_const_ctor,
|
cant_have_const_ctor,
|
||||||
no_const_asn_ref);
|
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. */
|
/* Process the using-declarations. */
|
||||||
for (; access_decls; access_decls = TREE_CHAIN (access_decls))
|
for (; access_decls; access_decls = TREE_CHAIN (access_decls))
|
||||||
handle_using_decl (TREE_VALUE (access_decls), t);
|
handle_using_decl (TREE_VALUE (access_decls), t);
|
||||||
|
|
|
@ -559,6 +559,7 @@ enum cp_tree_index
|
||||||
CPTI_COMPLETE_CTOR_IDENTIFIER,
|
CPTI_COMPLETE_CTOR_IDENTIFIER,
|
||||||
CPTI_BASE_CTOR_IDENTIFIER,
|
CPTI_BASE_CTOR_IDENTIFIER,
|
||||||
CPTI_DTOR_IDENTIFIER,
|
CPTI_DTOR_IDENTIFIER,
|
||||||
|
CPTI_COMPLETE_DTOR_IDENTIFIER,
|
||||||
CPTI_BASE_DTOR_IDENTIFIER,
|
CPTI_BASE_DTOR_IDENTIFIER,
|
||||||
CPTI_DELETING_DTOR_IDENTIFIER,
|
CPTI_DELETING_DTOR_IDENTIFIER,
|
||||||
CPTI_DELTA2_IDENTIFIER,
|
CPTI_DELTA2_IDENTIFIER,
|
||||||
|
@ -653,14 +654,18 @@ extern tree cp_global_trees[CPTI_MAX];
|
||||||
frequently. */
|
frequently. */
|
||||||
|
|
||||||
/* The name of a constructor that takes an in-charge parameter to
|
/* 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]
|
#define ctor_identifier cp_global_trees[CPTI_CTOR_IDENTIFIER]
|
||||||
/* The name of a constructor that constructs virtual base classes. */
|
/* The name of a constructor that constructs virtual base classes. */
|
||||||
#define complete_ctor_identifier cp_global_trees[CPTI_COMPLETE_CTOR_IDENTIFIER]
|
#define complete_ctor_identifier cp_global_trees[CPTI_COMPLETE_CTOR_IDENTIFIER]
|
||||||
/* The name of a constructor that does not construct virtual base classes. */
|
/* The name of a constructor that does not construct virtual base classes. */
|
||||||
#define base_ctor_identifier cp_global_trees[CPTI_BASE_CTOR_IDENTIFIER]
|
#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]
|
#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
|
/* The name of a destructor that does not destroy virtual base
|
||||||
classes. */
|
classes. */
|
||||||
#define base_dtor_identifier cp_global_trees[CPTI_BASE_DTOR_IDENTIFIER]
|
#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
|
either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
|
||||||
functions with the same name end up in the same slot. The first
|
functions with the same name end up in the same slot. The first
|
||||||
two elements are for constructors, and destructors, respectively.
|
two elements are for constructors, and destructors, respectively.
|
||||||
These are followed by ordinary member functions. There may be
|
Any conversion operators are next, followed by ordinary member
|
||||||
empty entries at the end of the vector. */
|
functions. There may be empty entries at the end of the vector. */
|
||||||
#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
|
#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
|
||||||
|
|
||||||
/* The first type conversion operator in the class (the others can be
|
/* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */
|
||||||
searched with TREE_CHAIN), or the first non-constructor function if
|
#define CLASSTYPE_CONSTRUCTOR_SLOT 0
|
||||||
there are no type conversion operators. */
|
|
||||||
#define CLASSTYPE_FIRST_CONVERSION(NODE) \
|
/* The slot in the CLASSTYPE_METHOD_VEC where destructors go. */
|
||||||
TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 2 \
|
#define CLASSTYPE_DESTRUCTOR_SLOT 1
|
||||||
? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \
|
|
||||||
: NULL_TREE;
|
/* 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. */
|
/* 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. */
|
/* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
|
||||||
tree saved_tree;
|
tree saved_tree;
|
||||||
|
|
||||||
|
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
|
||||||
|
tree cloned_function;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
tree sorted_fields;
|
tree sorted_fields;
|
||||||
|
@ -1909,6 +1929,24 @@ struct lang_decl
|
||||||
/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */
|
/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */
|
||||||
#define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr)
|
#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. */
|
/* Nonzero if NODE (a FUNCTION_DECL) is a copy constructor. */
|
||||||
#define DECL_COPY_CONSTRUCTOR_P(NODE) \
|
#define DECL_COPY_CONSTRUCTOR_P(NODE) \
|
||||||
(DECL_CONSTRUCTOR_P (NODE) && copy_args_p (NODE))
|
(DECL_CONSTRUCTOR_P (NODE) && copy_args_p (NODE))
|
||||||
|
@ -1919,6 +1957,22 @@ struct lang_decl
|
||||||
(DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE)) \
|
(DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE)) \
|
||||||
&& DECL_LANGUAGE (NODE) == lang_cplusplus)
|
&& 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. */
|
/* Non-zero if NODE is a user-defined conversion operator. */
|
||||||
#define DECL_CONV_FN_P(NODE) \
|
#define DECL_CONV_FN_P(NODE) \
|
||||||
(IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (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 build_expr_type_conversion PARAMS ((int, tree, int));
|
||||||
extern tree type_promotes_to PARAMS ((tree));
|
extern tree type_promotes_to PARAMS ((tree));
|
||||||
extern tree perform_qualification_conversions PARAMS ((tree, tree));
|
extern tree perform_qualification_conversions PARAMS ((tree, tree));
|
||||||
|
extern void clone_function_decl PARAMS ((tree, int));
|
||||||
|
|
||||||
/* decl.c */
|
/* decl.c */
|
||||||
/* resume_binding_level */
|
/* resume_binding_level */
|
||||||
|
@ -4093,6 +4148,7 @@ extern tree implicitly_declare_fn PARAMS ((special_function_kind,
|
||||||
/* In optimize.c */
|
/* In optimize.c */
|
||||||
extern void optimize_function PARAMS ((tree));
|
extern void optimize_function PARAMS ((tree));
|
||||||
extern int calls_setjmp_p PARAMS ((tree));
|
extern int calls_setjmp_p PARAMS ((tree));
|
||||||
|
extern int maybe_clone_body PARAMS ((tree));
|
||||||
|
|
||||||
/* in pt.c */
|
/* in pt.c */
|
||||||
extern void init_pt PARAMS ((void));
|
extern void init_pt PARAMS ((void));
|
||||||
|
|
|
@ -6063,6 +6063,7 @@ initialize_predefined_identifiers ()
|
||||||
{ "__base_ctor", &base_ctor_identifier },
|
{ "__base_ctor", &base_ctor_identifier },
|
||||||
{ "__comp_ctor", &complete_ctor_identifier },
|
{ "__comp_ctor", &complete_ctor_identifier },
|
||||||
{ DTOR_NAME, &dtor_identifier },
|
{ DTOR_NAME, &dtor_identifier },
|
||||||
|
{ "__comp_dtor", &complete_dtor_identifier },
|
||||||
{ "__base_dtor", &base_dtor_identifier },
|
{ "__base_dtor", &base_dtor_identifier },
|
||||||
{ "__deleting_dtor", &deleting_dtor_identifier },
|
{ "__deleting_dtor", &deleting_dtor_identifier },
|
||||||
{ VTABLE_DELTA2_NAME, &delta2_identifier },
|
{ VTABLE_DELTA2_NAME, &delta2_identifier },
|
||||||
|
@ -13966,7 +13967,11 @@ finish_function (flags)
|
||||||
store_parm_decls ();
|
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))
|
if (DECL_CONSTRUCTOR_P (fndecl))
|
||||||
{
|
{
|
||||||
|
@ -14763,6 +14768,7 @@ lang_mark_tree (t)
|
||||||
{
|
{
|
||||||
ggc_mark_tree (ld->befriending_classes);
|
ggc_mark_tree (ld->befriending_classes);
|
||||||
ggc_mark_tree (ld->saved_tree);
|
ggc_mark_tree (ld->saved_tree);
|
||||||
|
ggc_mark_tree (ld->cloned_function);
|
||||||
if (TREE_CODE (t) == TYPE_DECL)
|
if (TREE_CODE (t) == TYPE_DECL)
|
||||||
ggc_mark_tree (ld->u.sorted_fields);
|
ggc_mark_tree (ld->u.sorted_fields);
|
||||||
else if (TREE_CODE (t) == FUNCTION_DECL
|
else if (TREE_CODE (t) == FUNCTION_DECL
|
||||||
|
|
|
@ -5228,7 +5228,12 @@ mark_used (decl)
|
||||||
&& ! DECL_INITIAL (decl)
|
&& ! DECL_INITIAL (decl)
|
||||||
/* Kludge: don't synthesize for default args. */
|
/* Kludge: don't synthesize for default args. */
|
||||||
&& current_function_decl)
|
&& 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
|
/* 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
|
template, we now know that we will need to actually do the
|
||||||
|
|
|
@ -557,7 +557,6 @@ dequeue_and_dump (di)
|
||||||
|
|
||||||
case FUNCTION_DECL:
|
case FUNCTION_DECL:
|
||||||
case THUNK_DECL:
|
case THUNK_DECL:
|
||||||
dump_child ("scpe", CP_DECL_CONTEXT (t));
|
|
||||||
dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
|
dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
|
||||||
dump_child ("args", DECL_ARGUMENTS (t));
|
dump_child ("args", DECL_ARGUMENTS (t));
|
||||||
if (DECL_EXTERNAL (t))
|
if (DECL_EXTERNAL (t))
|
||||||
|
|
|
@ -1748,7 +1748,7 @@ set_mangled_name_for_decl (decl)
|
||||||
DECL_ASSEMBLER_NAME (decl)
|
DECL_ASSEMBLER_NAME (decl)
|
||||||
= build_decl_overload (DECL_NAME (decl), parm_types,
|
= build_decl_overload (DECL_NAME (decl), parm_types,
|
||||||
DECL_FUNCTION_MEMBER_P (decl)
|
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. */
|
/* Build an overload name for the type expression TYPE. */
|
||||||
|
@ -2359,6 +2359,15 @@ synthesize_method (fndecl)
|
||||||
if (at_eof)
|
if (at_eof)
|
||||||
import_export_decl (fndecl);
|
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)
|
if (! context)
|
||||||
push_to_top_level ();
|
push_to_top_level ();
|
||||||
else if (nested)
|
else if (nested)
|
||||||
|
|
|
@ -50,7 +50,9 @@ typedef struct inline_data
|
||||||
inlining the body of `h', the stack will contain, `h', followed
|
inlining the body of `h', the stack will contain, `h', followed
|
||||||
by `g', followed by `f'. */
|
by `g', followed by `f'. */
|
||||||
varray_type fns;
|
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;
|
tree ret_label;
|
||||||
/* The map from local declarations in the inlined function to
|
/* The map from local declarations in the inlined function to
|
||||||
equivalents in the function into which it is being inlined. */
|
equivalents in the function into which it is being inlined. */
|
||||||
|
@ -157,6 +159,7 @@ remap_block (scope_stmt, decls, id)
|
||||||
tree old_block;
|
tree old_block;
|
||||||
tree new_block;
|
tree new_block;
|
||||||
tree old_var;
|
tree old_var;
|
||||||
|
tree *first_block;
|
||||||
tree fn;
|
tree fn;
|
||||||
|
|
||||||
/* Make the new block. */
|
/* Make the new block. */
|
||||||
|
@ -175,9 +178,12 @@ remap_block (scope_stmt, decls, id)
|
||||||
|
|
||||||
/* Remap the variable. */
|
/* Remap the variable. */
|
||||||
new_var = remap_decl (old_var, id);
|
new_var = remap_decl (old_var, id);
|
||||||
if (!new_var)
|
/* If we didn't remap this variable, so we can't mess with
|
||||||
/* We didn't remap this variable, so we can't mess with
|
its TREE_CHAIN. If we remapped this variable to
|
||||||
its TREE_CHAIN. */
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -191,8 +197,12 @@ remap_block (scope_stmt, decls, id)
|
||||||
function into which this block is being inlined. In
|
function into which this block is being inlined. In
|
||||||
rest_of_compilation we will straighten out the BLOCK tree. */
|
rest_of_compilation we will straighten out the BLOCK tree. */
|
||||||
fn = VARRAY_TREE (id->fns, 0);
|
fn = VARRAY_TREE (id->fns, 0);
|
||||||
BLOCK_CHAIN (new_block) = BLOCK_CHAIN (DECL_INITIAL (fn));
|
if (DECL_INITIAL (fn))
|
||||||
BLOCK_CHAIN (DECL_INITIAL (fn)) = new_block;
|
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. */
|
/* Remember the remapped block. */
|
||||||
splay_tree_insert (id->decl_map,
|
splay_tree_insert (id->decl_map,
|
||||||
(splay_tree_key) old_block,
|
(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
|
/* If this is a RETURN_STMT, change it into an EXPR_STMT and a
|
||||||
GOTO_STMT with the RET_LABEL as its target. */
|
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 return_stmt = *tp;
|
||||||
tree goto_stmt;
|
tree goto_stmt;
|
||||||
|
@ -774,3 +784,106 @@ calls_setjmp_p (fn)
|
||||||
!= NULL_TREE);
|
!= 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;
|
||||||
|
}
|
||||||
|
|
56
gcc/cp/pt.c
56
gcc/cp/pt.c
|
@ -159,6 +159,7 @@ static int template_args_equal PARAMS ((tree, tree));
|
||||||
static void print_template_context PARAMS ((int));
|
static void print_template_context PARAMS ((int));
|
||||||
static void tsubst_default_arguments PARAMS ((tree));
|
static void tsubst_default_arguments PARAMS ((tree));
|
||||||
static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
|
static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
|
||||||
|
static tree instantiate_clone PARAMS ((tree, tree));
|
||||||
|
|
||||||
/* Called once to initialize pt.c. */
|
/* 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_INFO (r) = 0;
|
||||||
DECL_PENDING_INLINE_P (r) = 0;
|
DECL_PENDING_INLINE_P (r) = 0;
|
||||||
TREE_USED (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
|
/* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
|
||||||
name. There's no need to do this in the special friend
|
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;
|
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
|
/* Instantiate the indicated variable or function template TMPL with
|
||||||
the template arguments in TARG_PTR. */
|
the template arguments in TARG_PTR. */
|
||||||
|
|
||||||
|
@ -7385,6 +7430,10 @@ instantiate_template (tmpl, targ_ptr)
|
||||||
|
|
||||||
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
|
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. */
|
/* Check to see if we already have this specialization. */
|
||||||
spec = retrieve_specialization (tmpl, targ_ptr);
|
spec = retrieve_specialization (tmpl, targ_ptr);
|
||||||
if (spec != NULL_TREE)
|
if (spec != NULL_TREE)
|
||||||
|
@ -9389,6 +9438,11 @@ instantiate_decl (d, defer_ok)
|
||||||
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|
||||||
|| TREE_CODE (d) == VAR_DECL, 0);
|
|| 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))
|
if (DECL_TEMPLATE_INSTANTIATED (d))
|
||||||
/* D has already been instantiated. It might seem reasonable to
|
/* D has already been instantiated. It might seem reasonable to
|
||||||
check whether or not D is an explict instantiation, and, if so,
|
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,
|
= build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
|
||||||
tparms, targs,
|
tparms, targs,
|
||||||
DECL_FUNCTION_MEMBER_P (decl)
|
DECL_FUNCTION_MEMBER_P (decl)
|
||||||
+ DECL_CONSTRUCTOR_P (decl));
|
+ DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
|
||||||
|
|
||||||
/* Restore the previously active namespace. */
|
/* Restore the previously active namespace. */
|
||||||
current_namespace = saved_namespace;
|
current_namespace = saved_namespace;
|
||||||
|
|
|
@ -1688,13 +1688,16 @@ lookup_fnfields_1 (type, name)
|
||||||
|
|
||||||
/* Constructors are first... */
|
/* Constructors are first... */
|
||||||
if (name == ctor_identifier)
|
if (name == ctor_identifier)
|
||||||
return methods[0] ? 0 : -1;
|
return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
|
||||||
|
? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
|
||||||
/* and destructors are second. */
|
/* and destructors are second. */
|
||||||
if (name == dtor_identifier)
|
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
|
#ifdef GATHER_STATISTICS
|
||||||
n_outer_fields_searched++;
|
n_outer_fields_searched++;
|
||||||
|
@ -1737,7 +1740,9 @@ lookup_fnfields_1 (type, name)
|
||||||
above so that we will always find specializations first.) */
|
above so that we will always find specializations first.) */
|
||||||
if (IDENTIFIER_TYPENAME_P (name))
|
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]);
|
tmp = OVL_CURRENT (methods[i]);
|
||||||
if (! DECL_CONV_FN_P (tmp))
|
if (! DECL_CONV_FN_P (tmp))
|
||||||
|
|
|
@ -2717,6 +2717,16 @@ expand_body (fn)
|
||||||
/* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs. */
|
/* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs. */
|
||||||
walk_tree (&DECL_SAVED_TREE (fn), simplify_aggr_init_exprs_r, NULL);
|
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
|
/* There's no reason to do any of the work here if we're only doing
|
||||||
semantic analysis; this code just generates RTL. */
|
semantic analysis; this code just generates RTL. */
|
||||||
if (flag_syntax_only)
|
if (flag_syntax_only)
|
||||||
|
|
Loading…
Reference in New Issue