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:
Mark Mitchell 2000-04-09 06:44:20 +00:00 committed by Mark Mitchell
parent 568fe067bc
commit 9eb71d8c3b
11 changed files with 182 additions and 204 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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;
}

View File

@ -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));

View File

@ -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)

View File

@ -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);
}

View File

@ -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)

View File

@ -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. */

View File

@ -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;
}

View File

@ -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)

View File

@ -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)