OSDN Git Service

* cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Apr 2000 20:16:36 +0000 (20:16 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Apr 2000 20:16:36 +0000 (20:16 +0000)
(complete_dtor_identifier): New macro.
(CLASSTYPE_FIRST_CONVERSION): Remove.
(CLASSTYPE_CONSTRUCTOR_SLOT): New macro.
(CLASSTYPE_DESTRUCTOR_SLOT): Likewise.
(CLASSTYPE_FIRST_CONVERSION_SLOT): Likewise.
(CLASSTYPE_CONSTRUCTORS): Likewise.
(CLASSTYPE_DESTRUCTORS): Likewise.
(lang_decl): Add cloned_function.
(DECL_COMPLETE_CONSTRUCTOR_P): New macro.
(DECL_BASE_CONSTRUCTOR_P): Likewise.
(DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P): Likewise.
(DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P): Likewise.
(DECL_CLONED_FUNCTION_P): Likewise.
(DECL_CLONED_FUNCTION): Likewise.
(clone_function_decl): Declare.
(maybe_clone_body): Likewise.
* call.c (build_user_type_conversion_1): Call complete object
constructors in the new ABI.
(build_new_method_call): Don't add in-charge parameters under the
new ABI.
* class.c (add_method): Use DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P,
DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P, CLASSTYPE_CONSTRUCTOR_SLOT, and
CLASSTYPE_DESTRUCTOR_SLOT.
(build_clone): New function.
(clone_function_decl): Likewise.
(clone_constructors_and_destructors): Likewise.
(check_bases_and_members): Use it.
* decl.c (iniitialize_predefined_identifiers): Initialize
complete_dtor_identifier.
(finish_function): Don't add extra code to a clone.
(lang_mark_tree): Mark cloned_function.
* decl2.c (mark_used): Don't bother trying to instantiate things
we synthesized.
* dump.c (dequeue_and_dump): Don't dump CP_DECL_CONTEXT twice.
* method.c (set_mangled_name_for_decl): Don't treat clones as
constructors.
(synthesize_method): Sythesize cloned functions, not the clones.
* optimize.c (inline_data): Update comment on ret_label.
(remap_block): Don't assume DECL_INITIAL exists.
(copy_body_r): Allow ret_label to be NULL.
(maybe_clone_body): Define.
* pt.c (tsubst_decl): Handle clones.
(instantiate_clone): New function.
(instantiate_template): Use it.
(set_mangled_name_for_template_decl): Don't treat clones as
constructors.
* search.c (lookup_fnfields_1): Use CLASSTYPE_CONSTRUCTOR_SLOT,
CLASSTYPE_DESTRUCTOR_SLOT, and CLASSTYPE_FIRST_CONVERSION_SLOT.
* semantics.c (expand_body): Clone function bodies as necessary.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33084 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/dump.c
gcc/cp/method.c
gcc/cp/optimize.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/semantics.c

index c3b2d47..18f252d 100644 (file)
@@ -1,5 +1,56 @@
 2000-04-11  Mark Mitchell  <mark@codesourcery.com>
 
+       * cp-tree.h (cp_tree_index): Add CPTI_DTOR_IDENTIFIER.
+       (complete_dtor_identifier): New macro.
+       (CLASSTYPE_FIRST_CONVERSION): Remove.
+       (CLASSTYPE_CONSTRUCTOR_SLOT): New macro.
+       (CLASSTYPE_DESTRUCTOR_SLOT): Likewise.
+       (CLASSTYPE_FIRST_CONVERSION_SLOT): Likewise.
+       (CLASSTYPE_CONSTRUCTORS): Likewise.
+       (CLASSTYPE_DESTRUCTORS): Likewise.
+       (lang_decl): Add cloned_function.
+       (DECL_COMPLETE_CONSTRUCTOR_P): New macro.
+       (DECL_BASE_CONSTRUCTOR_P): Likewise.
+       (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P): Likewise.
+       (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P): Likewise.
+       (DECL_CLONED_FUNCTION_P): Likewise.
+       (DECL_CLONED_FUNCTION): Likewise.
+       (clone_function_decl): Declare.
+       (maybe_clone_body): Likewise.
+       * call.c (build_user_type_conversion_1): Call complete object
+       constructors in the new ABI.
+       (build_new_method_call): Don't add in-charge parameters under the
+       new ABI.
+       * class.c (add_method): Use DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P,
+       DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P, CLASSTYPE_CONSTRUCTOR_SLOT, and
+       CLASSTYPE_DESTRUCTOR_SLOT.
+       (build_clone): New function.
+       (clone_function_decl): Likewise.
+       (clone_constructors_and_destructors): Likewise.
+       (check_bases_and_members): Use it.
+       * decl.c (iniitialize_predefined_identifiers): Initialize
+       complete_dtor_identifier.
+       (finish_function): Don't add extra code to a clone.
+       (lang_mark_tree): Mark cloned_function.
+       * decl2.c (mark_used): Don't bother trying to instantiate things
+       we synthesized.
+       * dump.c (dequeue_and_dump): Don't dump CP_DECL_CONTEXT twice.
+       * method.c (set_mangled_name_for_decl): Don't treat clones as
+       constructors.
+       (synthesize_method): Sythesize cloned functions, not the clones.
+       * optimize.c (inline_data): Update comment on ret_label.
+       (remap_block): Don't assume DECL_INITIAL exists.
+       (copy_body_r): Allow ret_label to be NULL.
+       (maybe_clone_body): Define.
+       * pt.c (tsubst_decl): Handle clones.
+       (instantiate_clone): New function.
+       (instantiate_template): Use it.
+       (set_mangled_name_for_template_decl): Don't treat clones as
+       constructors.
+       * search.c (lookup_fnfields_1): Use CLASSTYPE_CONSTRUCTOR_SLOT,
+       CLASSTYPE_DESTRUCTOR_SLOT, and CLASSTYPE_FIRST_CONVERSION_SLOT.
+       * semantics.c (expand_body): Clone function bodies as necessary.
+       
        * optimize.c (remap_decl): Avoid sharing structure for arrays
        whose size is only known at run-time.
        * tree.c (copy_tree_r): Don't copy PARM_DECLs.
index 040801b..c003248 100644 (file)
@@ -2277,7 +2277,12 @@ build_user_type_conversion_1 (totype, expr, flags)
   tree templates = NULL_TREE;
 
   if (IS_AGGR_TYPE (totype))
-    ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
+    ctors = lookup_fnfields (TYPE_BINFO (totype),
+                            (flag_new_abi 
+                             ? complete_ctor_identifier
+                             : ctor_identifier),
+                            0);
+
   if (IS_AGGR_TYPE (fromtype)
       && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
     convs = lookup_conversions (fromtype);
@@ -4253,22 +4258,26 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       || name == base_ctor_identifier)
     {
       pretty_name = constructor_name (basetype);
-      /* Add the in-charge parameter as an implicit first argument.  */
-      if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+
+      if (!flag_new_abi)
        {
-         tree in_charge;
+         /* Add the in-charge parameter as an implicit first argument.  */
+         if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+           {
+             tree in_charge;
 
-         if (name == complete_ctor_identifier)
-           in_charge = integer_one_node;
-         else
-           in_charge = integer_zero_node;
+             if (name == complete_ctor_identifier)
+               in_charge = integer_one_node;
+             else
+               in_charge = integer_zero_node;
 
-         args = tree_cons (NULL_TREE, in_charge, args);
-       }
+             args = tree_cons (NULL_TREE, in_charge, args);
+           }
 
-      /* We want to call the normal constructor function under the old
-        ABI.  */
-      name = ctor_identifier;
+         /* We want to call the normal constructor function under the
+            old ABI.  */
+         name = ctor_identifier;
+       }
     }
   else
     pretty_name = name;
index 5262faa..d954ac0 100644 (file)
@@ -174,6 +174,8 @@ static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
                                                        vcall_offset_data *));
 static tree dfs_mark_primary_bases PARAMS ((tree, void *));
 static void mark_primary_bases PARAMS ((tree));
+static void clone_constructors_and_destructors PARAMS ((tree));
+static tree build_clone PARAMS ((tree, tree));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -1150,14 +1152,15 @@ add_method (type, fields, method)
       method_vec = CLASSTYPE_METHOD_VEC (type);
       len = TREE_VEC_LENGTH (method_vec);
 
-      if (DECL_NAME (method) == constructor_name (type))
-       /* A new constructor or destructor.  Constructors go in 
-          slot 0; destructors go in slot 1.  */
-       slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
+      /* Constructors and destructors go in special slots.  */
+      if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
+       slot = CLASSTYPE_CONSTRUCTOR_SLOT;
+      else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
+       slot = CLASSTYPE_DESTRUCTOR_SLOT;
       else
        {
          /* See if we already have an entry with this name.  */
-         for (slot = 2; slot < len; ++slot)
+         for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
            if (!TREE_VEC_ELT (method_vec, slot)
                || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, 
                                                          slot))) 
@@ -3855,6 +3858,151 @@ check_methods (t)
     }
 }
 
+/* FN is a constructor or destructor.  Clone the declaration to create
+   a specialized in-charge or not-in-charge version, as indicated by
+   NAME.  */
+
+static tree
+build_clone (fn, name)
+     tree fn;
+     tree name;
+{
+  tree parms;
+  tree clone;
+
+  /* Copy the function.  */
+  clone = copy_decl (fn);
+  /* Remember where this function came from.  */
+  DECL_CLONED_FUNCTION (clone) = fn;
+  /* Reset the function name.  */
+  DECL_NAME (clone) = name;
+  DECL_ASSEMBLER_NAME (clone) = DECL_NAME (clone);
+  /* There's no pending inline data for this function.  */
+  DECL_PENDING_INLINE_INFO (clone) = NULL;
+  DECL_PENDING_INLINE_P (clone) = 0;
+  /* And it hasn't yet been deferred.  */
+  DECL_DEFERRED_FN (clone) = 0;
+
+  /* If there was an in-charge paramter, drop it from the function
+     type.  */
+  if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+    {
+      tree basetype;
+      tree parmtypes;
+      tree exceptions;
+
+      exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
+      basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
+      parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone));
+      /* Skip the `this' parameter.  */
+      parmtypes = TREE_CHAIN (parmtypes);
+      /* Skip the in-charge parameter.  */
+      parmtypes = TREE_CHAIN (parmtypes);
+      TREE_TYPE (clone) 
+       = build_cplus_method_type (basetype,
+                                  TREE_TYPE (TREE_TYPE (clone)),
+                                  parmtypes);
+      if (exceptions)
+       TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
+                                                    exceptions);
+    }
+
+  /* Copy the function parameters.  But, DECL_ARGUMENTS aren't
+     function parameters; instead, those are the template parameters.  */
+  if (TREE_CODE (clone) != TEMPLATE_DECL)
+    {
+      DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone));
+      /* Remove the in-charge parameter.  */
+      if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+       {
+         TREE_CHAIN (DECL_ARGUMENTS (clone))
+           = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
+         DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
+       }
+      for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
+       {
+         DECL_CONTEXT (parms) = clone;
+         copy_lang_decl (parms);
+       }
+    }
+
+  /* Mangle the function name.  */
+  set_mangled_name_for_decl (clone);
+
+  /* Create the RTL for this function.  */
+  DECL_RTL (clone) = NULL_RTX;
+  rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof);
+  
+  /* Make it easy to find the CLONE given the FN.  */
+  TREE_CHAIN (clone) = TREE_CHAIN (fn);
+  TREE_CHAIN (fn) = clone;
+
+  /* If this is a template, handle the DECL_TEMPLATE_RESULT as well.  */
+  if (TREE_CODE (clone) == TEMPLATE_DECL)
+    {
+      tree result;
+
+      DECL_TEMPLATE_RESULT (clone) 
+       = build_clone (DECL_TEMPLATE_RESULT (clone), name);
+      result = DECL_TEMPLATE_RESULT (clone);
+      DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result));
+      DECL_TI_TEMPLATE (result) = clone;
+    }
+
+  return clone;
+}
+
+/* Produce declarations for all appropriate clones of FN.  If
+   UPDATE_METHOD_VEC_P is non-zero, the clones are added to the
+   CLASTYPE_METHOD_VEC as well.  */
+
+void
+clone_function_decl (fn, update_method_vec_p)
+     tree fn;
+     int update_method_vec_p;
+{
+  tree clone;
+
+  if (DECL_CONSTRUCTOR_P (fn))
+    {
+      clone = build_clone (fn, complete_ctor_identifier);
+      if (update_method_vec_p)
+       add_method (DECL_CONTEXT (clone), NULL, clone);
+      clone = build_clone (fn, base_ctor_identifier);
+      if (update_method_vec_p)
+       add_method (DECL_CONTEXT (clone), NULL, clone);
+    }
+  else
+    /* We don't do destructors yet.  */
+    my_friendly_abort (20000411);
+}
+
+/* For each of the constructors and destructors in T, create an
+   in-charge and not-in-charge variant.  */
+
+static void
+clone_constructors_and_destructors (t)
+     tree t;
+{
+  tree fns;
+
+  /* We only clone constructors and destructors under the new ABI.  */
+  if (!flag_new_abi)
+    return;
+
+  /* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail
+     out now.  */
+  if (!CLASSTYPE_METHOD_VEC (t))
+    return;
+
+  /* For each constructor, we need two variants: an in-charge version
+     and a not-in-charge version.  */
+  for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+    clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
+
+  /* For now, we don't do the destructors.  */
+}
+
 /* Remove all zero-width bit-fields from T.  */
 
 static void
@@ -3950,6 +4098,10 @@ check_bases_and_members (t, empty_p)
                                   cant_have_const_ctor,
                                   no_const_asn_ref);
 
+  /* Create the in-charge and not-in-charge variants of constructors
+     and destructors.  */
+  clone_constructors_and_destructors (t);
+
   /* Process the using-declarations.  */
   for (; access_decls; access_decls = TREE_CHAIN (access_decls))
     handle_using_decl (TREE_VALUE (access_decls), t);
index b9fa50e..db6a41c 100644 (file)
@@ -559,6 +559,7 @@ enum cp_tree_index
     CPTI_COMPLETE_CTOR_IDENTIFIER,
     CPTI_BASE_CTOR_IDENTIFIER,
     CPTI_DTOR_IDENTIFIER,
+    CPTI_COMPLETE_DTOR_IDENTIFIER,
     CPTI_BASE_DTOR_IDENTIFIER,
     CPTI_DELETING_DTOR_IDENTIFIER,
     CPTI_DELTA2_IDENTIFIER,
@@ -653,14 +654,18 @@ extern tree cp_global_trees[CPTI_MAX];
    frequently.  */
 
 /* The name of a constructor that takes an in-charge parameter to
-   decide whether or not to call virtual base classes.  */
+   decide whether or not to construct virtual base classes.  */
 #define ctor_identifier                 cp_global_trees[CPTI_CTOR_IDENTIFIER]
 /* The name of a constructor that constructs virtual base classes.  */
 #define complete_ctor_identifier        cp_global_trees[CPTI_COMPLETE_CTOR_IDENTIFIER]
 /* The name of a constructor that does not construct virtual base classes.  */
 #define base_ctor_identifier            cp_global_trees[CPTI_BASE_CTOR_IDENTIFIER]
-/* The name of a destructor that destroys virtual base classes.  */
+/* The name of a destructor that takes an in-charge parameter to
+   decide whether or not to destroy virtual base classes and whether
+   or not to delete the object.  */
 #define dtor_identifier                 cp_global_trees[CPTI_DTOR_IDENTIFIER]
+/* The name of a destructor that destroys virtual base classes.  */
+#define complete_dtor_identifier        cp_global_trees[CPTI_COMPLETE_DTOR_IDENTIFIER]
 /* The name of a destructor that does not destroy virtual base
    classes.  */
 #define base_dtor_identifier            cp_global_trees[CPTI_BASE_DTOR_IDENTIFIER]
@@ -1475,17 +1480,29 @@ struct lang_type
    either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD.  All
    functions with the same name end up in the same slot.  The first
    two elements are for constructors, and destructors, respectively.
-   These are followed by ordinary member functions.  There may be
-   empty entries at the end of the vector.  */
+   Any conversion operators are next, followed by ordinary member
+   functions.  There may be empty entries at the end of the vector.  */
 #define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
 
-/* The first type conversion operator in the class (the others can be
-   searched with TREE_CHAIN), or the first non-constructor function if
-   there are no type conversion operators.  */
-#define CLASSTYPE_FIRST_CONVERSION(NODE) \
-  TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 2 \
-    ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \
-    : NULL_TREE;
+/* The slot in the CLASSTYPE_METHOD_VEC where constructors go.  */
+#define CLASSTYPE_CONSTRUCTOR_SLOT 0
+
+/* The slot in the CLASSTYPE_METHOD_VEC where destructors go.  */
+#define CLASSTYPE_DESTRUCTOR_SLOT 1
+
+/* The first slot in the CLASSTYPE_METHOD_VEC where conversion
+   operators can appear.  */
+#define CLASSTYPE_FIRST_CONVERSION_SLOT 2
+
+/* A FUNCTION_DECL or OVERLOAD for the constructors for NODE.  These
+   are the constructors that take an in-charge parameter.  */
+#define CLASSTYPE_CONSTRUCTORS(NODE) \
+  (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT))
+
+/* A FUNCTION_DECL for the destructor for NODE.  These are te
+   destructors that take an in-charge parameter.  */
+#define CLASSTYPE_DESTRUCTORS(NODE) \
+  (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT))
 
 /* Mark bits for depth-first and breath-first searches.  */
 
@@ -1882,6 +1899,9 @@ struct lang_decl
   /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.  */
   tree saved_tree;
 
+  /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
+  tree cloned_function;
+
   union
   {
     tree sorted_fields;
@@ -1909,6 +1929,24 @@ 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)
 
+/* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a complete
+   object.  */
+#define DECL_COMPLETE_CONSTRUCTOR_P(NODE)              \
+  (DECL_CONSTRUCTOR_P (NODE)                           \
+   && DECL_NAME (NODE) == complete_ctor_identifier)
+
+/* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a base
+   object.  */
+#define DECL_BASE_CONSTRUCTOR_P(NODE)          \
+  (DECL_CONSTRUCTOR_P (NODE)                   \
+   && DECL_NAME (NODE) == base_ctor_identifier)
+
+/* Nonzero if NODE (a FUNCTION_DECL) is a constructor, but not either the
+   specialized in-charge constructor or the specialized not-in-charge
+   constructor.  */
+#define DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P(NODE)               \
+  (DECL_CONSTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE))
+
 /* Nonzero if NODE (a FUNCTION_DECL) is a copy constructor.  */
 #define DECL_COPY_CONSTRUCTOR_P(NODE) \
   (DECL_CONSTRUCTOR_P (NODE) && copy_args_p (NODE))
@@ -1919,6 +1957,22 @@ struct lang_decl
   (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE))      \
    && DECL_LANGUAGE (NODE) == lang_cplusplus)
 
+/* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the
+   specialized in-charge constructor, in-charge deleting constructor,
+   or the the base destructor.  */
+#define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE)                        \
+  (DECL_DESTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE))
+
+/* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or
+   destructor.  */
+#define DECL_CLONED_FUNCTION_P(NODE) \
+  (DECL_CLONED_FUNCTION (NODE) != NULL_TREE)
+
+/* If DECL_CLONED_FUNCTION_P holds, this is the function that was
+   cloned.  */
+#define DECL_CLONED_FUNCTION(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->cloned_function)
+
 /* Non-zero if NODE is a user-defined conversion operator.  */
 #define DECL_CONV_FN_P(NODE)                                                \
   (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE)))
@@ -3723,6 +3777,7 @@ extern tree build_type_conversion         PARAMS ((tree, tree, int));
 extern tree build_expr_type_conversion         PARAMS ((int, tree, int));
 extern tree type_promotes_to                   PARAMS ((tree));
 extern tree perform_qualification_conversions   PARAMS ((tree, tree));
+extern void clone_function_decl                 PARAMS ((tree, int));
 
 /* decl.c */
 /* resume_binding_level */
@@ -4093,6 +4148,7 @@ extern tree implicitly_declare_fn               PARAMS ((special_function_kind,
 /* In optimize.c */
 extern void optimize_function                   PARAMS ((tree));
 extern int calls_setjmp_p                       PARAMS ((tree));
+extern int maybe_clone_body                     PARAMS ((tree));
 
 /* in pt.c */
 extern void init_pt                             PARAMS ((void));
index a07cb3a..6b490a6 100644 (file)
@@ -6063,6 +6063,7 @@ initialize_predefined_identifiers ()
     { "__base_ctor", &base_ctor_identifier },
     { "__comp_ctor", &complete_ctor_identifier },
     { DTOR_NAME, &dtor_identifier },
+    { "__comp_dtor", &complete_dtor_identifier },
     { "__base_dtor", &base_dtor_identifier },
     { "__deleting_dtor", &deleting_dtor_identifier },
     { VTABLE_DELTA2_NAME, &delta2_identifier },
@@ -13966,7 +13967,11 @@ finish_function (flags)
       store_parm_decls ();
     }
 
-  if (building_stmt_tree ())
+  /* For a cloned function, we've already got all the code we need;
+     there's no need to add any extra bits.  */
+  if (building_stmt_tree () && DECL_CLONED_FUNCTION_P (fndecl))
+    ;
+  else if (building_stmt_tree ())
     {
       if (DECL_CONSTRUCTOR_P (fndecl))
        {
@@ -14763,6 +14768,7 @@ lang_mark_tree (t)
            {
              ggc_mark_tree (ld->befriending_classes);
              ggc_mark_tree (ld->saved_tree);
+             ggc_mark_tree (ld->cloned_function);
              if (TREE_CODE (t) == TYPE_DECL)
                ggc_mark_tree (ld->u.sorted_fields);
              else if (TREE_CODE (t) == FUNCTION_DECL
index 3e0a9df..83279a1 100644 (file)
@@ -5228,7 +5228,12 @@ mark_used (decl)
       && ! DECL_INITIAL (decl)
       /* Kludge: don't synthesize for default args.  */
       && current_function_decl)
-    synthesize_method (decl);
+    {
+      synthesize_method (decl);
+      /* If we've already synthesized the method we don't need to
+        instantiate it, so we can return right away.  */
+      return;
+    }
 
   /* If this is a function or variable that is an instance of some
      template, we now know that we will need to actually do the
index 7f81094..dd6673c 100644 (file)
@@ -557,7 +557,6 @@ dequeue_and_dump (di)
 
     case FUNCTION_DECL:
     case THUNK_DECL:
-      dump_child ("scpe", CP_DECL_CONTEXT (t));
       dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
       dump_child ("args", DECL_ARGUMENTS (t));
       if (DECL_EXTERNAL (t))
index c5e4805..ecc7dc0 100644 (file)
@@ -1748,7 +1748,7 @@ set_mangled_name_for_decl (decl)
   DECL_ASSEMBLER_NAME (decl)
     = build_decl_overload (DECL_NAME (decl), parm_types, 
                           DECL_FUNCTION_MEMBER_P (decl)
-                          + DECL_CONSTRUCTOR_P (decl));
+                          + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
 }
 
 /* Build an overload name for the type expression TYPE.  */
@@ -2359,6 +2359,15 @@ synthesize_method (fndecl)
   if (at_eof)
     import_export_decl (fndecl);
 
+  /* If we've been asked to synthesize a clone, just synthesize the
+     cloned function instead.  Doing so will automatically fill in the
+     body for the clone.  */
+  if (DECL_CLONED_FUNCTION_P (fndecl))
+    {
+      synthesize_method (DECL_CLONED_FUNCTION (fndecl));
+      return;
+    }
+
   if (! context)
     push_to_top_level ();
   else if (nested)
index b12a2ff..9f2fe35 100644 (file)
@@ -50,7 +50,9 @@ typedef struct inline_data
      inlining the body of `h', the stack will contain, `h', followed
      by `g', followed by `f'.  */
   varray_type fns;
-  /* The label to jump to when a return statement is encountered.  */
+  /* The label to jump to when a return statement is encountered.  If
+     this value is NULL, then return statements will simply be
+     remapped as return statements, rather than as jumps.  */
   tree ret_label;
   /* The map from local declarations in the inlined function to
      equivalents in the function into which it is being inlined.  */
@@ -157,6 +159,7 @@ remap_block (scope_stmt, decls, id)
       tree old_block;
       tree new_block;
       tree old_var;
+      tree *first_block;
       tree fn;
 
       /* Make the new block.  */
@@ -175,9 +178,12 @@ remap_block (scope_stmt, decls, id)
 
          /* Remap the variable.  */
          new_var = remap_decl (old_var, id);
-         if (!new_var)
-           /* We didn't remap this variable, so we can't mess with
-              its TREE_CHAIN.  */
+         /* If we didn't remap this variable, so we can't mess with
+            its TREE_CHAIN.  If we remapped this variable to
+            something other than a declaration (say, if we mapped it
+            to a constant), then we must similarly omit any mention
+            of it here.  */
+         if (!new_var || !DECL_P (new_var))
            ;
          else
            {
@@ -191,8 +197,12 @@ remap_block (scope_stmt, decls, id)
         function into which this block is being inlined.  In
         rest_of_compilation we will straighten out the BLOCK tree.  */
       fn = VARRAY_TREE (id->fns, 0);
-      BLOCK_CHAIN (new_block) = BLOCK_CHAIN (DECL_INITIAL (fn));
-      BLOCK_CHAIN (DECL_INITIAL (fn)) = new_block;
+      if (DECL_INITIAL (fn))
+       first_block = &BLOCK_CHAIN (DECL_INITIAL (fn));
+      else
+       first_block = &DECL_INITIAL (fn);
+      BLOCK_CHAIN (new_block) = *first_block;
+      *first_block = new_block;
       /* Remember the remapped block.  */
       splay_tree_insert (id->decl_map,
                         (splay_tree_key) old_block,
@@ -261,7 +271,7 @@ copy_body_r (tp, walk_subtrees, data)
 
   /* If this is a RETURN_STMT, change it into an EXPR_STMT and a
      GOTO_STMT with the RET_LABEL as its target.  */
-  if (TREE_CODE (*tp) == RETURN_STMT)
+  if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label)
     {
       tree return_stmt = *tp;
       tree goto_stmt;
@@ -774,3 +784,106 @@ calls_setjmp_p (fn)
          != NULL_TREE);
 }
 
+/* FN is a function that has a complete body.  Clone the body as
+   necessary.  Returns non-zero if there's no longer any need to
+   process the main body.  */
+
+int
+maybe_clone_body (fn)
+     tree fn;
+{
+  inline_data id;
+  tree clone;
+
+  /* We don't clone constructors and destructors under the old ABI.  */
+  if (!flag_new_abi)
+    return 0;
+
+  /* We only clone constructors and destructors.  */
+  if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
+      && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
+    return 0;
+
+  /* We don't yet handle destructors.  */
+  if (DECL_DESTRUCTOR_P (fn))
+    return 0;
+
+  /* We know that any clones immediately follow FN in the TYPE_METHODS
+     list.  */
+  for (clone = TREE_CHAIN (fn);
+       clone && DECL_CLONED_FUNCTION_P (clone);
+       clone = TREE_CHAIN (clone))
+    {
+      tree parm;
+      tree clone_parm;
+      int parmno;
+
+      /* Update CLONE's source position information to match FN's.  */
+      DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
+      DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
+
+      /* Start processing the function.  */
+      push_to_top_level ();
+      start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
+      store_parm_decls ();
+
+      /* Just clone the body, as if we were making an inline call.
+        But, remap the parameters in the callee to the parameters of
+        caller.  If there's an in-charge parameter, map it to an
+        appropriate constant.  */
+      memset (&id, 0, sizeof (id));
+      VARRAY_TREE_INIT (id.fns, 2, "fns");
+      VARRAY_PUSH_TREE (id.fns, clone);
+      VARRAY_PUSH_TREE (id.fns, fn);
+
+      /* Remap the parameters.  */
+      id.decl_map = splay_tree_new (splay_tree_compare_pointers,
+                                   NULL, NULL);
+      for (parmno = 0,
+            parm = DECL_ARGUMENTS (fn),
+            clone_parm = DECL_ARGUMENTS (clone);
+          parm;
+          ++parmno,
+            parm = TREE_CHAIN (parm))
+       {
+         /* Map the in-charge parameter to an appropriate constant.  */
+         if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
+           {
+             tree in_charge;
+
+             if (DECL_COMPLETE_CONSTRUCTOR_P (clone))
+               in_charge = integer_one_node;
+             else
+               in_charge = integer_zero_node;
+
+             splay_tree_insert (id.decl_map,
+                                (splay_tree_key) parm,
+                                (splay_tree_key) in_charge);
+           }
+         /* Map other parameters to their equivalents in the cloned
+            function.  */
+         else
+           {
+             splay_tree_insert (id.decl_map,
+                                (splay_tree_key) parm,
+                                (splay_tree_value) clone_parm);
+             clone_parm = TREE_CHAIN (clone_parm);
+           }
+       }
+
+      /* Actually copy the body.  */
+      TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
+
+      /* Clean up.  */
+      splay_tree_delete (id.decl_map);
+      VARRAY_FREE (id.fns);
+
+      /* Now, expand this function into RTL, if appropriate.  */
+      current_function_name_declared = 1;
+      expand_body (finish_function (0));
+      pop_from_top_level ();
+    }
+  
+  /* We don't need to process the original function any further.  */
+  return 1;
+}
index 0e3277e..caf84c8 100644 (file)
@@ -159,6 +159,7 @@ static int template_args_equal PARAMS ((tree, tree));
 static void print_template_context PARAMS ((int));
 static void tsubst_default_arguments PARAMS ((tree));
 static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
+static tree instantiate_clone PARAMS ((tree, tree));
 
 /* Called once to initialize pt.c.  */
 
@@ -5708,6 +5709,13 @@ tsubst_decl (t, args, type, in_decl)
        DECL_PENDING_INLINE_INFO (r) = 0;
        DECL_PENDING_INLINE_P (r) = 0;
        TREE_USED (r) = 0;
+       if (DECL_CLONED_FUNCTION (r))
+         {
+           DECL_CLONED_FUNCTION (r) = tsubst (DECL_CLONED_FUNCTION (t),
+                                              args, /*complain=*/1, t);
+           TREE_CHAIN (r) = TREE_CHAIN (DECL_CLONED_FUNCTION (r));
+           TREE_CHAIN (DECL_CLONED_FUNCTION (r)) = r;
+         }
 
        /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
           name.  There's no need to do this in the special friend
@@ -7367,6 +7375,43 @@ tsubst_expr (t, args, complain, in_decl)
   return NULL_TREE;
 }
 
+/* TMPL is a TEMPLATE_DECL for a cloned constructor or destructor.
+   Instantiate it with the ARGS.  */
+
+static tree
+instantiate_clone (tmpl, args)
+     tree tmpl;
+     tree args;
+{
+  tree spec;
+  tree clone;
+
+  /* Instantiated the cloned function, rather than the clone.  */
+  spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), args);
+
+  /* Then, see if we've already cloned the instantiation.  */
+  for (clone = TREE_CHAIN (spec);
+       clone && DECL_CLONED_FUNCTION_P (clone);
+       clone = TREE_CHAIN (clone))
+    if (DECL_NAME (clone) == DECL_NAME (tmpl))
+      return clone;
+
+  /* If we haven't, do so know.  */
+  if (!clone)
+    clone_function_decl (spec, /*update_method_vec_p=*/0);
+
+  /* Look again.  */
+  for (clone = TREE_CHAIN (spec);
+       clone && DECL_CLONED_FUNCTION_P (clone);
+       clone = TREE_CHAIN (clone))
+    if (DECL_NAME (clone) == DECL_NAME (tmpl))
+      return clone;
+
+  /* We should always have found the clone by now.  */
+  my_friendly_abort (20000411);
+  return NULL_TREE;
+}
+
 /* Instantiate the indicated variable or function template TMPL with
    the template arguments in TARG_PTR.  */
 
@@ -7385,6 +7430,10 @@ instantiate_template (tmpl, targ_ptr)
 
   my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
 
+  /* If this function is a clone, handle it specially.  */
+  if (DECL_CLONED_FUNCTION_P (tmpl))
+    return instantiate_clone (tmpl, targ_ptr);
+
   /* Check to see if we already have this specialization.  */
   spec = retrieve_specialization (tmpl, targ_ptr);
   if (spec != NULL_TREE)
@@ -9389,6 +9438,11 @@ instantiate_decl (d, defer_ok)
   my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
                      || TREE_CODE (d) == VAR_DECL, 0);
 
+  /* Don't instantiate cloned functions.  Instead, instantiate the
+     functions they cloned.  */
+  if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
+    d = DECL_CLONED_FUNCTION (d);
+
   if (DECL_TEMPLATE_INSTANTIATED (d))
     /* D has already been instantiated.  It might seem reasonable to
        check whether or not D is an explict instantiation, and, if so,
@@ -9935,7 +9989,7 @@ set_mangled_name_for_template_decl (decl)
     = build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
                                tparms, targs, 
                                DECL_FUNCTION_MEMBER_P (decl) 
-                               + DECL_CONSTRUCTOR_P (decl));
+                               + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
 
   /* Restore the previously active namespace.  */
   current_namespace = saved_namespace;
index fda652d..7ca43b3 100644 (file)
@@ -1688,13 +1688,16 @@ lookup_fnfields_1 (type, name)
 
       /* Constructors are first...  */
       if (name == ctor_identifier)
-       return methods[0] ? 0 : -1;
-
+       return (methods[CLASSTYPE_CONSTRUCTOR_SLOT] 
+               ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
       /* and destructors are second.  */
       if (name == dtor_identifier)
-       return methods[1] ? 1 : -1;
+       return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
+               ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
 
-      for (i = 2; i < len && methods[i]; ++i)
+      for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; 
+          i < len && methods[i]; 
+          ++i)
        {
 #ifdef GATHER_STATISTICS
          n_outer_fields_searched++;
@@ -1737,7 +1740,9 @@ lookup_fnfields_1 (type, name)
         above so that we will always find specializations first.)  */
       if (IDENTIFIER_TYPENAME_P (name)) 
        {
-         for (i = 2; i < len && methods[i]; ++i)
+         for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; 
+              i < len && methods[i]; 
+              ++i)
            {
              tmp = OVL_CURRENT (methods[i]);
              if (! DECL_CONV_FN_P (tmp))
index e7fcb63..8b9bfac 100644 (file)
@@ -2717,6 +2717,16 @@ expand_body (fn)
   /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs.  */
   walk_tree (&DECL_SAVED_TREE (fn), simplify_aggr_init_exprs_r, NULL);
 
+  /* If this is a constructor or destructor body, we have to clone it
+     under the new ABI.  */
+  if (maybe_clone_body (fn))
+    {
+      /* We don't want to process FN again, so pretend we've written
+        it out, even though we haven't.  */
+      TREE_ASM_WRITTEN (fn) = 1;
+      return;
+    }
+
   /* There's no reason to do any of the work here if we're only doing
      semantic analysis; this code just generates RTL.  */
   if (flag_syntax_only)