aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@gcc.gnu.org>1998-05-28 22:33:54 -0400
committerJason Merrill <jason@gcc.gnu.org>1998-05-28 22:33:54 -0400
commit711734a9c6e5f649d0557b9710ca97b4a1c55d9d (patch)
tree25e2c12ee0d8b3ffa267282b86a0afbbe7af373e
parentc71407f935c633b9d092349ad14ee0df473a34f9 (diff)
downloadgcc-711734a9c6e5f649d0557b9710ca97b4a1c55d9d.zip
gcc-711734a9c6e5f649d0557b9710ca97b4a1c55d9d.tar.gz
gcc-711734a9c6e5f649d0557b9710ca97b4a1c55d9d.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/cp/decl2.c149
-rw-r--r--gcc/cp/method.c10
-rw-r--r--gcc/cp/pt.c80
6 files changed, 144 insertions, 124 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 684c2af..ea4e5fb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 129047a..2c7917b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e3d1dd1..d61642c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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);
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 9fb08ac..5f4d5e9 100644
--- a/gcc/cp/decl2.c
+++ b/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;
}
+ 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)
{
- 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;
+ DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
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);
+ arg_types = hash_tree_chain (build_pointer_type (qualtype),
+ arg_types);
DECL_ASSEMBLER_NAME (function)
- = build_decl_overload (fn_name, these_arg_types,
+ = build_decl_overload (fn_name, arg_types,
1 + DECL_CONSTRUCTOR_P (function));
}
-
- DECL_ARGUMENTS (function) = last_function_parms;
- /* First approximations. */
- DECL_CONTEXT (function) = ctype;
- DECL_CLASS_CONTEXT (function) = ctype;
}
/* Work on the expr used by alignof (this is only called by the parser). */
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 054cfdd..2679d3e 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e13135c..a214906 100644
--- a/gcc/cp/pt.c
+++ b/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