cp-tree.h (DECL_DESTRUCTOR_P): New macro.

* cp-tree.h (DECL_DESTRUCTOR_P): New macro.
	* method.c (build_destructor_name): New fn.
	* decl2.c (maybe_retrofit_in_chrg): Split out...
	(grokclassfn): From here.  Reorganize.
	* decl.c (grok_ctor_properties): Make sure ctors for types with
	vbases have the in_chrg parm.
	* pt.c (instantiate_class_template): Update
	TYPE_USES_VIRTUAL_BASECLASSES from tsubsted bases.  Don't call
	grok_*_properties.
	(tsubst): Call grok_ctor_properties and maybe_retrofit_in_chrg.
	* pt.c (instantiate_decl): Make test for whether or not static
	variables should be instantiated early match its comment.

From-SVN: r20136
This commit is contained in:
Jason Merrill 1998-05-28 22:33:54 -04:00
parent c71407f935
commit 711734a9c6
6 changed files with 152 additions and 132 deletions

View File

@ -1,3 +1,21 @@
1998-05-29 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (DECL_DESTRUCTOR_P): New macro.
* method.c (build_destructor_name): New fn.
* decl2.c (maybe_retrofit_in_chrg): Split out...
(grokclassfn): From here. Reorganize.
* decl.c (grok_ctor_properties): Make sure ctors for types with
vbases have the in_chrg parm.
* pt.c (instantiate_class_template): Update
TYPE_USES_VIRTUAL_BASECLASSES from tsubsted bases. Don't call
grok_*_properties.
(tsubst): Call grok_ctor_properties and maybe_retrofit_in_chrg.
1998-05-28 Mark Mitchell <mark@markmitchell.com>
* pt.c (instantiate_decl): Make test for whether or not static
variables should be instantiated early match its comment.
1998-05-28 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (start_decl): Always pedwarn about vacuously redeclaring

View File

@ -1087,6 +1087,8 @@ struct lang_decl
/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */
#define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr)
#define DECL_DESTRUCTOR_P(NODE) (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME(NODE)))
/* For FUNCTION_DECLs: nonzero means that this function is a constructor
for an object with virtual baseclasses. */
#define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr)
@ -2396,6 +2398,7 @@ extern int lang_decode_option PROTO((char *));
extern tree grok_method_quals PROTO((tree, tree, tree));
extern void warn_if_unknown_interface PROTO((tree));
extern tree grok_x_components PROTO((tree, tree));
extern void maybe_retrofit_in_chrg PROTO((tree));
extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree));
extern tree grok_alignof PROTO((tree));
extern tree grok_array_decl PROTO((tree, tree));
@ -2584,6 +2587,7 @@ extern tree build_decl_overload PROTO((tree, tree, int));
extern tree build_template_decl_overload PROTO((tree, tree, tree, tree, tree, int));
extern tree build_typename_overload PROTO((tree));
extern tree build_overload_with_type PROTO((tree, tree));
extern tree build_destructor_name PROTO((tree));
extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree));
extern tree hack_identifier PROTO((tree, tree));
extern tree make_thunk PROTO((tree, int));

View File

@ -10606,10 +10606,11 @@ grok_ctor_properties (ctype, decl)
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 (parmtypes
&& TREE_VALUE (parmtypes) == integer_type_node
&& TYPE_USES_VIRTUAL_BASECLASSES (ctype))
if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
{
my_friendly_assert (parmtypes
&& TREE_VALUE (parmtypes) == integer_type_node,
980529);
parmtypes = TREE_CHAIN (parmtypes);
parmtype = TREE_VALUE (parmtypes);
}

View File

@ -958,6 +958,57 @@ grok_x_components (specs, components)
return grok_enum_decls (components);
}
/* Constructors for types with virtual baseclasses need an "in-charge" flag
saying whether this constructor is responsible for initialization of
virtual baseclasses or not. All destructors also need this "in-charge"
flag, which additionally determines whether or not the destructor should
free the memory for the object.
This function adds the "in-charge" flag to member function FN if
appropriate. It is called from grokclassfn and tsubst.
FN must be either a constructor or destructor. */
void
maybe_retrofit_in_chrg (fn)
tree fn;
{
tree basetype, arg_types, parms, parm, fntype;
if (DECL_CONSTRUCTOR_P (fn)
&& TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn))
&& ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn))
/* OK */;
else if (! DECL_CONSTRUCTOR_P (fn)
&& TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE)
/* OK */;
else
return;
if (DECL_CONSTRUCTOR_P (fn))
DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1;
/* First add it to DECL_ARGUMENTS... */
parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
/* Mark the artificial `__in_chrg' parameter as "artificial". */
SET_DECL_ARTIFICIAL (parm);
DECL_ARG_TYPE (parm) = 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));
basetype = TREE_TYPE (TREE_VALUE (arg_types));
arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types));
fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
arg_types);
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
fntype = build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
TREE_TYPE (fn) = fntype;
}
/* Classes overload their constituent function names automatically.
When a function name is declared in a record structure,
its name is changed to it overloaded name. Since names for
@ -988,8 +1039,6 @@ grokclassfn (ctype, cname, function, flags, quals)
tree arg_types;
tree parm;
tree qualtype;
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
if (fn_name == NULL_TREE)
{
@ -1016,24 +1065,6 @@ grokclassfn (ctype, cname, function, flags, quals)
&& (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)))
constp = 0;
if (DECL_CONSTRUCTOR_P (function))
{
if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
{
DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1;
/* In this case we need "in-charge" flag saying whether
this constructor is responsible for initialization
of virtual baseclasses or not. */
parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
/* Mark the artificial `__in_chrg' parameter as "artificial". */
SET_DECL_ARTIFICIAL (parm);
DECL_ARG_TYPE (parm) = integer_type_node;
TREE_READONLY (parm) = 1;
TREE_CHAIN (parm) = last_function_parms;
last_function_parms = parm;
}
}
parm = build_decl (PARM_DECL, this_identifier, type);
/* Mark the artificial `this' parameter as "artificial". */
SET_DECL_ARTIFICIAL (parm);
@ -1047,81 +1078,33 @@ grokclassfn (ctype, cname, function, flags, quals)
last_function_parms = parm;
}
if (flags == DTOR_FLAG)
{
char *buf, *dbuf;
int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1;
arg_types = hash_tree_chain (integer_type_node, void_list_node);
TREE_SIDE_EFFECTS (arg_types) = 1;
/* Build the overload name. It will look like `7Example'. */
if (IDENTIFIER_TYPE_VALUE (cname))
dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1);
else if (IDENTIFIER_LOCAL_VALUE (cname))
dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)),
1, 1);
else
/* Using ctype fixes the `X::Y::~Y()' crash. The cname has no type when
it's defined out of the class definition, since poplevel_class wipes
it out. This used to be internal error 346. */
dbuf = build_overload_name (ctype, 1, 1);
buf = (char *) alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX));
bcopy (DESTRUCTOR_DECL_PREFIX, buf, len);
buf[len] = '\0';
strcat (buf, dbuf);
DECL_ASSEMBLER_NAME (function) = get_identifier (buf);
parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
/* Mark the artificial `__in_chrg' parameter as "artificial". */
SET_DECL_ARTIFICIAL (parm);
TREE_READONLY (parm) = 1;
DECL_ARG_TYPE (parm) = integer_type_node;
/* This is the same chain as DECL_ARGUMENTS (...). */
TREE_CHAIN (last_function_parms) = parm;
fntype = build_cplus_method_type (qualtype, void_type_node,
arg_types);
if (raises)
{
fntype = build_exception_variant (fntype, raises);
}
TREE_TYPE (function) = fntype;
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
{
tree these_arg_types;
if (DECL_CONSTRUCTOR_FOR_VBASE_P (function))
{
arg_types = hash_tree_chain (integer_type_node,
TREE_CHAIN (arg_types));
fntype = build_cplus_method_type (qualtype,
TREE_TYPE (TREE_TYPE (function)),
arg_types);
if (raises)
{
fntype = build_exception_variant (fntype, raises);
}
TREE_TYPE (function) = fntype;
arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
}
these_arg_types = arg_types;
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
/* Only true for static member functions. */
these_arg_types = hash_tree_chain (build_pointer_type (qualtype),
arg_types);
DECL_ASSEMBLER_NAME (function)
= build_decl_overload (fn_name, these_arg_types,
1 + DECL_CONSTRUCTOR_P (function));
}
DECL_ARGUMENTS (function) = last_function_parms;
/* First approximations. */
DECL_CONTEXT (function) = ctype;
DECL_CLASS_CONTEXT (function) = ctype;
if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
{
maybe_retrofit_in_chrg (function);
arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
}
if (flags == DTOR_FLAG)
{
DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
{
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
/* Only true for static member functions. */
arg_types = hash_tree_chain (build_pointer_type (qualtype),
arg_types);
DECL_ASSEMBLER_NAME (function)
= build_decl_overload (fn_name, arg_types,
1 + DECL_CONSTRUCTOR_P (function));
}
}
/* Work on the expr used by alignof (this is only called by the parser). */

View File

@ -1728,6 +1728,16 @@ get_id_2 (name, name2)
OB_FINISH ();
return get_identifier (obstack_base (&scratch_obstack));
}
/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */
tree
build_destructor_name (type)
tree type;
{
return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX),
type);
}
/* Given a tree_code CODE, and some arguments (at least one),
attempt to use an overloaded operator on the arguments.

View File

@ -3777,19 +3777,33 @@ instantiate_class_template (type)
bases = make_tree_vec (len);
for (i = 0; i < len; ++i)
{
tree elt;
tree elt, basetype;
TREE_VEC_ELT (bases, i) = elt
= tsubst (TREE_VEC_ELT (pbases, i), args, NULL_TREE);
BINFO_INHERITANCE_CHAIN (elt) = binfo;
if (! IS_AGGR_TYPE (TREE_TYPE (elt)))
basetype = TREE_TYPE (elt);
if (! IS_AGGR_TYPE (basetype))
cp_error
("base type `%T' of `%T' fails to be a struct or class type",
TREE_TYPE (elt), type);
else if (TYPE_SIZE (complete_type (TREE_TYPE (elt))) == NULL_TREE)
basetype, type);
else if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE)
cp_error ("base class `%T' of `%T' has incomplete type",
TREE_TYPE (elt), type);
basetype, type);
/* These are set up in xref_basetypes for normal classes, so
we have to handle them here for template bases. */
if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
TYPE_USES_VIRTUAL_BASECLASSES (type) = 1;
TYPE_USES_COMPLEX_INHERITANCE (type) = 1;
}
TYPE_GETS_NEW (type) |= TYPE_GETS_NEW (basetype);
TYPE_GETS_DELETE (type) |= TYPE_GETS_DELETE (basetype);
CLASSTYPE_LOCAL_TYPEDECLS (type)
|= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
}
/* Don't initialize this until the vector is filled out, or
lookups will crash. */
@ -3837,13 +3851,6 @@ instantiate_class_template (type)
}
TYPE_METHODS (type) = tsubst_chain (TYPE_METHODS (pattern), args);
for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
{
if (DECL_CONSTRUCTOR_P (t))
grok_ctor_properties (type, t);
else if (IDENTIFIER_OPNAME_P (DECL_NAME (t)))
grok_op_properties (t, DECL_VIRTUAL_P (t), 0);
}
/* Construct the DECL_FRIENDLIST for the new class type. */
typedecl = TYPE_MAIN_DECL (type);
@ -4542,17 +4549,30 @@ tsubst (t, args, in_decl)
DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
}
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
DECL_MAIN_VARIANT (r) = r;
DECL_RESULT (r) = NULL_TREE;
DECL_INITIAL (r) = NULL_TREE;
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
DECL_EXTERNAL (r) = 1;
DECL_INTERFACE_KNOWN (r) = 0;
DECL_DEFER_OUTPUT (r) = 0;
TREE_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
TREE_USED (r) = 0;
if (DECL_CONSTRUCTOR_P (r))
{
char *buf, *dbuf = build_overload_name (ctx, 1, 1);
int len = sizeof (DESTRUCTOR_DECL_PREFIX) - 1;
buf = (char *) alloca (strlen (dbuf)
+ sizeof (DESTRUCTOR_DECL_PREFIX));
bcopy (DESTRUCTOR_DECL_PREFIX, buf, len);
buf[len] = '\0';
strcat (buf, dbuf);
DECL_ASSEMBLER_NAME (r) = get_identifier (buf);
maybe_retrofit_in_chrg (r);
grok_ctor_properties (ctx, r);
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
if (DECL_DESTRUCTOR_P (t))
DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
else
{
/* Instantiations of template functions must be mangled
@ -4645,23 +4665,6 @@ tsubst (t, args, in_decl)
DECL_RTL (r) = 0;
make_decl_rtl (r, NULL_PTR, 1);
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
DECL_MAIN_VARIANT (r) = r;
DECL_RESULT (r) = NULL_TREE;
DECL_INITIAL (r) = NULL_TREE;
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
DECL_EXTERNAL (r) = 1;
DECL_INTERFACE_KNOWN (r) = 0;
DECL_DEFER_OUTPUT (r) = 0;
TREE_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
TREE_USED (r) = 0;
if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
{
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
@ -7141,6 +7144,7 @@ instantiate_decl (d)
goto out;
if (TREE_CODE (d) == VAR_DECL
&& TREE_READONLY (d)
&& DECL_INITIAL (d) == NULL_TREE
&& DECL_INITIAL (code_pattern) != NULL_TREE)
/* We need to set up DECL_INITIAL regardless of pattern_defined if