cp-tree.h (cp_tree_index): Add CPTI_COMPLETE_CTOR_IDENTIFIER.
* cp-tree.h (cp_tree_index): Add CPTI_COMPLETE_CTOR_IDENTIFIER. (complete_ctor_identifier): New macro. (special_function_kind): Add sfk_copy_constructor and sfk_assignment_operator. (LOOKUP_HAS_IN_CHARGE): Remove. (cons_up_default_function): Rename to ... (implicitly_declare_fn): ... this. * call.c (build_new_method_call): Add in-charge parameters for constructors here. * class.c (add_implicitly_declared_members): Change parameter name from cant_have_assignment to cant_have_const_assignment. Replace calls to cons_up_default_function to implicitly_declare_fn. * cvt.c (ocp_convert): Use complete_ctor_identifier. * decl.c (initialize_predefined_identifiers): Initialize it. (start_function): Use DECL_CONSTRUCTOR_FOR_VBASE_P instead of complex expression. * init.c (expand_default_init): Don't calculate the in-charge parameter here. (build_new_1): Likewise. * lex.c (cons_up_default_function): Move to method.c. * method.c (synthesize_method): Use DECL_DESTRUCTOR_P. (implicitly_declare_fn): New function. * typeck.c (build_static_cast): Use complete_ctor_identifier. (build_modify_expr): Likewise. * typeck2.c (build_functional_cast): Likewise. From-SVN: r33038
This commit is contained in:
parent
568fe067bc
commit
9eb71d8c3b
|
@ -1,5 +1,31 @@
|
|||
2000-04-08 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (cp_tree_index): Add CPTI_COMPLETE_CTOR_IDENTIFIER.
|
||||
(complete_ctor_identifier): New macro.
|
||||
(special_function_kind): Add sfk_copy_constructor and
|
||||
sfk_assignment_operator.
|
||||
(LOOKUP_HAS_IN_CHARGE): Remove.
|
||||
(cons_up_default_function): Rename to ...
|
||||
(implicitly_declare_fn): ... this.
|
||||
* call.c (build_new_method_call): Add in-charge parameters for
|
||||
constructors here.
|
||||
* class.c (add_implicitly_declared_members): Change parameter name
|
||||
from cant_have_assignment to cant_have_const_assignment.
|
||||
Replace calls to cons_up_default_function to implicitly_declare_fn.
|
||||
* cvt.c (ocp_convert): Use complete_ctor_identifier.
|
||||
* decl.c (initialize_predefined_identifiers): Initialize it.
|
||||
(start_function): Use DECL_CONSTRUCTOR_FOR_VBASE_P instead of
|
||||
complex expression.
|
||||
* init.c (expand_default_init): Don't calculate the in-charge
|
||||
parameter here.
|
||||
(build_new_1): Likewise.
|
||||
* lex.c (cons_up_default_function): Move to method.c.
|
||||
* method.c (synthesize_method): Use DECL_DESTRUCTOR_P.
|
||||
(implicitly_declare_fn): New function.
|
||||
* typeck.c (build_static_cast): Use complete_ctor_identifier.
|
||||
(build_modify_expr): Likewise.
|
||||
* typeck2.c (build_functional_cast): Likewise.
|
||||
|
||||
Under the new ABI, constructors don't return `this'.
|
||||
* cp-tree.h (warn_reorder): Declare.
|
||||
(special_function_kind): New enum.
|
||||
|
|
|
@ -4196,11 +4196,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
|||
template_only = 1;
|
||||
}
|
||||
|
||||
/* If there is an extra argument for controlling virtual bases,
|
||||
remove it for error reporting. */
|
||||
if (flags & LOOKUP_HAS_IN_CHARGE)
|
||||
user_args = TREE_CHAIN (args);
|
||||
|
||||
user_args = args;
|
||||
args = resolve_args (args);
|
||||
|
||||
if (args == error_mark_node)
|
||||
|
@ -4248,8 +4244,33 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
|||
TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
|
||||
}
|
||||
|
||||
pretty_name
|
||||
= (name == ctor_identifier ? constructor_name (basetype) : name);
|
||||
/* Callers should explicitly indicate whether they want to construct
|
||||
the complete object or just the part without virtual bases. */
|
||||
my_friendly_assert (name != ctor_identifier, 20000408);
|
||||
|
||||
if (name == complete_ctor_identifier
|
||||
|| 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))
|
||||
{
|
||||
tree in_charge;
|
||||
|
||||
if (name == complete_ctor_identifier)
|
||||
in_charge = integer_one_node;
|
||||
else
|
||||
in_charge = integer_zero_node;
|
||||
|
||||
args = tree_cons (NULL_TREE, in_charge, args);
|
||||
}
|
||||
|
||||
/* We want to call the normal constructor function under the old
|
||||
ABI. */
|
||||
name = ctor_identifier;
|
||||
}
|
||||
else
|
||||
pretty_name = name;
|
||||
|
||||
fns = lookup_fnfields (basetype_path, name, 1);
|
||||
|
||||
|
@ -4259,12 +4280,6 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
|||
{
|
||||
tree base = BINFO_TYPE (TREE_PURPOSE (fns));
|
||||
tree fn = TREE_VALUE (fns);
|
||||
if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype)
|
||||
&& ! (flags & LOOKUP_HAS_IN_CHARGE))
|
||||
{
|
||||
flags |= LOOKUP_HAS_IN_CHARGE;
|
||||
args = tree_cons (NULL_TREE, integer_one_node, args);
|
||||
}
|
||||
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
|
||||
for (; fn; fn = OVL_NEXT (fn))
|
||||
{
|
||||
|
@ -4272,8 +4287,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
|||
tree this_arglist;
|
||||
|
||||
/* We can end up here for copy-init of same or base class. */
|
||||
if (name == ctor_identifier
|
||||
&& (flags & LOOKUP_ONLYCONVERTING)
|
||||
if ((flags & LOOKUP_ONLYCONVERTING)
|
||||
&& DECL_NONCONVERTING_P (t))
|
||||
continue;
|
||||
if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
|
||||
|
|
|
@ -2927,31 +2927,30 @@ extern int interface_only, interface_unknown;
|
|||
/* Create default constructors, assignment operators, and so forth for
|
||||
the type indicated by T, if they are needed.
|
||||
CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
|
||||
CANT_HAVE_ASSIGNMENT are nonzero if, for whatever reason, the class
|
||||
cannot have a default constructor, copy constructor taking a const
|
||||
reference argument, or an assignment operator, respectively. If a
|
||||
virtual destructor is created, its DECL is returned; otherwise the
|
||||
return value is NULL_TREE. */
|
||||
CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, the
|
||||
class cannot have a default constructor, copy constructor taking a
|
||||
const reference argument, or an assignment operator taking a const
|
||||
reference, respectively. If a virtual destructor is created, its
|
||||
DECL is returned; otherwise the return value is NULL_TREE. */
|
||||
|
||||
static tree
|
||||
add_implicitly_declared_members (t, cant_have_default_ctor,
|
||||
cant_have_const_cctor,
|
||||
cant_have_assignment)
|
||||
cant_have_const_assignment)
|
||||
tree t;
|
||||
int cant_have_default_ctor;
|
||||
int cant_have_const_cctor;
|
||||
int cant_have_assignment;
|
||||
int cant_have_const_assignment;
|
||||
{
|
||||
tree default_fn;
|
||||
tree implicit_fns = NULL_TREE;
|
||||
tree name = TYPE_IDENTIFIER (t);
|
||||
tree virtual_dtor = NULL_TREE;
|
||||
tree *f;
|
||||
|
||||
/* Destructor. */
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
|
||||
{
|
||||
default_fn = cons_up_default_function (t, name, 0);
|
||||
default_fn = implicitly_declare_fn (sfk_destructor, t, /*const_p=*/0);
|
||||
check_for_override (default_fn, t);
|
||||
|
||||
/* If we couldn't make it work, then pretend we didn't need it. */
|
||||
|
@ -2973,7 +2972,7 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
|
|||
/* Default constructor. */
|
||||
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
|
||||
{
|
||||
default_fn = cons_up_default_function (t, name, 2);
|
||||
default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0);
|
||||
TREE_CHAIN (default_fn) = implicit_fns;
|
||||
implicit_fns = default_fn;
|
||||
}
|
||||
|
@ -2983,8 +2982,9 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
|
|||
{
|
||||
/* ARM 12.18: You get either X(X&) or X(const X&), but
|
||||
not both. --Chip */
|
||||
default_fn = cons_up_default_function (t, name,
|
||||
3 + cant_have_const_cctor);
|
||||
default_fn
|
||||
= implicitly_declare_fn (sfk_copy_constructor, t,
|
||||
/*const_p=*/!cant_have_const_cctor);
|
||||
TREE_CHAIN (default_fn) = implicit_fns;
|
||||
implicit_fns = default_fn;
|
||||
}
|
||||
|
@ -2992,8 +2992,9 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
|
|||
/* Assignment operator. */
|
||||
if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t))
|
||||
{
|
||||
default_fn = cons_up_default_function (t, name,
|
||||
5 + cant_have_assignment);
|
||||
default_fn
|
||||
= implicitly_declare_fn (sfk_assignment_operator, t,
|
||||
/*const_p=*/!cant_have_const_assignment);
|
||||
TREE_CHAIN (default_fn) = implicit_fns;
|
||||
implicit_fns = default_fn;
|
||||
}
|
||||
|
|
|
@ -560,6 +560,7 @@ enum cp_tree_index
|
|||
CPTI_ACCESS_PRIVATE_VIRTUAL,
|
||||
|
||||
CPTI_CTOR_IDENTIFIER,
|
||||
CPTI_COMPLETE_CTOR_IDENTIFIER,
|
||||
CPTI_BASE_CTOR_IDENTIFIER,
|
||||
CPTI_DTOR_IDENTIFIER,
|
||||
CPTI_BASE_DTOR_IDENTIFIER,
|
||||
|
@ -655,8 +656,11 @@ extern tree cp_global_trees[CPTI_MAX];
|
|||
/* We cache these tree nodes so as to call get_identifier less
|
||||
frequently. */
|
||||
|
||||
/* The name of a constructor that constructors virtual base classes. */
|
||||
/* The name of a constructor that takes an in-charge parameter to
|
||||
decide whether or not to call 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. */
|
||||
|
@ -3105,6 +3109,8 @@ typedef enum access_kind {
|
|||
typedef enum special_function_kind {
|
||||
sfk_none, /* Not a special function. */
|
||||
sfk_constructor, /* A constructor. */
|
||||
sfk_copy_constructor, /* A copy constructor. */
|
||||
sfk_assignment_operator, /* An assignment operator. */
|
||||
sfk_destructor, /* A destructor. */
|
||||
sfk_conversion /* A conversion operator. */
|
||||
} special_function_kind;
|
||||
|
@ -3479,8 +3485,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
|||
LOOKUP_NONVIRTUAL means make a direct call to the member function found
|
||||
LOOKUP_GLOBAL means search through the space of overloaded functions,
|
||||
as well as the space of member functions.
|
||||
LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already
|
||||
in the parameter list.
|
||||
LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried.
|
||||
DIRECT_BIND means that if a temporary is created, it should be created so
|
||||
that it lives as long as the current variable bindings; otherwise it
|
||||
|
@ -3505,10 +3509,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
|||
#define LOOKUP_PROTECT (1)
|
||||
#define LOOKUP_COMPLAIN (2)
|
||||
#define LOOKUP_NORMAL (3)
|
||||
/* #define LOOKUP_UNUSED (4) */
|
||||
#define LOOKUP_NONVIRTUAL (8)
|
||||
#define LOOKUP_GLOBAL (16)
|
||||
#define LOOKUP_HAS_IN_CHARGE (32)
|
||||
#define LOOKUP_SPECULATIVELY (64)
|
||||
#define LOOKUP_ONLYCONVERTING (128)
|
||||
#define DIRECT_BIND (256)
|
||||
|
@ -4052,7 +4054,6 @@ extern void restore_pending_input PARAMS ((struct pending_input *));
|
|||
extern void yyungetc PARAMS ((int, int));
|
||||
extern void reinit_parse_for_method PARAMS ((int, tree));
|
||||
extern void reinit_parse_for_block PARAMS ((int, struct obstack *));
|
||||
extern tree cons_up_default_function PARAMS ((tree, tree, int));
|
||||
extern void check_for_missing_semicolon PARAMS ((tree));
|
||||
extern void note_got_semicolon PARAMS ((tree));
|
||||
extern void note_list_got_semicolon PARAMS ((tree));
|
||||
|
@ -4099,6 +4100,7 @@ extern tree make_thunk PARAMS ((tree, int, int));
|
|||
extern void emit_thunk PARAMS ((tree));
|
||||
extern void synthesize_method PARAMS ((tree));
|
||||
extern tree get_id_2 PARAMS ((const char *, tree));
|
||||
extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int));
|
||||
|
||||
/* In optimize.c */
|
||||
extern void optimize_function PARAMS ((tree));
|
||||
|
|
|
@ -806,7 +806,8 @@ ocp_convert (type, expr, convtype, flags)
|
|||
the target with the temp (see [dcl.init]). */
|
||||
ctor = build_user_type_conversion (type, ctor, flags);
|
||||
if (ctor)
|
||||
ctor = build_method_call (NULL_TREE, ctor_identifier,
|
||||
ctor = build_method_call (NULL_TREE,
|
||||
complete_ctor_identifier,
|
||||
build_tree_list (NULL_TREE, ctor),
|
||||
TYPE_BINFO (type), flags);
|
||||
if (ctor)
|
||||
|
|
|
@ -6063,6 +6063,7 @@ initialize_predefined_identifiers ()
|
|||
{ "Java", &lang_name_java },
|
||||
{ CTOR_NAME, &ctor_identifier },
|
||||
{ "__base_ctor", &base_ctor_identifier },
|
||||
{ "__comp_ctor", &complete_ctor_identifier },
|
||||
{ DTOR_NAME, &dtor_identifier },
|
||||
{ "__base_dtor", &base_dtor_identifier },
|
||||
{ "__deleting_dtor", &deleting_dtor_identifier },
|
||||
|
@ -13441,13 +13442,8 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
|
||||
/* Constructors and destructors need to know whether they're "in
|
||||
charge" of initializing virtual base classes. */
|
||||
if (DECL_DESTRUCTOR_P (decl1))
|
||||
current_in_charge_parm = TREE_CHAIN (t);
|
||||
else if (DECL_CONSTRUCTOR_P (decl1)
|
||||
&& TREE_CHAIN (t)
|
||||
&& DECL_ARTIFICIAL (TREE_CHAIN (t))
|
||||
&& (DECL_NAME (TREE_CHAIN (t))
|
||||
== in_charge_identifier))
|
||||
if (DECL_CONSTRUCTOR_FOR_VBASE_P (decl1)
|
||||
|| DECL_DESTRUCTOR_P (decl1))
|
||||
current_in_charge_parm = TREE_CHAIN (t);
|
||||
}
|
||||
|
||||
|
|
|
@ -1116,6 +1116,7 @@ expand_default_init (binfo, true_exp, exp, init, flags)
|
|||
int flags;
|
||||
{
|
||||
tree type = TREE_TYPE (exp);
|
||||
tree ctor_name;
|
||||
|
||||
/* It fails because there may not be a constructor which takes
|
||||
its own type as the first (or only parameter), but which does
|
||||
|
@ -1170,17 +1171,12 @@ expand_default_init (binfo, true_exp, exp, init, flags)
|
|||
else
|
||||
parms = build_tree_list (NULL_TREE, init);
|
||||
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
|
||||
{
|
||||
if (true_exp == exp)
|
||||
parms = tree_cons (NULL_TREE, integer_one_node, parms);
|
||||
else
|
||||
parms = tree_cons (NULL_TREE, integer_zero_node, parms);
|
||||
flags |= LOOKUP_HAS_IN_CHARGE;
|
||||
}
|
||||
if (true_exp == exp)
|
||||
ctor_name = complete_ctor_identifier;
|
||||
else
|
||||
ctor_name = base_ctor_identifier;
|
||||
|
||||
rval = build_method_call (exp, ctor_identifier,
|
||||
parms, binfo, flags);
|
||||
rval = build_method_call (exp, ctor_name, parms, binfo, flags);
|
||||
if (TREE_SIDE_EFFECTS (rval))
|
||||
finish_expr_stmt (rval);
|
||||
}
|
||||
|
@ -2350,19 +2346,14 @@ build_new_1 (exp)
|
|||
that argument. */
|
||||
int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN;
|
||||
|
||||
if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
|
||||
{
|
||||
init = tree_cons (NULL_TREE, integer_one_node, init);
|
||||
flags |= LOOKUP_HAS_IN_CHARGE;
|
||||
}
|
||||
|
||||
rval = save_expr (rval);
|
||||
newrval = rval;
|
||||
|
||||
if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
|
||||
newrval = build_indirect_ref (newrval, NULL_PTR);
|
||||
|
||||
newrval = build_method_call (newrval, ctor_identifier,
|
||||
newrval = build_method_call (newrval,
|
||||
complete_ctor_identifier,
|
||||
init, TYPE_BINFO (true_type), flags);
|
||||
|
||||
if (newrval == NULL_TREE || newrval == error_mark_node)
|
||||
|
|
136
gcc/cp/lex.c
136
gcc/cp/lex.c
|
@ -1978,142 +1978,6 @@ do_pending_defargs ()
|
|||
}
|
||||
}
|
||||
|
||||
/* Build a default function named NAME for type TYPE.
|
||||
KIND says what to build.
|
||||
|
||||
When KIND == 0, build default destructor.
|
||||
When KIND == 1, build virtual destructor.
|
||||
When KIND == 2, build default constructor.
|
||||
When KIND == 3, build default X(const X&) constructor.
|
||||
When KIND == 4, build default X(X&) constructor.
|
||||
When KIND == 5, build default operator = (const X&).
|
||||
When KIND == 6, build default operator = (X&). */
|
||||
|
||||
tree
|
||||
cons_up_default_function (type, full_name, kind)
|
||||
tree type, full_name;
|
||||
int kind;
|
||||
{
|
||||
tree declspecs = NULL_TREE;
|
||||
tree fn, args = NULL_TREE;
|
||||
tree argtype;
|
||||
int retref = 0;
|
||||
tree name = constructor_name (full_name);
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
/* Destructors. */
|
||||
case 0:
|
||||
name = build_parse_node (BIT_NOT_EXPR, name);
|
||||
args = void_list_node;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Default constructor. */
|
||||
args = void_list_node;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
type = build_qualified_type (type, TYPE_QUAL_CONST);
|
||||
/* Fall through... */
|
||||
case 4:
|
||||
/* According to ARM $12.8, the default copy ctor will be declared, but
|
||||
not defined, unless it's needed. */
|
||||
argtype = build_reference_type (type);
|
||||
args = tree_cons (NULL_TREE,
|
||||
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
|
||||
get_identifier ("_ctor_arg")),
|
||||
void_list_node);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 6:
|
||||
retref = 1;
|
||||
declspecs = build_decl_list (NULL_TREE, type);
|
||||
|
||||
if (kind == 5)
|
||||
type = build_qualified_type (type, TYPE_QUAL_CONST);
|
||||
|
||||
name = ansi_opname [(int) MODIFY_EXPR];
|
||||
|
||||
argtype = build_reference_type (type);
|
||||
args = tree_cons (NULL_TREE,
|
||||
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
|
||||
get_identifier ("_ctor_arg")),
|
||||
void_list_node);
|
||||
break;
|
||||
|
||||
default:
|
||||
my_friendly_abort (59);
|
||||
}
|
||||
|
||||
declspecs = decl_tree_cons (NULL_TREE, ridpointers [(int) RID_INLINE],
|
||||
declspecs);
|
||||
|
||||
TREE_PARMLIST (args) = 1;
|
||||
|
||||
{
|
||||
tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE);
|
||||
if (retref)
|
||||
declarator = build_parse_node (ADDR_EXPR, declarator);
|
||||
|
||||
fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
|
||||
}
|
||||
|
||||
if (fn == void_type_node)
|
||||
return fn;
|
||||
|
||||
if (kind > 2)
|
||||
SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn)));
|
||||
|
||||
#if 0
|
||||
if (processing_template_defn)
|
||||
{
|
||||
SET_DECL_IMPLICIT_INSTANTIATION (fn);
|
||||
repo_template_used (fn);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (CLASSTYPE_INTERFACE_KNOWN (type))
|
||||
{
|
||||
DECL_INTERFACE_KNOWN (fn) = 1;
|
||||
DECL_NOT_REALLY_EXTERN (fn) = (!CLASSTYPE_INTERFACE_ONLY (type)
|
||||
&& flag_implement_inlines);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
DECL_NOT_REALLY_EXTERN (fn) = 1;
|
||||
|
||||
defer_fn (fn);
|
||||
|
||||
#ifdef DEBUG_DEFAULT_FUNCTIONS
|
||||
{ char *fn_type = NULL;
|
||||
tree t = name;
|
||||
switch (kind)
|
||||
{
|
||||
case 0: fn_type = "default destructor"; break;
|
||||
case 1: fn_type = "virtual destructor"; break;
|
||||
case 2: fn_type = "default constructor"; break;
|
||||
case 3: fn_type = "default X(const X&)"; break;
|
||||
case 4: fn_type = "default X(X&)"; break;
|
||||
}
|
||||
if (fn_type)
|
||||
{
|
||||
if (TREE_CODE (name) == BIT_NOT_EXPR)
|
||||
t = TREE_OPERAND (name, 0);
|
||||
fprintf (stderr, "[[[[ %s for %s:\n%s]]]]\n", fn_type,
|
||||
IDENTIFIER_POINTER (t), func_buf);
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG_DEFAULT_FUNCTIONS */
|
||||
|
||||
/* Show that this function was generated by the compiler. */
|
||||
SET_DECL_ARTIFICIAL (fn);
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
/* Heuristic to tell whether the user is missing a semicolon
|
||||
after a struct or enum declaration. Emit an error message
|
||||
if we know the user has blown it. */
|
||||
|
|
|
@ -2383,7 +2383,7 @@ synthesize_method (fndecl)
|
|||
do_build_assign_ref (fndecl);
|
||||
need_body = 0;
|
||||
}
|
||||
else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
|
||||
else if (DECL_DESTRUCTOR_P (fndecl))
|
||||
setup_vtbl_ptr ();
|
||||
else
|
||||
{
|
||||
|
@ -2413,3 +2413,86 @@ synthesize_method (fndecl)
|
|||
else if (nested)
|
||||
pop_function_context_from (context);
|
||||
}
|
||||
|
||||
/* Implicitly declare the special function indicated by KIND, as a
|
||||
member of TYPE. For copy constructors and assignment operators,
|
||||
CONST_P indicates whether these functions should take a const
|
||||
reference argument or a non-const reference. */
|
||||
|
||||
tree
|
||||
implicitly_declare_fn (kind, type, const_p)
|
||||
special_function_kind kind;
|
||||
tree type;
|
||||
int const_p;
|
||||
{
|
||||
tree declspecs = NULL_TREE;
|
||||
tree fn, args = NULL_TREE;
|
||||
tree argtype;
|
||||
int retref = 0;
|
||||
tree name = constructor_name (TYPE_IDENTIFIER (type));
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
/* Destructors. */
|
||||
case sfk_destructor:
|
||||
name = build_parse_node (BIT_NOT_EXPR, name);
|
||||
args = void_list_node;
|
||||
break;
|
||||
|
||||
case sfk_constructor:
|
||||
/* Default constructor. */
|
||||
args = void_list_node;
|
||||
break;
|
||||
|
||||
case sfk_copy_constructor:
|
||||
if (const_p)
|
||||
type = build_qualified_type (type, TYPE_QUAL_CONST);
|
||||
argtype = build_reference_type (type);
|
||||
args = tree_cons (NULL_TREE,
|
||||
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
|
||||
get_identifier ("_ctor_arg")),
|
||||
void_list_node);
|
||||
break;
|
||||
|
||||
case sfk_assignment_operator:
|
||||
retref = 1;
|
||||
declspecs = build_decl_list (NULL_TREE, type);
|
||||
|
||||
if (const_p)
|
||||
type = build_qualified_type (type, TYPE_QUAL_CONST);
|
||||
|
||||
name = ansi_opname [(int) MODIFY_EXPR];
|
||||
|
||||
argtype = build_reference_type (type);
|
||||
args = tree_cons (NULL_TREE,
|
||||
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
|
||||
get_identifier ("_ctor_arg")),
|
||||
void_list_node);
|
||||
break;
|
||||
|
||||
default:
|
||||
my_friendly_abort (59);
|
||||
}
|
||||
|
||||
TREE_PARMLIST (args) = 1;
|
||||
|
||||
{
|
||||
tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE);
|
||||
if (retref)
|
||||
declarator = build_parse_node (ADDR_EXPR, declarator);
|
||||
|
||||
fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
|
||||
}
|
||||
|
||||
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 20000408);
|
||||
|
||||
if (kind != sfk_constructor && kind != sfk_destructor)
|
||||
SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn)));
|
||||
SET_DECL_ARTIFICIAL (fn);
|
||||
DECL_NOT_REALLY_EXTERN (fn) = 1;
|
||||
DECL_THIS_INLINE (fn) = 1;
|
||||
DECL_INLINE (fn) = 1;
|
||||
defer_fn (fn);
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
|
|
@ -5151,11 +5151,11 @@ build_static_cast (type, expr)
|
|||
LOOKUP_COMPLAIN, NULL_TREE)));
|
||||
|
||||
if (IS_AGGR_TYPE (type))
|
||||
return build_cplus_new
|
||||
(type, (build_method_call
|
||||
(NULL_TREE, ctor_identifier, build_tree_list (NULL_TREE, expr),
|
||||
TYPE_BINFO (type), LOOKUP_NORMAL)));
|
||||
|
||||
return build_cplus_new (type, (build_method_call
|
||||
(NULL_TREE, complete_ctor_identifier,
|
||||
build_tree_list (NULL_TREE, expr),
|
||||
TYPE_BINFO (type), LOOKUP_NORMAL)));
|
||||
|
||||
expr = decay_conversion (expr);
|
||||
intype = TREE_TYPE (expr);
|
||||
|
||||
|
@ -5671,7 +5671,7 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||
/* Do the default thing */;
|
||||
else
|
||||
{
|
||||
result = build_method_call (lhs, ctor_identifier,
|
||||
result = build_method_call (lhs, complete_ctor_identifier,
|
||||
build_tree_list (NULL_TREE, rhs),
|
||||
TYPE_BINFO (lhstype), LOOKUP_NORMAL);
|
||||
if (result == NULL_TREE)
|
||||
|
|
|
@ -1284,7 +1284,7 @@ build_functional_cast (exp, parms)
|
|||
return get_target_expr (exp);
|
||||
}
|
||||
|
||||
exp = build_method_call (NULL_TREE, ctor_identifier, parms,
|
||||
exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms,
|
||||
TYPE_BINFO (type), LOOKUP_NORMAL);
|
||||
|
||||
if (exp == error_mark_node)
|
||||
|
|
Loading…
Reference in New Issue