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 684c2af544ea1c9955d8d5d924b31ac6cc0e61b1..ea4e5fb172631a1f29b0fa28329b00bd56e07840 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 129047a5d16aa7569d6a74686768b3b53882a967..2c7917b2a6a1e2aa0b4acd596e050f58cf2538f9 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 e3d1dd1a4ad7512443acd7c40566b36c30df5428..d61642c1402ff96d1bcf143f1669e6b6f8aa57c2 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 9fb08acb6bf1c249abd7c8aadf601c12ee023cad..5f4d5e9bcf88daf32cdc50a406c1541053060bda 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 054cfddb9f312b637ce998aca3e1c4156f22c221..2679d3e539ba8bacd55a5b145a0043547f85e6bf 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 e13135c66c8c42dec96c8ddfbc4abed239ed23ba..a214906eaaa16baaca1bdb36678a79b1dd2c7eab 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