cp-tree.h (THUNK_TARGET): New macro.
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 30 Dec 2002 13:39:48 +0000 (13:39 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 30 Dec 2002 13:39:48 +0000 (13:39 +0000)
cp:
* cp-tree.h (THUNK_TARGET): New macro.
(THUNK_VIRTUAL_OFFSET): For result thunks it is always a binfo.
(finish_thunk): Remove offset parms.
* class.c (find_final_overrider): Look through thunks.
(get_vcall_index): Use THUNK_TARGET.
(update_vtable_entry_for_fn): Look through thunks. Set covariant
fixed offset here. Adjust finish_thunk call.
(build_vtbl_initializer): Adjust finish_thunk calls.
* mangle.c (mangle_call_offset): Remove superfluous if.
(mangle_thunk): Adjust.
* method.c (make_thunk): Adjust.
(finish_thunk): Adjust.
(thunk_adjust): Remove assert.
(use_thunk): Use THUNK_TARGET
* dump1.c (cp_dump_tree): Adjust thunk dumping.
testsuite:
* g++.dg/inherit/covariant5.C: New test.
* g++.dg/inherit/covariant6.C: New test.
* g++.dg/inherit/covariant7.C: New test.

From-SVN: r60628

gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/dump.c
gcc/cp/mangle.c
gcc/cp/method.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/covariant5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/inherit/covariant6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/inherit/covariant7.C [new file with mode: 0644]

index 85d6d2a..0ce3f11 100644 (file)
@@ -2299,6 +2299,9 @@ find_final_overrider (derived, binfo, fn)
      
      The solution is to look at all paths to BINFO.  If we find
      different overriders along any two, then there is a problem.  */
+  if (DECL_THUNK_P (fn))
+    fn = THUNK_TARGET (fn);
+  
   ffod.fn = fn;
   ffod.declaring_base = binfo;
   ffod.most_derived_type = BINFO_TYPE (derived);
@@ -2328,8 +2331,8 @@ get_vcall_index (tree fn, tree type)
 {
   tree v;
 
-  if (DECL_RESULT_THUNK_P (fn))
-    fn = TREE_OPERAND (DECL_INITIAL (fn), 0);
+  if (DECL_THUNK_P (fn))
+    fn = THUNK_TARGET (fn);
 
   for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
     if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
@@ -2360,11 +2363,15 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
   tree first_defn;
   bool lost = false;
 
+  if (DECL_THUNK_P (fn))
+    fn = THUNK_TARGET (fn);
+  
   /* Find the nearest primary base (possibly binfo itself) which defines
      this function; this is the class the caller will convert to when
      calling FN through BINFO.  */
   for (b = binfo; ; b = get_primary_binfo (b))
     {
+      my_friendly_assert (b, 20021227);
       if (look_for_overrides_here (BINFO_TYPE (b), fn))
        break;
 
@@ -2408,10 +2415,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
                /* If the covariant type is within the class hierarchy
                   we are currently laying out, the vbase index is not
                   yet known, so we have to remember the virtual base
-                  binfo for the moment.  The thunk will be finished
-                  in build_vtbl_initializer, where we'll know the
-                  vtable index of the virtual base.  */
-               virtual_offset = binfo_for_vbase (BINFO_TYPE (binfo), t);
+                  binfo. */
+               virtual_offset = binfo_for_vbase (BINFO_TYPE (binfo),
+                                                 TREE_TYPE (over_return));
+               fixed_offset = size_diffop (fixed_offset,
+                                           BINFO_OFFSET (virtual_offset));
              }
            
            /* Replace the overriding function with a covariant thunk.
@@ -2421,7 +2429,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
                                fixed_offset, virtual_offset);
            TREE_PURPOSE (overrider) = thunk;
            if (!virtual_offset && !DECL_NAME (thunk))
-             finish_thunk (thunk, fixed_offset, NULL_TREE);
+             finish_thunk (thunk);
          }
       }
   }
@@ -7739,18 +7747,12 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
       tree init = NULL_TREE;
       
       fn = BV_FN (v);
-      fn_original = (DECL_RESULT_THUNK_P (fn)
-                    ? TREE_OPERAND (DECL_INITIAL (fn), 0)
-                    : fn);
-      /* Finish an unfinished covariant thunk. */
-      if (DECL_RESULT_THUNK_P (fn) && !DECL_NAME (fn))
+      fn_original = fn;
+      if (DECL_THUNK_P (fn))
        {
-         tree binfo = THUNK_VIRTUAL_OFFSET (fn);
-         tree fixed_offset = size_int (THUNK_FIXED_OFFSET (fn));
-         tree virtual_offset = BINFO_VPTR_FIELD (binfo);
-         
-         fixed_offset = size_diffop (fixed_offset, BINFO_OFFSET (binfo));
-         finish_thunk (fn, fixed_offset, virtual_offset);
+         if (!DECL_NAME (fn))
+           finish_thunk (fn);
+         fn_original = THUNK_TARGET (fn);
        }
       
       /* If the only definition of this function signature along our
@@ -7796,7 +7798,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
            {
              fn = make_thunk (fn, /*this_adjusting=*/1, delta, vcall_index);
              if (!DECL_NAME (fn))
-               finish_thunk (fn, delta, THUNK_VIRTUAL_OFFSET (fn));
+               finish_thunk (fn);
            }
          /* Take the address of the function, considering it to be of an
             appropriate generic type.  */
index c224e2a..6296731 100644 (file)
@@ -1791,6 +1791,9 @@ struct lang_decl GTY(())
     {
       struct full_lang_decl 
       {
+       /* For a non-thunk function decl, this is a tree list of
+          friendly classes. For a thunk function decl, it is the
+          thunked to function decl.  */
        tree befriending_classes;
        
        /* For a non-virtual FUNCTION_DECL, this is
@@ -2977,14 +2980,20 @@ struct lang_decl GTY(())
 /* An integer indicating how many bytes should be subtracted from the
    this or result pointer when this function is called.  */
 #define THUNK_FIXED_OFFSET(DECL) \
-  (DECL_LANG_SPECIFIC (DECL)->u.f.fixed_offset)
-
-/* A tree indicating how many bytes should be added to the
-   vtable for the this or result pointer to find the vcall or vbase
-   offset.  (The vptr is always located at offset zero from the
-   this or result pointer.)  If NULL, then there is no virtual adjust.  */
+  (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL))->u.f.fixed_offset)
+
+/* A tree indicating how to perform the virtual adjustment. For a this
+   adjusting thunk it is the number of bytes to be added to the vtable
+   to find the vcall offset. For a result adjusting thunk, it is the
+   binfo of the relevant virtual base.  The vptr is always located at
+   offset zero from the this or result pointer.  If NULL, then there
+   is no virtual adjust.  */
 #define THUNK_VIRTUAL_OFFSET(DECL) \
-  (LANG_DECL_U2_CHECK (DECL, 0)->virtual_offset)
+  (LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset)
+
+/* For thunk NODE, this is the FUNCTION_DECL thunked to.  */
+#define THUNK_TARGET(NODE)                             \
+  (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
 
 /* These macros provide convenient access to the various _STMT nodes
    created when parsing template declarations.  */
@@ -3990,7 +3999,7 @@ extern void set_mangled_name_for_decl (tree);
 extern tree build_opfncall (enum tree_code, int, tree, tree, tree);
 extern tree hack_identifier (tree, tree);
 extern tree make_thunk (tree, bool, tree, tree);
-extern void finish_thunk (tree, tree, tree);
+extern void finish_thunk (tree);
 extern void use_thunk (tree, bool);
 extern void synthesize_method (tree);
 extern tree implicitly_declare_fn (special_function_kind, tree, bool);
index da207d3..bb842bd 100644 (file)
@@ -336,13 +336,20 @@ cp_dump_tree (dump_info, t)
        }
       else
        {
+         tree virt = THUNK_VIRTUAL_OFFSET (t);
+         
          dump_string (di, "thunk");
          if (DECL_THIS_THUNK_P (t))
            dump_string (di, "this adjusting");
          else
-           dump_string (di, "result adjusting");
+           {
+             dump_string (di, "result adjusting");
+             if (virt)
+               virt = BINFO_VPTR_FIELD (virt);
+           }
          dump_int (di, "fixd", THUNK_FIXED_OFFSET (t));
-         dump_child ("virt", THUNK_VIRTUAL_OFFSET (t));
+         if (virt)
+           dump_int (di, "virt", tree_low_cst (virt, 0));
          dump_child ("fn", DECL_INITIAL (t));
        }
       break;
index cf106d5..70443aa 100644 (file)
@@ -2545,10 +2545,7 @@ mangle_call_offset (fixed_offset, virtual_offset)
      tree fixed_offset;
      tree virtual_offset;
 {
-  if (virtual_offset)
-    write_char (virtual_offset ? 'v' : 'h');
-  else
-    write_char ('h');
+  write_char (virtual_offset ? 'v' : 'h');
 
   /* For either flavor, write the fixed offset.  */
   write_integer_cst (fixed_offset);
@@ -2590,24 +2587,27 @@ mangle_thunk (fn_decl, this_adjusting, fixed_offset, virtual_offset)
   write_string ("_Z");
   write_char ('T');
   
-  if (this_adjusting && !DECL_RESULT_THUNK_P (fn_decl))
-    /* Plain this adjusting thunk.  */
-    mangle_call_offset (fixed_offset, virtual_offset);
-  else if (!this_adjusting)
+  if (!this_adjusting)
     {
       /* Covariant thunk with no this adjustment */
       write_char ('c');
       mangle_call_offset (integer_zero_node, NULL_TREE);
       mangle_call_offset (fixed_offset, virtual_offset);
     }
+  else if (!DECL_THUNK_P (fn_decl))
+    /* Plain this adjusting thunk.  */
+    mangle_call_offset (fixed_offset, virtual_offset);
   else
     {
       /* This adjusting thunk to covariant thunk.  */
       write_char ('c');
       mangle_call_offset (fixed_offset, virtual_offset);
-      mangle_call_offset (ssize_int (THUNK_FIXED_OFFSET (fn_decl)),
-                         THUNK_VIRTUAL_OFFSET (fn_decl));
-      fn_decl = TREE_OPERAND (DECL_INITIAL (fn_decl), 0);
+      fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn_decl));
+      virtual_offset = THUNK_VIRTUAL_OFFSET (fn_decl);
+      if (virtual_offset)
+       virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
+      mangle_call_offset (fixed_offset, virtual_offset);
+      fn_decl = THUNK_TARGET (fn_decl);
     }
 
   /* Scoped name.  */
index 707a498..f4cfe0d 100644 (file)
@@ -261,8 +261,7 @@ make_thunk (tree function, bool this_adjusting,
   
   /* See if we already have the thunk in question.  For this_adjusting
      thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
-     will be a BINFO (because of the organization of the layout
-     algorithm). */
+     will be a BINFO. */
   for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
     if (DECL_THIS_THUNK_P (thunk) == this_adjusting
        && THUNK_FIXED_OFFSET (thunk) == d
@@ -281,7 +280,7 @@ make_thunk (tree function, bool this_adjusting,
 
   thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
   DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
-  cxx_dup_lang_specific_decl (function);
+  cxx_dup_lang_specific_decl (thunk);
   DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
   TREE_READONLY (thunk) = TREE_READONLY (function);
   TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
@@ -289,8 +288,8 @@ make_thunk (tree function, bool this_adjusting,
   if (flag_weak)
     comdat_linkage (thunk);
   SET_DECL_THUNK_P (thunk, this_adjusting);
-  DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function);
-  THUNK_FIXED_OFFSET (thunk) = tree_low_cst (fixed_offset, 0);
+  THUNK_TARGET (thunk) = function;
+  THUNK_FIXED_OFFSET (thunk) = d;
   THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
   
   /* The thunk itself is not a constructor or destructor, even if
@@ -320,20 +319,21 @@ make_thunk (tree function, bool this_adjusting,
   return thunk;
 }
 
-/* Finish THUNK, a thunk decl. FIXED_OFFSET and VIRTUAL_OFFSET are the
-   adjustments to apply.  */
+/* Finish THUNK, a thunk decl.  */
 
 void
-finish_thunk (tree thunk, tree fixed_offset, tree virtual_offset)
+finish_thunk (tree thunk)
 {
   tree function, name;
-  
+  tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk));
+  tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk);
+
   my_friendly_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk), 20021127);
-  function = TREE_OPERAND (DECL_INITIAL (thunk), 0);
+  if (virtual_offset && DECL_RESULT_THUNK_P (thunk))
+    virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
+  function = THUNK_TARGET (thunk);
   name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
-                           fixed_offset, virtual_offset);
-  THUNK_FIXED_OFFSET (thunk) = tree_low_cst (fixed_offset, 0);
-  THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
+                      fixed_offset, virtual_offset);
   DECL_NAME (thunk) = name;
   SET_DECL_ASSEMBLER_NAME (thunk, name);
 }
@@ -358,9 +358,6 @@ thunk_adjust (tree ptr, bool this_adjusting,
     {
       tree vtable;
 
-      /* It shouldn't be a binfo any more. */
-      my_friendly_assert (TREE_CODE (virtual_offset) == INTEGER_CST, 20021127);
-      
       ptr = save_expr (ptr);
       /* The vptr is always at offset zero in the object.  */
       vtable = build1 (NOP_EXPR,
@@ -392,10 +389,10 @@ thunk_adjust (tree ptr, bool this_adjusting,
 void
 use_thunk (tree thunk_fndecl, bool emit_p)
 {
-  tree fnaddr;
   tree function;
   tree virtual_offset;
   HOST_WIDE_INT fixed_offset, virtual_value;
+  bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);
 
   /* We should have called finish_thunk to give it a name. */
   my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127);
@@ -403,8 +400,8 @@ use_thunk (tree thunk_fndecl, bool emit_p)
   if (TREE_ASM_WRITTEN (thunk_fndecl))
     return;
   
-  fnaddr = DECL_INITIAL (thunk_fndecl);
-  if (TREE_CODE (DECL_INITIAL (thunk_fndecl)) != ADDR_EXPR)
+  function = THUNK_TARGET (thunk_fndecl);
+  if (DECL_RESULT (thunk_fndecl))
     /* We already turned this thunk into an ordinary function.
        There's no need to process this thunk again.  */
     return;
@@ -414,7 +411,6 @@ use_thunk (tree thunk_fndecl, bool emit_p)
 
   /* Figure out what function is being thunked to.  It's referenced in
      this translation unit.  */
-  function = TREE_OPERAND (fnaddr, 0);
   TREE_ADDRESSABLE (function) = 1;
   mark_used (function);
   TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (function)) = 1;
@@ -424,9 +420,15 @@ use_thunk (tree thunk_fndecl, bool emit_p)
   fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
   virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);
 
-  virtual_value = (virtual_offset
-                  ? tree_low_cst (virtual_offset, /*pos=*/0) : 0);
-  my_friendly_assert (!virtual_offset || virtual_value, 20021026);
+  if (virtual_offset)
+    {
+      if (!this_adjusting)
+       virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
+      virtual_value = tree_low_cst (virtual_offset, /*pos=*/0);
+      my_friendly_assert (virtual_value, 20021026);
+    }
+  else
+    virtual_value = 0;
   
   /* And, if we need to emit the thunk, it's used.  */
   mark_used (thunk_fndecl);
@@ -447,10 +449,9 @@ use_thunk (tree thunk_fndecl, bool emit_p)
   /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
      create one.  */
   DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
-  BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) 
-    = DECL_ARGUMENTS (thunk_fndecl);
-
-  if (DECL_THIS_THUNK_P (thunk_fndecl)
+  BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = DECL_ARGUMENTS (thunk_fndecl);
+  
+  if (this_adjusting
       && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
                                              virtual_value, function))
     {
@@ -502,7 +503,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
 
       t = a;
       
-      if (DECL_THIS_THUNK_P (thunk_fndecl))
+      if (this_adjusting)
        t = thunk_adjust (t, /*this_adjusting=*/1,
                          fixed_offset, virtual_offset);
       
@@ -512,7 +513,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
        t = tree_cons (NULL_TREE, a, t);
       t = nreverse (t);
       t = build_call (function, t);
-      if (DECL_RESULT_THUNK_P (thunk_fndecl))
+      if (!this_adjusting)
        t = thunk_adjust (t, /*this_adjusting=*/0,
                          fixed_offset, virtual_offset);
       
index 3373f6d..cae2b90 100644 (file)
@@ -1,3 +1,9 @@
+2002-12-30  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.dg/inherit/covariant5.C: New test.
+       * g++.dg/inherit/covariant6.C: New test.
+       * g++.dg/inherit/covariant7.C: New test.
+
 2002-12-29  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        PR c++/2739
diff --git a/gcc/testsuite/g++.dg/inherit/covariant5.C b/gcc/testsuite/g++.dg/inherit/covariant5.C
new file mode 100644 (file)
index 0000000..a46b1bf
--- /dev/null
@@ -0,0 +1,27 @@
+// { dg-do compile }
+
+// Copyright (C) 2002 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 27 Dec 2002 <nathan@codesourcery.com>
+
+// We ICE'd
+
+struct c0 {};
+
+struct c1 : virtual c0
+{
+  virtual c0 &f2();
+};
+
+struct c3 : c1
+{
+  virtual c1 &f2();
+};
+
+c1 &c3::f2()
+{
+  throw 0;
+}
+
+struct c4 : virtual c3
+{
+};
diff --git a/gcc/testsuite/g++.dg/inherit/covariant6.C b/gcc/testsuite/g++.dg/inherit/covariant6.C
new file mode 100644 (file)
index 0000000..dc55971
--- /dev/null
@@ -0,0 +1,27 @@
+// { dg-do compile }
+
+// Copyright (C) 2002 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 27 Dec 2002 <nathan@codesourcery.com>
+
+// We ICE'd
+
+struct c0 {};
+
+struct c1 : virtual c0
+{
+  virtual c0 &f2();
+};
+
+struct c3 : virtual c1
+{
+  virtual c1 &f2();
+};
+
+c1 &c3::f2()
+{
+  throw 0;
+}
+
+struct c4 : virtual c3
+{
+};
diff --git a/gcc/testsuite/g++.dg/inherit/covariant7.C b/gcc/testsuite/g++.dg/inherit/covariant7.C
new file mode 100644 (file)
index 0000000..596c679
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-do compile }
+
+// Copyright (C) 2002 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 27 Dec 2002 <nathan@codesourcery.com>
+
+// We ICE'd
+
+struct c0 {};
+
+struct c1 : virtual c0
+{
+  virtual c0 &f2() volatile;
+};
+
+struct c2 
+{
+  int m;
+};
+
+struct c3 : virtual c0, virtual c1, c2
+{
+  virtual c1 &f2() volatile;
+};
+
+struct c4 : virtual c3, virtual c0, virtual c1
+{
+  int m;
+};
+
+struct c6 : c0, c3, c4
+{ // { dg-warning "direct base" "" }
+  virtual c1 &f2() volatile;
+};