]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Finish implementation of VTTs.
authorMark Mitchell <mark@codesourcery.com>
Thu, 25 May 2000 23:27:18 +0000 (23:27 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 25 May 2000 23:27:18 +0000 (23:27 +0000)
* cp-tree.h (cp_tree_index): Add CPTI_VTT_PARM_TYPE and
CPTI_VTT_PARM_IDENTIFIER.
(vtt_parm_identifier): New macro.
(vtt_parm_type): Likewise.
(BINFO_SUBVTT_INDEX): Likewise.
(BINFO_VPTR_INDEX): Likewise.
(struct lang_decl): Add vtt_parm.
(DECL_VTT_PARM): New macro.
(DECL_USE_VTT_PARM): Likewise.
(DECL_NEEDS_VTT_PARM_P): Likewise.
(get_vtt_name): Declare.
(build_artifical_parm): Likewise.
(fixup_all_virtual_upcast_offsets): Likewise.
(expand_indirect_vtbls_init): Remove.
* call.c (build_new_method_call): Pass the vtt to subobject
constructors and destructors.
* class.c (get_vtt_name): Give it external linkage.
(build_clone): Handle the magic VTT parameters for clones.
(clone_function_decl): Fix typo in comment.
(build_vtt): Keep track of the indices in the VTTs where various
entities are stored.
(build_vtt_inits): Likewise.
(dfs_build_vtt_inits): Likewise.
(build_ctor_vtbl_group): Tweak type of construction vtables.
(dfs_accumulate_vtbl_inits): Build vtables for all bases, even
primary bases, when building construction vtables.
* decl.c (duplicate_decls): Handle DECL_VTT_PARM.
(initialize_predefined_identifiers): Add vtt_parm_identifier.
(init_decl_processing): Initialize vtt_parm_type.
(grokfndecl): Use DECL_OVERLOADED_OPERATOR_P.
(lang_mark_tree): Make vtt_parm.
* decl2.c (build_artificial_parm): New function.
(maybe_retrofit_in_chrg): Use it.  Add VTT parameters.
(grokclassfn): Use build_artificial_parm.
* init.c (initialize_vtbl_ptrs): Call
fixup_all_virtual_upcast_offsets directly.
(perform_member_init): Use the complete subobject destructor for
member cleanups.
(build_vtbl_address): New function.
(expand_virtual_init): Handle VTTs.
* optimize (maybe_clone_body): Likewise.
* search.c (fixup_all_virtual_upcast_offsets): Give it external
linkage.
(expand_indirect_vtbls_init): Remove.
* semantics.c (setup_vtbl_ptr): Fix typos in comment.
* tree.c (make_binfo): Make them bigger.

From-SVN: r34177

13 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/init.c
gcc/cp/optimize.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/g++.old-deja/g++.other/vbase1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/vbase2.C [new file with mode: 0644]

index db9cb15afe7ad935ee75a4685934eb5530cdff87..33d02bed58446b3966044d290075dbafa8f3dc42 100644 (file)
@@ -1,3 +1,53 @@
+2000-05-25  Mark Mitchell  <mark@codesourcery.com>
+
+       Finish implementation of VTTs.
+       * cp-tree.h (cp_tree_index): Add CPTI_VTT_PARM_TYPE and
+       CPTI_VTT_PARM_IDENTIFIER.
+       (vtt_parm_identifier): New macro.
+       (vtt_parm_type): Likewise.
+       (BINFO_SUBVTT_INDEX): Likewise.
+       (BINFO_VPTR_INDEX): Likewise.
+       (struct lang_decl): Add vtt_parm.
+       (DECL_VTT_PARM): New macro.
+       (DECL_USE_VTT_PARM): Likewise.
+       (DECL_NEEDS_VTT_PARM_P): Likewise.
+       (get_vtt_name): Declare.
+       (build_artifical_parm): Likewise.
+       (fixup_all_virtual_upcast_offsets): Likewise.
+       (expand_indirect_vtbls_init): Remove.
+       * call.c (build_new_method_call): Pass the vtt to subobject
+       constructors and destructors.
+       * class.c (get_vtt_name): Give it external linkage.
+       (build_clone): Handle the magic VTT parameters for clones.
+       (clone_function_decl): Fix typo in comment.
+       (build_vtt): Keep track of the indices in the VTTs where various
+       entities are stored.
+       (build_vtt_inits): Likewise.
+       (dfs_build_vtt_inits): Likewise.
+       (build_ctor_vtbl_group): Tweak type of construction vtables.
+       (dfs_accumulate_vtbl_inits): Build vtables for all bases, even
+       primary bases, when building construction vtables.
+       * decl.c (duplicate_decls): Handle DECL_VTT_PARM.
+       (initialize_predefined_identifiers): Add vtt_parm_identifier.
+       (init_decl_processing): Initialize vtt_parm_type.
+       (grokfndecl): Use DECL_OVERLOADED_OPERATOR_P.
+       (lang_mark_tree): Make vtt_parm.
+       * decl2.c (build_artificial_parm): New function.
+       (maybe_retrofit_in_chrg): Use it.  Add VTT parameters.
+       (grokclassfn): Use build_artificial_parm.
+       * init.c (initialize_vtbl_ptrs): Call
+       fixup_all_virtual_upcast_offsets directly.
+       (perform_member_init): Use the complete subobject destructor for
+       member cleanups.
+       (build_vtbl_address): New function.
+       (expand_virtual_init): Handle VTTs.
+       * optimize (maybe_clone_body): Likewise.
+       * search.c (fixup_all_virtual_upcast_offsets): Give it external
+       linkage.
+       (expand_indirect_vtbls_init): Remove.
+       * semantics.c (setup_vtbl_ptr): Fix typos in comment.
+       * tree.c (make_binfo): Make them bigger.
+       
 2000-05-25  Nathan Sidwell  <nathan@codesourcery.com>
 
        * inc/cxxabi.h (__pbase_type_info): Define, based on
index 93feaddd9e26629f6df1414991963289c1f5d9e6..a034f5292a64031ae0ced5416dff40463f68e17f 100644 (file)
@@ -4321,6 +4321,32 @@ build_new_method_call (instance, name, args, basetype_path, flags)
             old ABI.  */
          name = constructor_p ? ctor_identifier : dtor_identifier;
        }
+      /* If we're call a subobject constructor or destructor for a
+        subobject that uses virtual base classes, then we need to
+        pass down a pointer to a VTT for the subobject.  */
+      else if ((name == base_ctor_identifier
+               || name == base_dtor_identifier)
+              && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+       {
+         tree vtt;
+         tree sub_vtt;
+
+         /* If the current function is a complete object constructor
+            or destructor, then we fetch the VTT directly.
+            Otherwise, we look it up using the VTT we were given.  */
+         vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
+         vtt = build_unary_op (ADDR_EXPR, vtt, /*noconvert=*/1);
+         vtt = build (COND_EXPR, TREE_TYPE (vtt), 
+                      DECL_USE_VTT_PARM (current_function_decl),
+                      DECL_VTT_PARM (current_function_decl),
+                      vtt);
+
+         sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
+                          BINFO_SUBVTT_INDEX (basetype_path));
+         sub_vtt = build_indirect_ref (sub_vtt, NULL);
+
+         args = tree_cons (NULL_TREE, sub_vtt, args);
+       }
     }
   else
     pretty_name = name;
index b86bac460c0688448718ded39a72cee9aefc69e7..d865fba5f9912282742545b1c210231c66c4990e 100644 (file)
@@ -181,7 +181,7 @@ static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
 static tree copy_virtuals PARAMS ((tree));
 static void build_ctor_vtbl_group PARAMS ((tree, tree));
 static void build_vtt PARAMS ((tree));
-static tree *build_vtt_inits PARAMS ((tree, tree, tree *));
+static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
 static tree dfs_build_vtt_inits PARAMS ((tree, void *));
 static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
 
@@ -635,7 +635,7 @@ get_vtable_name (type)
 /* Return an IDENTIFIER_NODE for the name of the virtual table table
    for TYPE.  */
 
-static tree
+tree
 get_vtt_name (type)
      tree type;
 {
@@ -3957,6 +3957,8 @@ build_clone (fn, name)
   DECL_PENDING_INLINE_P (clone) = 0;
   /* And it hasn't yet been deferred.  */
   DECL_DEFERRED_FN (clone) = 0;
+  /* There's no magic VTT parameter in the clone.  */
+  DECL_VTT_PARM (clone) = NULL_TREE;
 
   /* The base-class destructor is not virtual.  */
   if (name == base_dtor_identifier)
@@ -3981,6 +3983,10 @@ build_clone (fn, name)
       parmtypes = TREE_CHAIN (parmtypes);
       /* Skip the in-charge parameter.  */
       parmtypes = TREE_CHAIN (parmtypes);
+       /* If this is subobject constructor or destructor, add the vtt
+        parameter.  */
+      if (DECL_NEEDS_VTT_PARM_P (clone))
+       parmtypes = hash_tree_chain (vtt_parm_type, parmtypes);
       TREE_TYPE (clone) 
        = build_cplus_method_type (basetype,
                                   TREE_TYPE (TREE_TYPE (clone)),
@@ -4002,6 +4008,18 @@ build_clone (fn, name)
            = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
          DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
        }
+
+      /* Add the VTT parameter.  */
+      if (DECL_NEEDS_VTT_PARM_P (clone))
+       {
+         tree parm;
+
+         parm = build_artificial_parm (vtt_parm_identifier,
+                                       vtt_parm_type);
+         TREE_CHAIN (parm) = TREE_CHAIN (DECL_ARGUMENTS (clone));
+         TREE_CHAIN (DECL_ARGUMENTS (clone)) = parm;
+       }
+
       for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
        {
          DECL_CONTEXT (parms) = clone;
@@ -4063,7 +4081,7 @@ clone_function_decl (fn, update_method_vec_p)
     {
       my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
 
-      /* For each destructor, we need two variants: an in-charge
+      /* For each destructor, we need three variants: an in-charge
         version, a not-in-charge version, and an in-charge deleting
         version.  We clone the deleting version first because that
         means it will go second on the TYPE_METHODS list -- and that
@@ -6474,6 +6492,7 @@ build_vtt (t)
   tree inits;
   tree type;
   tree vtt;
+  tree index;
 
   /* Under the old ABI, we don't use VTTs.  */
   if (!flag_new_abi)
@@ -6481,7 +6500,8 @@ build_vtt (t)
 
   /* Build up the initializers for the VTT.  */
   inits = NULL_TREE;
-  build_vtt_inits (TYPE_BINFO (t), t, &inits);
+  index = size_zero_node;
+  build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
 
   /* If we didn't need a VTT, we're done.  */
   if (!inits)
@@ -6499,13 +6519,15 @@ build_vtt (t)
 
 /* Recursively build the VTT-initializer for BINFO (which is in the
    hierarchy dominated by T).  INITS points to the end of the
-   initializer list to date.  */
+   initializer list to date.  INDEX is the VTT index where the next
+   element will be placed.  */
 
 static tree *
-build_vtt_inits (binfo, t, inits)
+build_vtt_inits (binfo, t, inits, index)
      tree binfo;
      tree t;
      tree *inits;
+     tree *index;
 {
   int i;
   tree b;
@@ -6521,7 +6543,12 @@ build_vtt_inits (binfo, t, inits)
      VTT.  */
   ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
   if (ctor_vtbl_p)
-    build_ctor_vtbl_group (binfo, t);
+    {
+      build_ctor_vtbl_group (binfo, t);
+
+      /* Record the offset in the VTT where this sub-VTT can be found.  */
+      BINFO_SUBVTT_INDEX (binfo) = *index;
+    }
 
   /* Add the address of the primary vtable for the complete object.  */
   init = BINFO_VTABLE (binfo);
@@ -6529,20 +6556,24 @@ build_vtt_inits (binfo, t, inits)
     init = TREE_PURPOSE (init);
   *inits = build_tree_list (NULL_TREE, init);
   inits = &TREE_CHAIN (*inits);
-
+  BINFO_VPTR_INDEX (binfo) = *index;
+  *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
+                      
   /* Recursively add the secondary VTTs for non-virtual bases.  */
   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
     {
       b = BINFO_BASETYPE (binfo, i);
       if (!TREE_VIA_VIRTUAL (b))
-       inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits);
+       inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits,
+                                index);
     }
-
+      
   /* Add secondary virtual pointers for all subobjects of BINFO with
      either virtual bases or virtual functions overridden along a
      virtual path between the declaration and D, except subobjects
      that are non-virtual primary bases.  */
   secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
+  TREE_TYPE (secondary_vptrs) = *index;
   dfs_walk_real (binfo,
                 dfs_build_vtt_inits,
                 NULL,
@@ -6550,6 +6581,7 @@ build_vtt_inits (binfo, t, inits)
                 secondary_vptrs);
   dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
            BINFO_TYPE (binfo));
+  *index = TREE_TYPE (secondary_vptrs);
 
   /* The secondary vptrs come back in reverse order.  After we reverse
      them, and add the INITS, the last init will be the first element
@@ -6571,7 +6603,7 @@ build_vtt_inits (binfo, t, inits)
        continue;
 
       vbase = binfo_for_vbase (BINFO_TYPE (b), t);
-      inits = build_vtt_inits (vbase, t, inits);
+      inits = build_vtt_inits (vbase, t, inits, index);
     }
 
   return inits;
@@ -6587,6 +6619,7 @@ dfs_build_vtt_inits (binfo, data)
   tree l; 
   tree t;
   tree init;
+  tree index;
 
   l = (tree) data;
   t = TREE_PURPOSE (l);
@@ -6612,13 +6645,18 @@ dfs_build_vtt_inits (binfo, data)
     /* FIXME: Implement this.  */
     ;
 
-  /* Add the initializer for this secondary vptr.  */
+  /* Record the index where this secondary vptr can be found.  */
+  index = TREE_TYPE (l);
+  BINFO_VPTR_INDEX (binfo) = index;
+  TREE_TYPE (l) = size_binop (PLUS_EXPR, index, 
+                             TYPE_SIZE_UNIT (ptr_type_node));
+
+  /* Add the initializer for the secondary vptr itself.  */
   init = BINFO_VTABLE (binfo);
   if (TREE_CODE (init) == TREE_LIST)
     init = TREE_PURPOSE (init);
-
   TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
-  
+
   return NULL_TREE;
 }
 
@@ -6665,7 +6703,7 @@ build_ctor_vtbl_group (binfo, t)
   /* Build a version of VTBL (with the wrong type) for use in
      constructing the addresses of secondary vtables in the
      construction vtable group.  */
-  vtbl = build_vtable (BINFO_TYPE (binfo), id, vtable_entry_type);
+  vtbl = build_vtable (BINFO_TYPE (binfo), id, ptr_type_node);
   list = build_tree_list (vtbl, NULL_TREE);
   accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
                         binfo, t, list);
@@ -6762,7 +6800,7 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
   if (BINFO_NEW_VTABLE_MARKED (binfo, t)
       /* We need a new vtable, even for a primary base, when we're
         building a construction vtable.  */
-      || (ctor_vtbl_p && orig_binfo == rtti_binfo))
+      || (ctor_vtbl_p && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))))
     {
       tree vtbl;
       tree index;
index 6080abde32ad0e710b07c6bc3d212e410f458350..d935c351c93814e94576d876b01389866d658dc4 100644 (file)
@@ -530,6 +530,7 @@ enum cp_tree_index
     CPTI_DELTA_TYPE,
     CPTI_VTABLE_INDEX_TYPE,
     CPTI_CLEANUP_TYPE,
+    CPTI_VTT_PARM_TYPE,
 
     CPTI_TI_DESC_TYPE,
     CPTI_BLTN_DESC_TYPE,
@@ -578,6 +579,7 @@ enum cp_tree_index
     CPTI_DELTA2_IDENTIFIER,
     CPTI_DELTA_IDENTIFIER,
     CPTI_IN_CHARGE_IDENTIFIER,
+    CPTI_VTT_PARM_IDENTIFIER,
     CPTI_INDEX_IDENTIFIER,
     CPTI_NELTS_IDENTIFIER,
     CPTI_THIS_IDENTIFIER,
@@ -690,6 +692,11 @@ extern tree cp_global_trees[CPTI_MAX];
 #define delta2_identifier               cp_global_trees[CPTI_DELTA2_IDENTIFIER]
 #define delta_identifier                cp_global_trees[CPTI_DELTA_IDENTIFIER]
 #define in_charge_identifier            cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER]
+
+/* The name of the parameter that contains a pointer to the VTT to use
+   for this subobject constructor or destructor.  */
+#define vtt_parm_identifier             cp_global_trees[CPTI_VTT_PARM_IDENTIFIER]
+
 #define index_identifier                cp_global_trees[CPTI_INDEX_IDENTIFIER]
 #define nelts_identifier                cp_global_trees[CPTI_NELTS_IDENTIFIER]
 #define this_identifier                 cp_global_trees[CPTI_THIS_IDENTIFIER]
@@ -731,6 +738,10 @@ extern tree cp_global_trees[CPTI_MAX];
 /* The type of a destructor.  */
 #define cleanup_type                    cp_global_trees[CPTI_CLEANUP_TYPE]
 
+/* The type of the vtt parameter passed to subobject constructors and
+   destructors.  */
+#define vtt_parm_type                   cp_global_trees[CPTI_VTT_PARM_TYPE]
+
 /* Global state.  */
 
 struct stmt_tree {
@@ -1755,6 +1766,14 @@ struct lang_type
    is primary *somewhere* in the hierarchy.  */
 #define BINFO_VBASE_PRIMARY_P(NODE) TREE_LANG_FLAG_6 (NODE)
 
+/* The index in the VTT where this subobject's sub-VTT can be found.
+   NULL_TREE if there is no sub-VTT.  */
+#define BINFO_SUBVTT_INDEX(NODE) TREE_VEC_ELT ((NODE), 8)
+
+/* The index in the VTT where the vptr for this subobject can be
+   found.  NULL_TREE if there is no secondary vptr in the VTT.  */
+#define BINFO_VPTR_INDEX(NODE) TREE_VEC_ELT ((NODE), 9)
+
 /* Used by various search routines.  */
 #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
 \f
@@ -1884,6 +1903,9 @@ struct lang_decl
   /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
   tree cloned_function;
 
+  /* In a FUNCTION_DECL, this is VTT_PARM.  */
+  tree vtt_parm;
+
   union
   {
     tree sorted_fields;
@@ -1972,6 +1994,25 @@ struct lang_decl
 #define DECL_CLONED_FUNCTION(NODE) \
   (DECL_LANG_SPECIFIC (NODE)->cloned_function)
 
+/* In a maybe-in-charge constructor or destructor, this is the VTT
+   parameter.  It's not actually on the DECL_ARGUMENTS list.  */
+#define DECL_VTT_PARM(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->vtt_parm)
+
+/* If there's a DECL_VTT_PARM, this is a magic variable that indicates
+   whether or not the VTT parm should be used.  In a subobject
+   constructor, `true' is substituted for this value; in a complete
+   object constructor, `false' is substituted instead.  */
+#define DECL_USE_VTT_PARM(NODE) \
+  (TREE_CHAIN (DECL_VTT_PARM (NODE)))
+
+/* Non-zero if NODE is a FUNCTION_DECL for which a VTT parameter is
+   required.  */
+#define DECL_NEEDS_VTT_PARM_P(NODE)                    \
+  (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (NODE)) \
+   && (DECL_BASE_CONSTRUCTOR_P (NODE)                  \
+       || DECL_BASE_DESTRUCTOR_P (NODE)))
+
 /* Non-zero if NODE is a user-defined conversion operator.  */
 #define DECL_CONV_FN_P(NODE) \
   (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)))
@@ -3820,6 +3861,7 @@ extern void maybe_note_name_used_in_class       PARAMS ((tree, tree));
 extern void note_name_declared_in_class         PARAMS ((tree, tree));
 extern tree get_vtbl_decl_for_binfo             PARAMS ((tree));
 extern tree in_charge_arg_for_name              PARAMS ((tree));
+extern tree get_vtt_name                        PARAMS ((tree));
 
 /* in cvt.c */
 extern tree convert_to_reference               PARAMS ((tree, tree, int, int, tree));
@@ -4054,6 +4096,7 @@ extern void mark_used                             PARAMS ((tree));
 extern tree handle_class_head                  PARAMS ((tree, tree, tree));
 extern tree lookup_arg_dependent                PARAMS ((tree, tree, tree));
 extern void finish_static_data_member_decl      PARAMS ((tree, tree, tree, int));
+extern tree build_artificial_parm               PARAMS ((tree, tree));
 
 /* in parse.y */
 extern void cp_parse_init                      PARAMS ((void));
@@ -4303,7 +4346,6 @@ extern tree lookup_nested_tag                     PARAMS ((tree, tree));
 extern tree get_matching_virtual               PARAMS ((tree, tree, int));
 extern void get_pure_virtuals                  PARAMS ((tree));
 extern tree init_vbase_pointers                        PARAMS ((tree, tree));
-extern void expand_indirect_vtbls_init         PARAMS ((tree));
 extern void get_vbase_types                    PARAMS ((tree));
 extern void maybe_suppress_debug_info          PARAMS ((tree));
 extern void note_debug_info_needed             PARAMS ((tree));
@@ -4340,6 +4382,7 @@ extern tree unmarked_vtable_pathp               PARAMS ((tree, void *));
 extern tree convert_pointer_to_vbase            PARAMS ((tree, tree));
 extern tree find_vbase_instance                 PARAMS ((tree, tree));
 extern tree binfo_for_vbase                     PARAMS ((tree, tree));
+extern void fixup_all_virtual_upcast_offsets    PARAMS ((tree));
 
 /* in semantics.c */
 extern void finish_expr_stmt                    PARAMS ((tree));
index 05c17f620f09c1d619e38c7cd891cbb2cbb3f67f..5704a17217050a9e95dbc07b34cf1080a1864769 100644 (file)
@@ -3369,6 +3369,7 @@ duplicate_decls (newdecl, olddecl)
       DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
       DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
+      DECL_VTT_PARM (newdecl) = DECL_VTT_PARM (olddecl);
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
       /* Optionally warn about more than one declaration for the same
@@ -6074,6 +6075,7 @@ initialize_predefined_identifiers ()
     { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
     { "_vptr", &vptr_identifier, 0 },
     { "__cp_push_exception", &cp_push_exception_identifier, 0 },
+    { "__vtt_parm", &vtt_parm_identifier, 0 },
     { NULL, NULL, 0 }
   };
 
@@ -6325,6 +6327,7 @@ init_decl_processing ()
   const_ptr_type_node
     = build_pointer_type (build_qualified_type (void_type_node,
                                                TYPE_QUAL_CONST));
+  vtt_parm_type = build_pointer_type (const_ptr_type_node);
   c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
   lang_type_promotes_to = convert_type_from_ellipsis;
 
@@ -8740,7 +8743,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
       quals = NULL_TREE;
     }
 
-  if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
+  if (DECL_OVERLOADED_OPERATOR_P (decl))
     grok_op_properties (decl, virtualp, check < 0);
 
   if (ctype && decl_function_context (decl))
@@ -14744,6 +14747,7 @@ lang_mark_tree (t)
              ggc_mark_tree (ld->befriending_classes);
              ggc_mark_tree (ld->saved_tree);
              ggc_mark_tree (ld->cloned_function);
+             ggc_mark_tree (ld->vtt_parm);
              if (TREE_CODE (t) == TYPE_DECL)
                ggc_mark_tree (ld->u.sorted_fields);
              else if (TREE_CODE (t) == FUNCTION_DECL
index 5b7209827cc4d47ba38afea42fb9e67339f800b5..315e3c86e7b43018b425e4e030ee86c1701f1176 100644 (file)
@@ -924,6 +924,22 @@ grok_x_components (specs)
       break;
 }
 
+/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
+   indicated NAME.  */
+
+tree
+build_artificial_parm (name, type)
+     tree name;
+     tree type;
+{
+  tree parm;
+
+  parm = build_decl (PARM_DECL, name, type);
+  SET_DECL_ARTIFICIAL (parm);
+  DECL_ARG_TYPE (parm) = type;
+  return parm;
+}
+
 /* 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"
@@ -956,10 +972,7 @@ maybe_retrofit_in_chrg (fn)
     return;
 
   /* 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;
+  parm = build_artificial_parm (in_charge_identifier, integer_type_node);
   TREE_READONLY (parm) = 1;
   parms = DECL_ARGUMENTS (fn);
   TREE_CHAIN (parm) = TREE_CHAIN (parms);
@@ -978,6 +991,18 @@ maybe_retrofit_in_chrg (fn)
 
   /* Now we've got the in-charge parameter.  */
   DECL_HAS_IN_CHARGE_PARM_P (fn) = 1;
+
+  /* If this is a subobject constructor or destructor, our caller will
+     pass us a pointer to our VTT.  */
+  if (flag_new_abi && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+    {
+      DECL_VTT_PARM (fn) = build_artificial_parm (vtt_parm_identifier, 
+                                                 vtt_parm_type);
+      DECL_CONTEXT (DECL_VTT_PARM (fn)) = fn;
+      DECL_USE_VTT_PARM (fn) = build_artificial_parm (NULL_TREE,
+                                                     boolean_type_node);
+      DECL_CONTEXT (DECL_USE_VTT_PARM (fn)) = fn;
+    }
 }
 
 /* Classes overload their constituent function names automatically.
@@ -1032,12 +1057,9 @@ grokclassfn (ctype, function, flags, quals)
         assigned to.  */
       this_quals |= TYPE_QUAL_CONST;
       qual_type = cp_build_qualified_type (type, this_quals);
-      parm = build_decl (PARM_DECL, this_identifier, qual_type);
+      parm = build_artificial_parm (this_identifier, qual_type);
       c_apply_type_quals_to_decl (this_quals, parm);
 
-      /* Mark the artificial `this' parameter as "artificial".  */
-      SET_DECL_ARTIFICIAL (parm);
-      DECL_ARG_TYPE (parm) = type;
       /* We can make this a register, so long as we don't
         accidentally complain if someone tries to take its address.  */
       DECL_REGISTER (parm) = 1;
index 7d6892e232d9264eac272dd826b18b9d2ed62355..cc5be91c79efe887db4d33898e7112d955127bb5 100644 (file)
@@ -53,6 +53,7 @@ static tree build_new_1       PARAMS ((tree));
 static tree get_cookie_size PARAMS ((tree));
 static tree build_dtor_call PARAMS ((tree, special_function_kind, int));
 static tree build_field_list PARAMS ((tree, tree, int *));
+static tree build_vtbl_address PARAMS ((tree));
 
 /* Set up local variable for this file.  MUST BE CALLED AFTER
    INIT_DECL_PROCESSING.  */
@@ -172,7 +173,14 @@ initialize_vtbl_ptrs (addr)
                 NULL, dfs_unmarked_real_bases_queue_p, list);
   dfs_walk (TYPE_BINFO (type), dfs_unmark,
            dfs_marked_real_bases_queue_p, type);
-  expand_indirect_vtbls_init (addr);
+
+  /* If we're not using thunks, we may need to adjust the deltas in
+     the vtable to handle virtual base classes correctly.  When we are
+     using thunks, we either use construction vtables (which are
+     preloaded with the right answers) or nothing (in which case
+     vitual function calls sometimes don't work right.)  */
+  if (TYPE_USES_VIRTUAL_BASECLASSES (type) && !flag_vtable_thunks)
+    fixup_all_virtual_upcast_offsets (addr);
 }
 
 /* Subroutine of emit_base_init.  */
@@ -276,7 +284,7 @@ perform_member_init (member, init, explicit)
 
       expr = build_component_ref (current_class_ref, member, NULL_TREE,
                                  explicit);
-      expr = build_delete (type, expr, sfk_base_destructor,
+      expr = build_delete (type, expr, sfk_complete_destructor,
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
 
       if (expr != error_mark_node)
@@ -726,6 +734,32 @@ emit_base_init ()
     }
 }
 
+/* Returns the address of the vtable (i.e., the value that should be
+   assigned to the vptr) for BINFO.  */
+
+static tree
+build_vtbl_address (binfo)
+     tree binfo;
+{
+  tree vtbl;
+
+  /* Figure out what vtable BINFO's vtable is based on, and mark it as
+     used.  */
+  vtbl = get_vtbl_decl_for_binfo (binfo);
+  assemble_external (vtbl);
+  TREE_USED (vtbl) = 1;
+
+  /* Now compute the address to use when initializing the vptr.  */
+  vtbl = BINFO_VTABLE (binfo);
+  if (TREE_CODE (vtbl) == VAR_DECL)
+    {
+      vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+      TREE_CONSTANT (vtbl) = 1;
+    }
+
+  return vtbl;
+}
+
 /* This code sets up the virtual function tables appropriate for
    the pointer DECL.  It is a one-ply initialization.
 
@@ -739,23 +773,40 @@ expand_virtual_init (binfo, decl)
   tree type = BINFO_TYPE (binfo);
   tree vtbl, vtbl_ptr;
   tree vtype, vtype_binfo;
-  tree b;
+  tree vtt_index;
 
   /* Compute the location of the vtable.  */
   vtype = DECL_CONTEXT (TYPE_VFIELD (type));
   vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
-  b = binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo);
-
-  /* Figure out what vtable BINFO's vtable is based on, and mark it as
-     used.  */
-  vtbl = get_vtbl_decl_for_binfo (b);
-  assemble_external (vtbl);
-  TREE_USED (vtbl) = 1;
-
-  /* Now compute the address to use when initializing the vptr.  */
-  vtbl = BINFO_VTABLE (b);
-  if (TREE_CODE (vtbl) == VAR_DECL)
-    vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+  
+  /* Compute the initializer for vptr.  */
+  vtbl = build_vtbl_address (binfo);
+
+  /* Under the new ABI, we may get this vptr from a VTT, if this is a
+     subobject constructor or subobject destructor.  */
+  vtt_index = BINFO_VPTR_INDEX (binfo);
+  if (vtt_index)
+    {
+      tree vtbl2;
+      tree vtt_parm;
+
+      /* Compute the value to use, when there's a VTT.  */
+      vtt_parm = DECL_VTT_PARM (current_function_decl);
+      vtbl2 = build (PLUS_EXPR, 
+                    TREE_TYPE (vtt_parm), 
+                    vtt_parm,
+                    vtt_index);
+      vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2);
+
+      /* The actual initializer is the VTT value only in the subobject
+        constructor.  In maybe_clone_body we'll substitute NULL for
+        the vtt_parm in the case of the non-subobject constructor.  */
+      vtbl = build (COND_EXPR, 
+                   TREE_TYPE (vtbl), 
+                   DECL_USE_VTT_PARM (current_function_decl),
+                   vtbl2, 
+                   vtbl);
+    }
 
   /* Compute the location of the vtpr.  */
   decl = convert_pointer_to_real (vtype_binfo, decl);
index b7711d6e02eb9aaf6ec2fcb56ce46b56b2d48f51..52292ffbcf1929a426f9c62fe8607508b576e5f2 100644 (file)
@@ -902,6 +902,10 @@ maybe_clone_body (fn)
       DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
       DECL_INLINE (clone) = DECL_INLINE (fn);
       DECL_THIS_INLINE (clone) = DECL_THIS_INLINE (fn);
+      DECL_COMDAT (clone) = DECL_COMDAT (fn);
+      DECL_WEAK (clone) = DECL_WEAK (fn);
+      DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn);
+      DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
 
       /* Start processing the function.  */
       push_to_top_level ();
@@ -934,7 +938,31 @@ maybe_clone_body (fn)
              in_charge = in_charge_arg_for_name (DECL_NAME (clone));
              splay_tree_insert (id.decl_map,
                                 (splay_tree_key) parm,
-                                (splay_tree_key) in_charge);
+                                (splay_tree_value) in_charge);
+
+             /* For a subobject constructor or destructor, the next
+                argument is the VTT parameter.  Remap the VTT_PARM
+                from the CLONE to this parameter.  */
+             if (DECL_NEEDS_VTT_PARM_P (clone))
+               {
+                 splay_tree_insert (id.decl_map,
+                                    (splay_tree_key) DECL_VTT_PARM (fn),
+                                    (splay_tree_value) clone_parm);
+                 splay_tree_insert (id.decl_map,
+                                    (splay_tree_key) DECL_USE_VTT_PARM (fn),
+                                    (splay_tree_value) boolean_true_node);
+                 clone_parm = TREE_CHAIN (clone_parm);
+               }
+             /* Otherwise, map the VTT parameter to `NULL'.  */
+             else if (DECL_VTT_PARM (fn))
+               {
+                 splay_tree_insert (id.decl_map,
+                                    (splay_tree_key) DECL_VTT_PARM (fn),
+                                    (splay_tree_value) null_pointer_node);
+                 splay_tree_insert (id.decl_map,
+                                    (splay_tree_key) DECL_USE_VTT_PARM (fn),
+                                    (splay_tree_value) boolean_false_node);
+               }
            }
          /* Map other parameters to their equivalents in the cloned
             function.  */
index bebca052a5def8f8d8c5208e80299347d97b525a..1160cd4b6a0a0d3f6a5f7cccc4b8d506e81c4e4b 100644 (file)
@@ -144,7 +144,6 @@ static int protected_accessible_p PARAMS ((tree, tree, tree));
 static int friend_accessible_p PARAMS ((tree, tree, tree));
 static void setup_class_bindings PARAMS ((tree, int));
 static int template_self_reference_p PARAMS ((tree, tree));
-static void fixup_all_virtual_upcast_offsets PARAMS ((tree, tree));
 static tree get_shared_vbase_if_not_primary PARAMS ((tree, void *));
 static tree dfs_find_vbase_instance PARAMS ((tree, void *));
 static tree dfs_get_pure_virtuals PARAMS ((tree, void *));
@@ -2770,14 +2769,14 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
 /* Fixup all the virtual upcast offsets for TYPE.  DECL_PTR is the
    address of the sub-object being initialized.  */
 
-static void
-fixup_all_virtual_upcast_offsets (type, decl_ptr)
-     tree type;
+void
+fixup_all_virtual_upcast_offsets (decl_ptr)
      tree decl_ptr;
 {
   tree if_stmt;
   tree in_charge_node;
   tree vbases;
+  tree type;
 
   /* Only tweak the vtables if we're in charge.  */
   in_charge_node = current_in_charge_parm;
@@ -2791,6 +2790,7 @@ fixup_all_virtual_upcast_offsets (type, decl_ptr)
   
   /* Iterate through the virtual bases, fixing up the upcast offset
      for each one.  */
+  type = TREE_TYPE (TREE_TYPE (decl_ptr));
   for (vbases = CLASSTYPE_VBASECLASSES (type);
        vbases;
        vbases = TREE_CHAIN (vbases))
@@ -2820,22 +2820,6 @@ fixup_all_virtual_upcast_offsets (type, decl_ptr)
   finish_if_stmt ();
 }
 
-/* Generate the code needed to initialize all the virtual function
-   table slots of all the virtual baseclasses.  ADDR points to the
-   address of the complete object we are initializing.  */
-
-void
-expand_indirect_vtbls_init (addr)
-     tree addr;
-{
-  tree type;
-
-  type = TREE_TYPE (TREE_TYPE (addr));
-
-  if (TYPE_USES_VIRTUAL_BASECLASSES (type))
-    fixup_all_virtual_upcast_offsets (type, addr);
-}
-
 /* get virtual base class types.
    This adds type to the vbase_types list in reverse dfs order.
    Ordering is very important, so don't change it.  */
index dbeb7f109f3dfd510d0df16696108c39ecdf94df..77728ba40c7a519d2e0a61391954f46d6b2091b6 100644 (file)
@@ -1257,15 +1257,15 @@ setup_vtbl_ptr ()
       tree compound_stmt;
       int saved_cfnd;
 
-      /* If the dtor is empty, and we know there is not possible way we
-        could use any vtable entries, before they are possibly set by
-        a base class dtor, we don't have to setup the vtables, as we
-        know that any base class dtoring will set up any vtables it
-        needs.  We avoid MI, because one base class dtor can do a
+      /* If the dtor is empty, and we know there is not any possible
+        way we could use any vtable entries, before they are possibly
+        set by a base class dtor, we don't have to setup the vtables,
+        as we know that any base class dtor will set up any vtables
+        it needs.  We avoid MI, because one base class dtor can do a
         virtual dispatch to an overridden function that would need to
         have a non-related vtable set up, we cannot avoid setting up
-        vtables in that case.  We could change this to see if there is
-        just one vtable.  */
+        vtables in that case.  We could change this to see if there
+        is just one vtable.  */
       if_stmt = begin_if_stmt ();
 
       /* If it is not safe to avoid setting up the vtables, then
index 078558ebd96a3f0bd58bd375020ea5c6aacbd279..646a892fe79bc76cf4d3a228741bcdb7cab294df 100644 (file)
@@ -847,7 +847,7 @@ make_binfo (offset, binfo, vtable, virtuals)
      tree offset, binfo;
      tree vtable, virtuals;
 {
-  tree new_binfo = make_tree_vec (8);
+  tree new_binfo = make_tree_vec (10);
   tree type;
 
   if (TREE_CODE (binfo) == TREE_VEC)
diff --git a/gcc/testsuite/g++.old-deja/g++.other/vbase1.C b/gcc/testsuite/g++.old-deja/g++.other/vbase1.C
new file mode 100644 (file)
index 0000000..99a3867
--- /dev/null
@@ -0,0 +1,51 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+// Special g++ Options: -w
+
+int result;
+
+struct A {
+  A ();
+
+  int i;
+};
+
+A* ap;
+
+A::A ()
+{
+  ap = this;
+}
+
+struct B : virtual public A
+{
+  B ();
+  ~B ();
+
+  int j;
+};
+
+B::B () {
+  if ((A*) this != ap)
+    result = 1;
+}
+
+B::~B () {
+  if ((A*) this != ap)
+    result = 1;
+}
+
+struct C : public B {
+};
+
+struct D : public C, public B
+{
+};
+
+int main ()
+{
+  {
+    D d;
+  }
+
+  return result;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/vbase2.C b/gcc/testsuite/g++.old-deja/g++.other/vbase2.C
new file mode 100644 (file)
index 0000000..2f15249
--- /dev/null
@@ -0,0 +1,36 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+int i;
+
+struct A
+{
+  ~A ();
+};
+
+A::~A () {
+  i = 1;
+}
+
+struct B : virtual public A {
+};
+
+struct C {
+  C ();
+
+  B b;
+};
+
+C::C () {
+  throw 3;
+}
+
+int main () 
+{
+  try { 
+    C c;
+  } catch (...) {
+  }
+
+  if (i != 1)
+    return 1;
+}