* class.c (build_vtbl_initializer): Don't use build_vtable_entry.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Oct 2002 19:39:47 +0000 (19:39 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Oct 2002 19:39:47 +0000 (19:39 +0000)
(build_vtable_entry): Remove.
* cp-tree.h (BINFO_VIRTUALS): Expand documentation.
(lang_decl): Add thunks.
(DECL_THUNKS): New macro.
* decl.c (duplicate_decls): Copy it.
* method.c (make_thunk): Simplify, and add thunks to DECL_THUNKS.
* semantics.c (emit_associated_thunks): Simplify.

* g++.dg/abi/vthunk2.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/method.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/vthunk2.C [new file with mode: 0644]

index 119bdc1..35251df 100644 (file)
@@ -1,3 +1,14 @@
+2002-10-25  Mark Mitchell  <mark@codesourcery.com>
+
+       * class.c (build_vtbl_initializer): Don't use build_vtable_entry.
+       (build_vtable_entry): Remove.
+       * cp-tree.h (BINFO_VIRTUALS): Expand documentation.
+       (lang_decl): Add thunks.
+       (DECL_THUNKS): New macro.
+       * decl.c (duplicate_decls): Copy it.
+       * method.c (make_thunk): Simplify, and add thunks to DECL_THUNKS.
+       * semantics.c (emit_associated_thunks): Simplify.
+       
 2002-10-24  David Edelsohn  <edelsohn@gnu.org>
 
        PR c++/7228
index f4b9beb..a11ad7b 100644 (file)
@@ -103,7 +103,6 @@ varray_type local_classes;
 
 static tree get_vfield_name PARAMS ((tree));
 static void finish_struct_anon PARAMS ((tree));
-static tree build_vtable_entry PARAMS ((tree, tree, tree));
 static tree get_vtable_name PARAMS ((tree));
 static tree get_basefndecls PARAMS ((tree, tree));
 static int build_primary_vtable PARAMS ((tree, tree));
@@ -7673,7 +7672,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
       tree delta;
       tree vcall_index;
       tree fn;
-      tree pfn;
       tree init = NULL_TREE;
       
       fn = BV_FN (v);
@@ -7724,15 +7722,13 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
             So, we replace these functions with __pure_virtual.  */
          if (DECL_PURE_VIRTUAL_P (fn))
            fn = abort_fndecl;
-
+         else if (!integer_zerop (delta) || vcall_index)
+           fn = make_thunk (fn, delta, vcall_index);
          /* Take the address of the function, considering it to be of an
             appropriate generic type.  */
-         pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
+         init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
          /* The address of a function can't change.  */
-         TREE_CONSTANT (pfn) = 1;
-
-         /* Enter it in the vtable.  */
-         init = build_vtable_entry (delta, vcall_index, pfn);
+         TREE_CONSTANT (init) = 1;
        }
 
       /* And add it to the chain of initializers.  */
@@ -8164,33 +8160,3 @@ build_rtti_vtbl_entries (binfo, vid)
   *vid->last_init = build_tree_list (NULL_TREE, init);
   vid->last_init = &TREE_CHAIN (*vid->last_init);
 }
-
-/* Build an entry in the virtual function table.  DELTA is the offset
-   for the `this' pointer.  VCALL_INDEX is the vtable index containing
-   the vcall offset; NULL_TREE if none.  ENTRY is the virtual function
-   table entry itself.  It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
-   but it may not actually be a virtual function table pointer.  (For
-   example, it might be the address of the RTTI object, under the new
-   ABI.)  */
-
-static tree
-build_vtable_entry (delta, vcall_index, entry)
-     tree delta;
-     tree vcall_index;
-     tree entry;
-{
-  tree fn = TREE_OPERAND (entry, 0);
-  
-  if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
-      && fn != abort_fndecl)
-    {
-      entry = make_thunk (entry, delta, vcall_index);
-      entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
-      TREE_READONLY (entry) = 1;
-      TREE_CONSTANT (entry) = 1;
-    }
-#ifdef GATHER_STATISTICS
-  n_vtable_entries += 1;
-#endif
-  return entry;
-}
index 40c4ab5..5b30d39 100644 (file)
@@ -121,11 +121,15 @@ struct diagnostic_context;
      For a FUNCTION_TYPE or METHOD_TYPE, this is TYPE_RAISES_EXCEPTIONS
 
   BINFO_VIRTUALS
-     For a binfo, this is a TREE_LIST.  The BV_DELTA of each node
-     gives the amount by which to adjust the `this' pointer when
-     calling the function.  If the method is an overriden version of a
-     base class method, then it is assumed that, prior to adjustment,
-     the this pointer points to an object of the base class.
+     For a binfo, this is a TREE_LIST.  There is an entry for each
+     virtual function declared either in BINFO or its direct and
+     indirect primary bases.
+
+     The BV_DELTA of each node gives the amount by which to adjust the
+     `this' pointer when calling the function.  If the method is an
+     overriden version of a base class method, then it is assumed
+     that, prior to adjustment, the this pointer points to an object
+     of the base class.
 
      The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable
      index of the vcall offset for this entry.  If
@@ -1766,6 +1770,10 @@ struct lang_decl GTY(())
           non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT.  */
        tree context;
        
+       /* In a FUNCTION_DECL for which DECL_THUNK_P does not hold, this
+          is DECL_THUNKS.  */
+       tree thunks;
+
        /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
        tree cloned_function;
        
@@ -2049,6 +2057,11 @@ struct lang_decl GTY(())
 #define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) \
   (DECL_LANG_SPECIFIC (NODE)->decl_flags.needs_final_overrider)
 
+/* The thunks associated with NODE, a FUNCTION_DECL that is not itself
+   a thunk.  */
+#define DECL_THUNKS(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->u.f.thunks)
+
 /* Nonzero if NODE is a thunk, rather than an ordinary function.  */
 #define DECL_THUNK_P(NODE)                     \
   (TREE_CODE (NODE) == FUNCTION_DECL           \
index 97ab946..7459c87 100644 (file)
@@ -3594,9 +3594,12 @@ duplicate_decls (newdecl, olddecl)
       /* Only functions have DECL_BEFRIENDING_CLASSES.  */
       if (TREE_CODE (newdecl) == FUNCTION_DECL
          || DECL_FUNCTION_TEMPLATE_P (newdecl))
-       DECL_BEFRIENDING_CLASSES (newdecl)
-         = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
-                    DECL_BEFRIENDING_CLASSES (olddecl));
+       {
+         DECL_BEFRIENDING_CLASSES (newdecl)
+           = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+                      DECL_BEFRIENDING_CLASSES (olddecl));
+         DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
+       }
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
index 60a0dce..8a905b2 100644 (file)
@@ -278,10 +278,11 @@ make_thunk (function, delta, vcall_index)
 {
   tree thunk_id;
   tree thunk;
-  tree func_decl;
   tree vcall_offset;
   HOST_WIDE_INT d;
 
+  my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
+
   /* Scale the VCALL_INDEX to be in terms of bytes.  */
   if (vcall_index)
     vcall_offset 
@@ -294,59 +295,59 @@ make_thunk (function, delta, vcall_index)
 
   d = tree_low_cst (delta, 0);
 
-  if (TREE_CODE (function) != ADDR_EXPR)
-    abort ();
-  func_decl = TREE_OPERAND (function, 0);
-  if (TREE_CODE (func_decl) != FUNCTION_DECL)
-    abort ();
+  /* See if we already have the thunk in question.  */
+  for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
+    if (THUNK_DELTA (thunk) == d
+       && ((THUNK_VCALL_OFFSET (thunk) != NULL_TREE)
+           == (vcall_offset != NULL_TREE))
+       && (THUNK_VCALL_OFFSET (thunk)
+           ? tree_int_cst_equal (THUNK_VCALL_OFFSET (thunk), 
+                                 vcall_offset)
+           : true))
+      return thunk;
+
+  /* All thunks must be created before FUNCTION is actually emitted;
+     the ABI requires that all thunks be emitted together with the
+     function to which they transfer control.  */
+  my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025);
+
+  thunk_id = mangle_thunk (function, delta, vcall_offset);
+  thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (function));
+  DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
+  cxx_dup_lang_specific_decl (function);
+  SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
+  DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
+  TREE_READONLY (thunk) = TREE_READONLY (function);
+  TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
+  TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
+  if (flag_weak)
+    comdat_linkage (thunk);
+  SET_DECL_THUNK_P (thunk);
+  DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function);
+  THUNK_DELTA (thunk) = d;
+  THUNK_VCALL_OFFSET (thunk) = vcall_offset;
+  /* The thunk itself is not a constructor or destructor, even if
+     the thing it is thunking to is.  */
+  DECL_INTERFACE_KNOWN (thunk) = 1;
+  DECL_NOT_REALLY_EXTERN (thunk) = 1;
+  DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
+  DECL_DESTRUCTOR_P (thunk) = 0;
+  DECL_CONSTRUCTOR_P (thunk) = 0;
+  /* And neither is it a clone.  */
+  DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
+  DECL_EXTERNAL (thunk) = 1;
+  DECL_ARTIFICIAL (thunk) = 1;
+  /* Even if this thunk is a member of a local class, we don't
+     need a static chain.  */
+  DECL_NO_STATIC_CHAIN (thunk) = 1;
+  /* The THUNK is not a pending inline, even if the FUNCTION is.  */
+  DECL_PENDING_INLINE_P (thunk) = 0;
+  /* Nor has it been deferred.  */
+  DECL_DEFERRED_FN (thunk) = 0;
+  /* Add it to the list of thunks associated with FUNCTION.  */
+  TREE_CHAIN (thunk) = DECL_THUNKS (function);
+  DECL_THUNKS (function) = thunk;
 
-  thunk_id = mangle_thunk (TREE_OPERAND (function, 0), 
-                          delta, vcall_offset);
-  thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
-  if (thunk && !DECL_THUNK_P (thunk))
-    {
-      error ("implementation-reserved name `%D' used", thunk_id);
-      thunk = NULL_TREE;
-      SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
-    }
-  if (thunk == NULL_TREE)
-    {
-      thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
-      DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl);
-      cxx_dup_lang_specific_decl (func_decl);
-      SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
-      DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
-      TREE_READONLY (thunk) = TREE_READONLY (func_decl);
-      TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
-      TREE_PUBLIC (thunk) = TREE_PUBLIC (func_decl);
-      if (flag_weak)
-       comdat_linkage (thunk);
-      SET_DECL_THUNK_P (thunk);
-      DECL_INITIAL (thunk) = function;
-      THUNK_DELTA (thunk) = d;
-      THUNK_VCALL_OFFSET (thunk) = vcall_offset;
-      /* The thunk itself is not a constructor or destructor, even if
-         the thing it is thunking to is.  */
-      DECL_INTERFACE_KNOWN (thunk) = 1;
-      DECL_NOT_REALLY_EXTERN (thunk) = 1;
-      DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
-      DECL_DESTRUCTOR_P (thunk) = 0;
-      DECL_CONSTRUCTOR_P (thunk) = 0;
-      /* And neither is it a clone.  */
-      DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
-      DECL_EXTERNAL (thunk) = 1;
-      DECL_ARTIFICIAL (thunk) = 1;
-      /* Even if this thunk is a member of a local class, we don't
-        need a static chain.  */
-      DECL_NO_STATIC_CHAIN (thunk) = 1;
-      /* The THUNK is not a pending inline, even if the FUNC_DECL is.  */
-      DECL_PENDING_INLINE_P (thunk) = 0;
-      /* Nor has it been deferred.  */
-      DECL_DEFERRED_FN (thunk) = 0;
-      /* So that finish_file can write out any thunks that need to be: */
-      pushdecl_top_level (thunk);
-      SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
-    }
   return thunk;
 }
 
index c561a66..e2428a9 100644 (file)
@@ -2271,35 +2271,9 @@ emit_associated_thunks (fn)
      enabling you to output all the thunks with the function itself.  */
   if (DECL_VIRTUAL_P (fn))
     {
-      tree binfo;
-      tree v;
-
-      for (binfo = TYPE_BINFO (DECL_CONTEXT (fn));
-          binfo;
-          binfo = TREE_CHAIN (binfo))
-       for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v))
-         if (BV_FN (v) == fn
-             && (!integer_zerop (BV_DELTA (v))
-                 || BV_USE_VCALL_INDEX_P (v)))
-           {
-             tree thunk;
-             tree vcall_index;
-
-             if (BV_USE_VCALL_INDEX_P (v))
-               {
-                 vcall_index = BV_VCALL_INDEX (v);
-                 my_friendly_assert (vcall_index != NULL_TREE, 20000621);
-               }
-             else
-               vcall_index = NULL_TREE;
-
-             thunk = make_thunk (build1 (ADDR_EXPR,
-                                         vfunc_ptr_type_node,
-                                         fn),
-                                 BV_DELTA (v),
-                                 vcall_index);
-             use_thunk (thunk, /*emit_p=*/1);
-           }
+      tree thunk;
+      for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
+       use_thunk (thunk, /*emit_p=*/1);
     }
 }
 
index e7e3cff..a073e68 100644 (file)
@@ -1,3 +1,7 @@
+2002-10-25  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/vthunk2.C: New test.
+
 2002-10-25  Zack Weinberg  <zack@codesourcery.com>
 
        * g++.dg/ext/vla1.C, gcc.dg/vla-2.c: New tests.
diff --git a/gcc/testsuite/g++.dg/abi/vthunk2.C b/gcc/testsuite/g++.dg/abi/vthunk2.C
new file mode 100644 (file)
index 0000000..2499749
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-do compile { target i?86-*-* } }
+
+struct c0 {
+  virtual void f ();
+};
+
+struct c1 : virtual public c0 {
+};
+
+struct c2 : virtual public c0, public c1 {
+  virtual void f ();
+};
+
+void c2::f () {}
+
+// { dg-final { scan-assembler _ZTv0_n12_N2c21fEv } }