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:
parent
c71407f935
commit
711734a9c6
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
165
gcc/cp/decl2.c
165
gcc/cp/decl2.c
|
@ -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). */
|
||||
|
|
|
@ -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.
|
||||
|
|
80
gcc/cp/pt.c
80
gcc/cp/pt.c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue