cp-tree.h (DECL_DESTRUCTOR_P): New macro.
authorJason Merrill <jason@gcc.gnu.org>
Fri, 29 May 1998 02:33:54 +0000 (22:33 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 29 May 1998 02:33:54 +0000 (22:33 -0400)
* 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/method.c
gcc/cp/pt.c

index 684c2af..ea4e5fb 100644 (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 
index 129047a..2c7917b 100644 (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));
index e3d1dd1..d61642c 100644 (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);
     }
index 9fb08ac..5f4d5e9 100644 (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;
     }
 
+  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).  */
index 054cfdd..2679d3e 100644 (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);
+}
 \f
 /* Given a tree_code CODE, and some arguments (at least one),
    attempt to use an overloaded operator on the arguments.
index e13135c..a214906 100644 (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