Do put the VTT parameter in DECL_ARGUMENTS.

* cp-tree.h (struct cp_language_function): Add x_vtt_parm.
        (current_vtt_parm): New macro.
        (struct lang_decl_flags): Add has_vtt_parm_p, remove vtt_parm.
        (DECL_HAS_VTT_PARM_P): New macro.
        (DECL_VTT_PARM): Remove.
        (FUNCTION_FIRST_USER_PARMTYPE, FUNCTION_FIRST_USER_PARM): New macros.
        * decl.c (duplicate_decls): Only copy the operator code if
        appropriate.
        (start_function): Set current_vtt_parm.
        (lang_mark_tree): Don't mark vtt_parm.
        * decl2.c (maybe_retrofit_in_chrg): Do add the VTT parm to
        DECL_ARGUMENTS.  Set DECL_HAS_VTT_PARM_P.
        * class.c (build_clone): Maybe remove the VTT parm.
        * optimize.c (maybe_clone_body): Set up the VTT parm.
        * pt.c (copy_default_args_to_explicit_spec): Preserve the VTT parm.
        * call.c (build_over_call): Just allow the VTT arg.
        * method.c (make_thunk): Don't set DECL_VTT_PARM.
        (do_build_copy_constructor): Use FUNCTION_FIRST_USER_PARM.
        (synthesize_method): Use FUNCTION_FIRST_USER_PARMTYPE.
        * decl.c (grokdeclarator, copy_args_p, grok_ctor_properties): Likewise.
        * error.c (dump_function_decl): Likewise.
        * call.c (build_user_type_conversion_1, convert_like_real): Abort
        if we try to call a constructor with in-charge or VTT parms.
        * method.c (skip_artificial_parms_for): New fn.
        * call.c (add_function_candidate, build_over_call): Call it.
        * call.c (build_new_method_call): Use current_vtt_parm.
        * init.c (expand_virtual_init): Likewise.
        * class.c (same_signature_p): No longer static.
        * cp-tree.h: Declare it.
        * search.c (look_for_overrides_r): Use it.

From-SVN: r39841
This commit is contained in:
Jason Merrill 2001-02-18 14:08:00 -05:00 committed by Jason Merrill
parent 3118975871
commit e0fff4b3a7
12 changed files with 195 additions and 132 deletions

View File

@ -1,3 +1,37 @@
2001-02-18 Jason Merrill <jason@redhat.com>
Do put the VTT parameter in DECL_ARGUMENTS.
* cp-tree.h (struct cp_language_function): Add x_vtt_parm.
(current_vtt_parm): New macro.
(struct lang_decl_flags): Add has_vtt_parm_p, remove vtt_parm.
(DECL_HAS_VTT_PARM_P): New macro.
(DECL_VTT_PARM): Remove.
(FUNCTION_FIRST_USER_PARMTYPE, FUNCTION_FIRST_USER_PARM): New macros.
* decl.c (duplicate_decls): Only copy the operator code if
appropriate.
(start_function): Set current_vtt_parm.
(lang_mark_tree): Don't mark vtt_parm.
* decl2.c (maybe_retrofit_in_chrg): Do add the VTT parm to
DECL_ARGUMENTS. Set DECL_HAS_VTT_PARM_P.
* class.c (build_clone): Maybe remove the VTT parm.
* optimize.c (maybe_clone_body): Set up the VTT parm.
* pt.c (copy_default_args_to_explicit_spec): Preserve the VTT parm.
* call.c (build_over_call): Just allow the VTT arg.
* method.c (make_thunk): Don't set DECL_VTT_PARM.
(do_build_copy_constructor): Use FUNCTION_FIRST_USER_PARM.
(synthesize_method): Use FUNCTION_FIRST_USER_PARMTYPE.
* decl.c (grokdeclarator, copy_args_p, grok_ctor_properties): Likewise.
* error.c (dump_function_decl): Likewise.
* call.c (build_user_type_conversion_1, convert_like_real): Abort
if we try to call a constructor with in-charge or VTT parms.
* method.c (skip_artificial_parms_for): New fn.
* call.c (add_function_candidate, build_over_call): Call it.
* call.c (build_new_method_call): Use current_vtt_parm.
* init.c (expand_virtual_init): Likewise.
* class.c (same_signature_p): No longer static.
* cp-tree.h: Declare it.
* search.c (look_for_overrides_r): Use it.
2001-02-17 Mark Mitchell <mark@codesourcery.com> 2001-02-17 Mark Mitchell <mark@codesourcery.com>
* init.c (build_new): Allow enumeration types for the array-bounds * init.c (build_new): Allow enumeration types for the array-bounds

View File

@ -1305,17 +1305,12 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
tree parmnode, argnode; tree parmnode, argnode;
int viable = 1; int viable = 1;
/* The `this' and `in_chrg' arguments to constructors are not considered /* The `this', `in_chrg' and VTT arguments to constructors are not
in overload resolution. */ considered in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn)) if (DECL_CONSTRUCTOR_P (fn))
{ {
parmlist = TREE_CHAIN (parmlist); parmlist = skip_artificial_parms_for (fn, parmlist);
arglist = TREE_CHAIN (arglist); arglist = skip_artificial_parms_for (fn, arglist);
if (DECL_HAS_IN_CHARGE_PARM_P (fn))
{
parmlist = TREE_CHAIN (parmlist);
arglist = TREE_CHAIN (arglist);
}
} }
len = list_length (arglist); len = list_length (arglist);
@ -2382,10 +2377,11 @@ build_user_type_conversion_1 (totype, expr, flags)
t = build_int_2 (0, 0); t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype); TREE_TYPE (t) = build_pointer_type (totype);
args = build_tree_list (NULL_TREE, expr); args = build_tree_list (NULL_TREE, expr);
if (DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))) if (DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
args = tree_cons (NULL_TREE, || DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)))
in_charge_arg_for_name (complete_ctor_identifier), /* We should never try to call the abstract or base constructor
args); from here. */
abort ();
args = tree_cons (NULL_TREE, t, args); args = tree_cons (NULL_TREE, t, args);
} }
for (; ctors; ctors = OVL_NEXT (ctors)) for (; ctors; ctors = OVL_NEXT (ctors))
@ -3735,8 +3731,11 @@ convert_like_real (convs, expr, fn, argnum, inner)
TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn)); TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn));
args = build_tree_list (NULL_TREE, expr); args = build_tree_list (NULL_TREE, expr);
if (DECL_HAS_IN_CHARGE_PARM_P (convfn)) if (DECL_HAS_IN_CHARGE_PARM_P (convfn)
args = tree_cons (NULL_TREE, integer_one_node, args); || DECL_HAS_VTT_PARM_P (convfn))
/* We should never try to call the abstract or base constructor
from here. */
abort ();
args = tree_cons (NULL_TREE, t, args); args = tree_cons (NULL_TREE, t, args);
} }
else else
@ -4065,6 +4064,9 @@ build_over_call (cand, args, flags)
arg = TREE_CHAIN (arg); arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm); parm = TREE_CHAIN (parm);
if (DECL_HAS_IN_CHARGE_PARM_P (fn)) if (DECL_HAS_IN_CHARGE_PARM_P (fn))
/* We should never try to call the abstract constructor. */
abort ();
if (DECL_HAS_VTT_PARM_P (fn))
{ {
converted_args = tree_cons converted_args = tree_cons
(NULL_TREE, TREE_VALUE (arg), converted_args); (NULL_TREE, TREE_VALUE (arg), converted_args);
@ -4169,9 +4171,7 @@ build_over_call (cand, args, flags)
&& DECL_COPY_CONSTRUCTOR_P (fn)) && DECL_COPY_CONSTRUCTOR_P (fn))
{ {
tree targ; tree targ;
arg = TREE_CHAIN (converted_args); arg = skip_artificial_parms_for (fn, converted_args);
if (DECL_HAS_IN_CHARGE_PARM_P (fn))
arg = TREE_CHAIN (arg);
arg = TREE_VALUE (arg); arg = TREE_VALUE (arg);
/* Pull out the real argument, disregarding const-correctness. */ /* Pull out the real argument, disregarding const-correctness. */
@ -4439,7 +4439,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
vtt = build (COND_EXPR, TREE_TYPE (vtt), vtt = build (COND_EXPR, TREE_TYPE (vtt),
build (EQ_EXPR, boolean_type_node, build (EQ_EXPR, boolean_type_node,
current_in_charge_parm, integer_zero_node), current_in_charge_parm, integer_zero_node),
DECL_VTT_PARM (current_function_decl), current_vtt_parm,
vtt); vtt);
if (TREE_VIA_VIRTUAL (basebinfo)) if (TREE_VIA_VIRTUAL (basebinfo))
basebinfo = binfo_for_vbase (basetype, current_class_type); basebinfo = binfo_for_vbase (basetype, current_class_type);

View File

@ -119,7 +119,6 @@ static void delete_duplicate_fields PARAMS ((tree));
static void finish_struct_bits PARAMS ((tree)); static void finish_struct_bits PARAMS ((tree));
static int alter_access PARAMS ((tree, tree, tree)); static int alter_access PARAMS ((tree, tree, tree));
static void handle_using_decl PARAMS ((tree, tree)); static void handle_using_decl PARAMS ((tree, tree));
static int same_signature_p PARAMS ((tree, tree));
static int strictly_overrides PARAMS ((tree, tree)); static int strictly_overrides PARAMS ((tree, tree));
static void mark_overriders PARAMS ((tree, tree)); static void mark_overriders PARAMS ((tree, tree));
static void check_for_override PARAMS ((tree, tree)); static void check_for_override PARAMS ((tree, tree));
@ -2460,7 +2459,7 @@ layout_vtable_decl (binfo, n)
/* True iff FNDECL and BASE_FNDECL (both non-static member functions) /* True iff FNDECL and BASE_FNDECL (both non-static member functions)
have the same signature. */ have the same signature. */
static int int
same_signature_p (fndecl, base_fndecl) same_signature_p (fndecl, base_fndecl)
tree fndecl, base_fndecl; tree fndecl, base_fndecl;
{ {
@ -4188,8 +4187,6 @@ build_clone (fn, name)
DECL_PENDING_INLINE_P (clone) = 0; DECL_PENDING_INLINE_P (clone) = 0;
/* And it hasn't yet been deferred. */ /* And it hasn't yet been deferred. */
DECL_DEFERRED_FN (clone) = 0; DECL_DEFERRED_FN (clone) = 0;
/* There's no magic VTT parameter in the clone. */
DECL_VTT_PARM (clone) = NULL_TREE;
/* The base-class destructor is not virtual. */ /* The base-class destructor is not virtual. */
if (name == base_dtor_identifier) if (name == base_dtor_identifier)
@ -4214,10 +4211,12 @@ build_clone (fn, name)
parmtypes = TREE_CHAIN (parmtypes); parmtypes = TREE_CHAIN (parmtypes);
/* Skip the in-charge parameter. */ /* Skip the in-charge parameter. */
parmtypes = TREE_CHAIN (parmtypes); parmtypes = TREE_CHAIN (parmtypes);
/* And the VTT parm, in a complete [cd]tor. */
if (DECL_HAS_VTT_PARM_P (fn)
&& ! DECL_NEEDS_VTT_PARM_P (clone))
parmtypes = TREE_CHAIN (parmtypes);
/* If this is subobject constructor or destructor, add the vtt /* If this is subobject constructor or destructor, add the vtt
parameter. */ parameter. */
if (DECL_NEEDS_VTT_PARM_P (clone))
parmtypes = hash_tree_chain (vtt_parm_type, parmtypes);
TREE_TYPE (clone) TREE_TYPE (clone)
= build_cplus_method_type (basetype, = build_cplus_method_type (basetype,
TREE_TYPE (TREE_TYPE (clone)), TREE_TYPE (TREE_TYPE (clone)),
@ -4227,8 +4226,8 @@ build_clone (fn, name)
exceptions); exceptions);
} }
/* Copy the function parameters. But, DECL_ARGUMENTS aren't /* Copy the function parameters. But, DECL_ARGUMENTS on a TEMPLATE_DECL
function parameters; instead, those are the template parameters. */ aren't function parameters; those are the template parameters. */
if (TREE_CODE (clone) != TEMPLATE_DECL) if (TREE_CODE (clone) != TEMPLATE_DECL)
{ {
DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone)); DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone));
@ -4239,16 +4238,17 @@ build_clone (fn, name)
= TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone))); = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
DECL_HAS_IN_CHARGE_PARM_P (clone) = 0; DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
} }
/* And the VTT parm, in a complete [cd]tor. */
/* Add the VTT parameter. */ if (DECL_HAS_VTT_PARM_P (fn))
if (DECL_NEEDS_VTT_PARM_P (clone))
{ {
tree parm; if (DECL_NEEDS_VTT_PARM_P (clone))
DECL_HAS_VTT_PARM_P (clone) = 1;
parm = build_artificial_parm (vtt_parm_identifier, else
vtt_parm_type); {
TREE_CHAIN (parm) = TREE_CHAIN (DECL_ARGUMENTS (clone)); TREE_CHAIN (DECL_ARGUMENTS (clone))
TREE_CHAIN (DECL_ARGUMENTS (clone)) = parm; = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
DECL_HAS_VTT_PARM_P (clone) = 0;
}
} }
for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms)) for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))

View File

@ -881,6 +881,7 @@ struct cp_language_function
tree x_current_class_ref; tree x_current_class_ref;
tree x_eh_spec_try_block; tree x_eh_spec_try_block;
tree x_in_charge_parm; tree x_in_charge_parm;
tree x_vtt_parm;
tree *x_vcalls_possible_p; tree *x_vcalls_possible_p;
@ -927,10 +928,15 @@ struct cp_language_function
#define current_eh_spec_try_block cp_function_chain->x_eh_spec_try_block #define current_eh_spec_try_block cp_function_chain->x_eh_spec_try_block
/* The `__in_chrg' parameter for the current function. Only used for /* The `__in_chrg' parameter for the current function. Only used for
destructors. */ constructors and destructors. */
#define current_in_charge_parm cp_function_chain->x_in_charge_parm #define current_in_charge_parm cp_function_chain->x_in_charge_parm
/* The `__vtt_parm' parameter for the current function. Only used for
constructors and destructors. */
#define current_vtt_parm cp_function_chain->x_vtt_parm
/* In destructors, this is a pointer to a condition in an /* In destructors, this is a pointer to a condition in an
if-statement. If the pointed-to value is boolean_true_node, then if-statement. If the pointed-to value is boolean_true_node, then
there may be virtual function calls in this destructor. */ there may be virtual function calls in this destructor. */
@ -1249,7 +1255,18 @@ enum languages { lang_c, lang_cplusplus, lang_java };
? (ENTRY) \ ? (ENTRY) \
: DECL_INITIAL (TREE_OPERAND ((ENTRY), 0))) : DECL_INITIAL (TREE_OPERAND ((ENTRY), 0)))
#define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE)))) #define FUNCTION_ARG_CHAIN(NODE) \
(TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE))))
/* Given a FUNCTION_DECL, returns the first TREE_LIST out of TYPE_ARG_TYPES
which refers to a user-written parameter. */
#define FUNCTION_FIRST_USER_PARMTYPE(NODE) \
(skip_artificial_parms_for (NODE, TYPE_ARG_TYPES (TREE_TYPE (NODE))))
/* Similarly, but for DECL_ARGUMENTS. */
#define FUNCTION_FIRST_USER_PARM(NODE) \
(skip_artificial_parms_for (NODE, DECL_ARGUMENTS (NODE)))
#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) \ #define PROMOTES_TO_AGGR_TYPE(NODE,CODE) \
(((CODE) == TREE_CODE (NODE) \ (((CODE) == TREE_CODE (NODE) \
&& IS_AGGR_TYPE (TREE_TYPE (NODE))) \ && IS_AGGR_TYPE (TREE_TYPE (NODE))) \
@ -1825,7 +1842,7 @@ struct lang_decl_flags
unsigned assignment_operator_p : 1; unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1; unsigned anticipated_p : 1;
unsigned generate_with_vtable_p : 1; unsigned generate_with_vtable_p : 1;
unsigned dummy : 1; unsigned has_vtt_parm_p : 1;
union { union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
@ -1876,9 +1893,6 @@ struct lang_decl
/* In an overloaded operator, this is the value of /* In an overloaded operator, this is the value of
DECL_OVERLOADED_OPERATOR_P. */ DECL_OVERLOADED_OPERATOR_P. */
enum tree_code operator_code; enum tree_code operator_code;
/* In a maybe-in-charge constructor or destructor, this is
DECL_VTT_PARM. */
tree vtt_parm;
} u2; } u2;
}; };
@ -1978,10 +1992,9 @@ struct lang_decl
#define DECL_CLONED_FUNCTION(NODE) \ #define DECL_CLONED_FUNCTION(NODE) \
(DECL_LANG_SPECIFIC (NODE)->cloned_function) (DECL_LANG_SPECIFIC (NODE)->cloned_function)
/* In a maybe-in-charge constructor or destructor, this is the VTT /* Non-zero if the VTT parm has been added to NODE. */
parameter. It's not actually on the DECL_ARGUMENTS list. */ #define DECL_HAS_VTT_PARM_P(NODE) \
#define DECL_VTT_PARM(NODE) \ (DECL_LANG_SPECIFIC (NODE)->decl_flags.has_vtt_parm_p)
(DECL_LANG_SPECIFIC (NODE)->u2.vtt_parm)
/* Non-zero if NODE is a FUNCTION_DECL for which a VTT parameter is /* Non-zero if NODE is a FUNCTION_DECL for which a VTT parameter is
required. */ required. */
@ -3723,6 +3736,7 @@ extern void pop_lang_context PARAMS ((void));
extern tree instantiate_type PARAMS ((tree, tree, enum instantiate_type_flags)); extern tree instantiate_type PARAMS ((tree, tree, enum instantiate_type_flags));
extern void print_class_statistics PARAMS ((void)); extern void print_class_statistics PARAMS ((void));
extern void build_self_reference PARAMS ((void)); extern void build_self_reference PARAMS ((void));
extern int same_signature_p PARAMS ((tree, tree));
extern void warn_hidden PARAMS ((tree)); extern void warn_hidden PARAMS ((tree));
extern tree get_enclosing_class PARAMS ((tree)); extern tree get_enclosing_class PARAMS ((tree));
int is_base_of_enclosing_class PARAMS ((tree, tree)); int is_base_of_enclosing_class PARAMS ((tree, tree));
@ -4085,6 +4099,7 @@ extern tree make_thunk PARAMS ((tree, tree, tree, int));
extern void use_thunk PARAMS ((tree, int)); extern void use_thunk PARAMS ((tree, int));
extern void synthesize_method PARAMS ((tree)); extern void synthesize_method PARAMS ((tree));
extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int)); extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int));
extern tree skip_artificial_parms_for PARAMS ((tree, tree));
/* In optimize.c */ /* In optimize.c */
extern void optimize_function PARAMS ((tree)); extern void optimize_function PARAMS ((tree));

View File

@ -3399,7 +3399,9 @@ duplicate_decls (newdecl, olddecl)
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl); DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl); DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl); DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
DECL_LANG_SPECIFIC (newdecl)->u2 = DECL_LANG_SPECIFIC (olddecl)->u2; if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
SET_OVERLOADED_OPERATOR_CODE
(newdecl, DECL_OVERLOADED_OPERATOR_P (olddecl));
new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE; new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
/* Optionally warn about more than one declaration for the same /* Optionally warn about more than one declaration for the same
@ -11300,15 +11302,8 @@ friend declaration requires class-key, i.e. `friend %#T'",
/* The constructor can be called with exactly one /* The constructor can be called with exactly one
parameter if there is at least one parameter, and parameter if there is at least one parameter, and
any subsequent parameters have default arguments. any subsequent parameters have default arguments.
We don't look at the first parameter, which is Ignore any compiler-added parms. */
really just the `this' parameter for the new tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
object. */
tree arg_types =
TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)));
/* Skip the `in_chrg' argument too, if present. */
if (DECL_HAS_IN_CHARGE_PARM_P (decl))
arg_types = TREE_CHAIN (arg_types);
if (arg_types == void_list_node if (arg_types == void_list_node
|| (arg_types || (arg_types
@ -11923,9 +11918,7 @@ copy_args_p (d)
if (!DECL_FUNCTION_MEMBER_P (d)) if (!DECL_FUNCTION_MEMBER_P (d))
return 0; return 0;
t = FUNCTION_ARG_CHAIN (d); t = FUNCTION_FIRST_USER_PARMTYPE (d);
if (DECL_CONSTRUCTOR_P (d) && DECL_HAS_IN_CHARGE_PARM_P (d))
t = TREE_CHAIN (t);
if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t))) && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t)))
== DECL_CONTEXT (d)) == DECL_CONTEXT (d))
@ -11948,22 +11941,9 @@ int
grok_ctor_properties (ctype, decl) grok_ctor_properties (ctype, decl)
tree ctype, decl; tree ctype, decl;
{ {
tree parmtypes = FUNCTION_ARG_CHAIN (decl); tree parmtypes = FUNCTION_FIRST_USER_PARMTYPE (decl);
tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
/* When a type has virtual baseclasses, a magical first int argument is
added to any ctor so we can tell if the class has been initialized
yet. This could screw things up in this function, so we deliberately
ignore the leading int if we're in that situation. */
if (DECL_HAS_IN_CHARGE_PARM_P (decl))
{
my_friendly_assert (parmtypes
&& TREE_VALUE (parmtypes) == integer_type_node,
980529);
parmtypes = TREE_CHAIN (parmtypes);
parmtype = TREE_VALUE (parmtypes);
}
/* [class.copy] /* [class.copy]
A non-template constructor for class X is a copy constructor if A non-template constructor for class X is a copy constructor if
@ -13473,8 +13453,18 @@ start_function (declspecs, declarator, attrs, flags)
/* Constructors and destructors need to know whether they're "in /* Constructors and destructors need to know whether they're "in
charge" of initializing virtual base classes. */ charge" of initializing virtual base classes. */
t = TREE_CHAIN (t);
if (DECL_HAS_IN_CHARGE_PARM_P (decl1)) if (DECL_HAS_IN_CHARGE_PARM_P (decl1))
current_in_charge_parm = TREE_CHAIN (t); {
current_in_charge_parm = t;
t = TREE_CHAIN (t);
}
if (DECL_HAS_VTT_PARM_P (decl1))
{
if (DECL_NAME (t) != vtt_parm_identifier)
abort ();
current_vtt_parm = t;
}
} }
if (DECL_INTERFACE_KNOWN (decl1)) if (DECL_INTERFACE_KNOWN (decl1))
@ -14425,8 +14415,6 @@ lang_mark_tree (t)
ggc_mark_tree (ld->befriending_classes); ggc_mark_tree (ld->befriending_classes);
ggc_mark_tree (ld->context); ggc_mark_tree (ld->context);
ggc_mark_tree (ld->cloned_function); ggc_mark_tree (ld->cloned_function);
if (!DECL_OVERLOADED_OPERATOR_P (t))
ggc_mark_tree (ld->u2.vtt_parm);
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

View File

@ -932,7 +932,10 @@ build_artificial_parm (name, type)
This function adds the "in-charge" flag to member function FN if This function adds the "in-charge" flag to member function FN if
appropriate. It is called from grokclassfn and tsubst. appropriate. It is called from grokclassfn and tsubst.
FN must be either a constructor or destructor. */ FN must be either a constructor or destructor.
The in-charge flag follows the 'this' parameter, and is followed by the
VTT parm (if any), then the user-written parms. */
void void
maybe_retrofit_in_chrg (fn) maybe_retrofit_in_chrg (fn)
@ -955,17 +958,38 @@ maybe_retrofit_in_chrg (fn)
&& !TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) && !TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
return; return;
/* First add it to DECL_ARGUMENTS... */
parm = build_artificial_parm (in_charge_identifier, integer_type_node);
TREE_READONLY (parm) = 1;
parms = DECL_ARGUMENTS (fn);
TREE_CHAIN (parm) = TREE_CHAIN (parms);
TREE_CHAIN (parms) = parm;
/* ...and then to TYPE_ARG_TYPES. */
arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
basetype = TREE_TYPE (TREE_VALUE (arg_types)); basetype = TREE_TYPE (TREE_VALUE (arg_types));
arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types)); arg_types = TREE_CHAIN (arg_types);
parms = TREE_CHAIN (DECL_ARGUMENTS (fn));
/* If this is a subobject constructor or destructor, our caller will
pass us a pointer to our VTT. */
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
{
parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
/* First add it to DECL_ARGUMENTS between 'this' and the real args... */
TREE_CHAIN (parm) = parms;
parms = parm;
/* ...and then to TYPE_ARG_TYPES. */
arg_types = hash_tree_chain (vtt_parm_type, arg_types);
DECL_HAS_VTT_PARM_P (fn) = 1;
}
/* Then add the in-charge parm (before the VTT parm). */
parm = build_artificial_parm (in_charge_identifier, integer_type_node);
TREE_CHAIN (parm) = parms;
parms = parm;
arg_types = hash_tree_chain (integer_type_node, arg_types);
/* Insert our new parameter(s) into the list. */
TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
/* And rebuild the function type. */
fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
arg_types); arg_types);
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
@ -975,15 +999,6 @@ maybe_retrofit_in_chrg (fn)
/* Now we've got the in-charge parameter. */ /* Now we've got the in-charge parameter. */
DECL_HAS_IN_CHARGE_PARM_P (fn) = 1; DECL_HAS_IN_CHARGE_PARM_P (fn) = 1;
/* If this is a subobject constructor or destructor, our caller will
pass us a pointer to our VTT. */
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
{
DECL_VTT_PARM (fn) = build_artificial_parm (vtt_parm_identifier,
vtt_parm_type);
DECL_CONTEXT (DECL_VTT_PARM (fn)) = fn;
}
} }
/* Classes overload their constituent function names automatically. /* Classes overload their constituent function names automatically.

View File

@ -1203,7 +1203,7 @@ dump_function_decl (t, flags)
} }
fntype = TREE_TYPE (t); fntype = TREE_TYPE (t);
parmtypes = TYPE_ARG_TYPES (fntype); parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
if (DECL_CLASS_SCOPE_P (t)) if (DECL_CLASS_SCOPE_P (t))
cname = DECL_CONTEXT (t); cname = DECL_CONTEXT (t);
@ -1241,14 +1241,6 @@ dump_function_decl (t, flags)
if (flags & TFF_DECL_SPECIFIERS) if (flags & TFF_DECL_SPECIFIERS)
{ {
if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
/* Skip "this" parameter. */
parmtypes = TREE_CHAIN (parmtypes);
/* Skip past the "in_charge" parameter. */
if (DECL_HAS_IN_CHARGE_PARM_P (t))
parmtypes = TREE_CHAIN (parmtypes);
dump_parameters (parmtypes, flags); dump_parameters (parmtypes, flags);
if (show_return) if (show_return)

View File

@ -860,7 +860,7 @@ expand_virtual_init (binfo, decl)
tree vtt_parm; tree vtt_parm;
/* Compute the value to use, when there's a VTT. */ /* Compute the value to use, when there's a VTT. */
vtt_parm = DECL_VTT_PARM (current_function_decl); vtt_parm = current_vtt_parm;
vtbl2 = build (PLUS_EXPR, vtbl2 = build (PLUS_EXPR,
TREE_TYPE (vtt_parm), TREE_TYPE (vtt_parm),
vtt_parm, vtt_parm,

View File

@ -364,7 +364,6 @@ make_thunk (function, delta, vcall_index, generate_with_vtable_p)
DECL_CONSTRUCTOR_P (thunk) = 0; DECL_CONSTRUCTOR_P (thunk) = 0;
DECL_EXTERNAL (thunk) = 1; DECL_EXTERNAL (thunk) = 1;
DECL_ARTIFICIAL (thunk) = 1; DECL_ARTIFICIAL (thunk) = 1;
DECL_VTT_PARM (thunk) = NULL_TREE;
/* Even if this thunk is a member of a local class, we don't /* Even if this thunk is a member of a local class, we don't
need a static chain. */ need a static chain. */
DECL_NO_STATIC_CHAIN (thunk) = 1; DECL_NO_STATIC_CHAIN (thunk) = 1;
@ -536,11 +535,9 @@ static void
do_build_copy_constructor (fndecl) do_build_copy_constructor (fndecl)
tree fndecl; tree fndecl;
{ {
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
tree t; tree t;
if (DECL_HAS_IN_CHARGE_PARM_P (fndecl))
parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm); parm = convert_from_reference (parm);
if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
@ -760,9 +757,7 @@ synthesize_method (fndecl)
setup_vtbl_ptr (NULL_TREE, NULL_TREE); setup_vtbl_ptr (NULL_TREE, NULL_TREE);
else else
{ {
tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
if (DECL_HAS_IN_CHARGE_PARM_P (fndecl))
arg_chain = TREE_CHAIN (arg_chain);
if (arg_chain != void_list_node) if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl); do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
@ -1041,3 +1036,22 @@ implicitly_declare_fn (kind, type, const_p)
return fn; return fn;
} }
/* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST
as there are artificial parms in FN. */
tree
skip_artificial_parms_for (fn, list)
tree fn, list;
{
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
list = TREE_CHAIN (list);
else
return list;
if (DECL_HAS_IN_CHARGE_PARM_P (fn))
list = TREE_CHAIN (list);
if (DECL_HAS_VTT_PARM_P (fn))
list = TREE_CHAIN (list);
return list;
}

View File

@ -981,22 +981,25 @@ maybe_clone_body (fn)
splay_tree_insert (id.decl_map, splay_tree_insert (id.decl_map,
(splay_tree_key) parm, (splay_tree_key) parm,
(splay_tree_value) in_charge); (splay_tree_value) in_charge);
}
else if (DECL_ARTIFICIAL (parm)
&& DECL_NAME (parm) == vtt_parm_identifier)
{
/* For a subobject constructor or destructor, the next /* For a subobject constructor or destructor, the next
argument is the VTT parameter. Remap the VTT_PARM argument is the VTT parameter. Remap the VTT_PARM
from the CLONE to this parameter. */ from the CLONE to this parameter. */
if (DECL_NEEDS_VTT_PARM_P (clone)) if (DECL_HAS_VTT_PARM_P (clone))
{ {
splay_tree_insert (id.decl_map, splay_tree_insert (id.decl_map,
(splay_tree_key) DECL_VTT_PARM (fn), (splay_tree_key) parm,
(splay_tree_value) clone_parm); (splay_tree_value) clone_parm);
clone_parm = TREE_CHAIN (clone_parm); clone_parm = TREE_CHAIN (clone_parm);
} }
/* Otherwise, map the VTT parameter to `NULL'. */ /* Otherwise, map the VTT parameter to `NULL'. */
else if (DECL_VTT_PARM (fn)) else
{ {
splay_tree_insert (id.decl_map, splay_tree_insert (id.decl_map,
(splay_tree_key) DECL_VTT_PARM (fn), (splay_tree_key) parm,
(splay_tree_value) null_pointer_node); (splay_tree_value) null_pointer_node);
} }
} }

View File

@ -1208,6 +1208,7 @@ copy_default_args_to_explicit_spec (decl)
tree t; tree t;
tree object_type = NULL_TREE; tree object_type = NULL_TREE;
tree in_charge = NULL_TREE; tree in_charge = NULL_TREE;
tree vtt = NULL_TREE;
/* See if there's anything we need to do. */ /* See if there's anything we need to do. */
tmpl = DECL_TI_TEMPLATE (decl); tmpl = DECL_TI_TEMPLATE (decl);
@ -1236,6 +1237,11 @@ copy_default_args_to_explicit_spec (decl)
in_charge = spec_types; in_charge = spec_types;
spec_types = TREE_CHAIN (spec_types); spec_types = TREE_CHAIN (spec_types);
} }
if (DECL_HAS_VTT_PARM_P (decl))
{
vtt = spec_types;
spec_types = TREE_CHAIN (spec_types);
}
} }
/* Compute the merged default arguments. */ /* Compute the merged default arguments. */
@ -1245,6 +1251,11 @@ copy_default_args_to_explicit_spec (decl)
/* Compute the new FUNCTION_TYPE. */ /* Compute the new FUNCTION_TYPE. */
if (object_type) if (object_type)
{ {
if (vtt)
new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt),
TREE_VALUE (vtt),
new_spec_types);
if (in_charge) if (in_charge)
/* Put the in-charge parameter back. */ /* Put the in-charge parameter back. */
new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge), new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge),

View File

@ -2046,22 +2046,13 @@ look_for_overrides_r (type, fndecl)
return 1; return 1;
} }
} }
else else if (same_signature_p (fndecl, fn))
{ {
if (/* The first parameter is the `this' parameter, /* It's definitely virtual, even if not explicitly set. */
which has POINTER_TYPE, and we can therefore DECL_VIRTUAL_P (fndecl) = 1;
safely use TYPE_QUALS, rather than check_final_overrider (fndecl, fn);
CP_TYPE_QUALS. */
(TYPE_QUALS (TREE_TYPE (TREE_VALUE (btypes))) return 1;
== TYPE_QUALS (thistype))
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
{
/* It's definitely virtual, even if not explicitly set. */
DECL_VIRTUAL_P (fndecl) = 1;
check_final_overrider (fndecl, fn);
return 1;
}
} }
} }
} }