cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 20 Apr 2001 15:29:09 +0000 (15:29 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 20 Apr 2001 15:29:09 +0000 (15:29 +0000)
* class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED.
(layout_empty_base): Return at end flag.
(build_base_field): Likewise.
(build_base_fields): Likewise.
(layout_virtual_bases): Don't add 1 to eoc value.
(end_of_class): Use full size for empty bases.
(layout_class_type): Clear CLASSNEARLY_EMPTY_P if we appended
empty bases. Don't add 1 to eoc value. Only add trailing padding
if we're an empty class with no empty bases.
(dump_class_hierarchy): Dump size and alignment.
testsuite:
* g++.old-deja/g++.abi/empty2.C: New test.
* g++.old-deja/g++.abi/empty3.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.abi/empty2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/empty3.C [new file with mode: 0644]

index 16a03dc..eaee2bb 100644 (file)
@@ -1,3 +1,16 @@
+2001-04-20  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED.
+       (layout_empty_base): Return at end flag.
+       (build_base_field): Likewise.
+       (build_base_fields): Likewise.
+       (layout_virtual_bases): Don't add 1 to eoc value.
+       (end_of_class): Use full size for empty bases.
+       (layout_class_type): Clear CLASSNEARLY_EMPTY_P if we appended
+       empty bases. Don't add 1 to eoc value. Only add trailing padding
+       if we're an empty class with no empty bases.
+       (dump_class_hierarchy): Dump size and alignment.
+
 2001-04-20  Jakub Jelinek  <jakub@redhat.com>
 
        * call.c (maybe_handle_ref_bind): Copy ICS_USER_FLAG and
index 290dc21..9c713c0 100644 (file)
@@ -144,10 +144,10 @@ static void check_bitfield_decl PARAMS ((tree));
 static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
 static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
                                     int *));
-static void build_base_field PARAMS ((record_layout_info, tree, int *,
+static bool build_base_field PARAMS ((record_layout_info, tree, int *,
+                                    splay_tree));
+static bool build_base_fields PARAMS ((record_layout_info, int *,
                                      splay_tree));
-static void build_base_fields PARAMS ((record_layout_info, int *,
-                                      splay_tree));
 static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
 static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
                                               int *));
@@ -180,7 +180,7 @@ static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
                                                   tree, tree,
                                                   splay_tree));
 static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
-static void layout_empty_base PARAMS ((tree, tree, splay_tree));
+static bool layout_empty_base PARAMS ((tree, tree, splay_tree));
 static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
 static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
                                               tree));
@@ -1825,7 +1825,7 @@ mark_primary_virtual_base (binfo, base_binfo, type)
 
 static tree dfs_unshared_virtual_bases (binfo, data)
      tree binfo;
-     void *data;
+     void *data ATTRIBUTE_UNUSED;
 {
   if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo)
       && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
@@ -4015,9 +4015,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets)
 /* Layout the empty base BINFO.  EOC indicates the byte currently just
    past the end of the class, and should be correctly aligned for a
    class of the type indicated by BINFO; OFFSETS gives the offsets of
-   the empty bases allocated so far.  */
+   the empty bases allocated so far. Return non-zero iff we added it
+   at the end. */
 
-static void
+static bool
 layout_empty_base (binfo, eoc, offsets)
      tree binfo;
      tree eoc;
@@ -4025,6 +4026,7 @@ layout_empty_base (binfo, eoc, offsets)
 {
   tree alignment;
   tree basetype = BINFO_TYPE (binfo);
+  bool atend = false;
   
   /* This routine should only be used for empty classes.  */
   my_friendly_assert (is_empty_class (basetype), 20000321);
@@ -4039,6 +4041,7 @@ layout_empty_base (binfo, eoc, offsets)
     {
       /* That didn't work.  Now, we move forward from the next
         available spot in the class.  */
+      atend = true;
       propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
       while (1) 
        {
@@ -4053,14 +4056,16 @@ layout_empty_base (binfo, eoc, offsets)
          propagate_binfo_offsets (binfo, alignment);
        }
     }
+  return atend;
 }
 
 /* Build a FIELD_DECL for the base given by BINFO in the class
    indicated by RLI.  If the new object is non-empty, clear *EMPTY_P.
    *BASE_ALIGN is a running maximum of the alignments of any base
-   class.  OFFSETS gives the location of empty base subobjects.  */
+   class.  OFFSETS gives the location of empty base subobjects. Return
+   non-zero if the new object cannot be nearly-empty. */
 
-static void
+static bool
 build_base_field (rli, binfo, empty_p, offsets)
      record_layout_info rli;
      tree binfo;
@@ -4069,11 +4074,12 @@ build_base_field (rli, binfo, empty_p, offsets)
 {
   tree basetype = BINFO_TYPE (binfo);
   tree decl;
+  bool atend = false;
 
   if (!COMPLETE_TYPE_P (basetype))
     /* This error is now reported in xref_tag, thus giving better
        location information.  */
-    return;
+    return atend;
   
   decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
   DECL_ARTIFICIAL (decl) = 1;
@@ -4102,7 +4108,7 @@ build_base_field (rli, binfo, empty_p, offsets)
         byte-aligned.  */
       eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
       eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
-      layout_empty_base (binfo, size_int (eoc), offsets);
+      atend |= layout_empty_base (binfo, size_int (eoc), offsets);
     }
 
   /* Record the offsets of BINFO and its base subobjects.  */
@@ -4110,12 +4116,14 @@ build_base_field (rli, binfo, empty_p, offsets)
                            BINFO_OFFSET (binfo),
                            offsets, 
                            /*vbases_p=*/0);
+  return atend;
 }
 
 /* Layout all of the non-virtual base classes.  Record empty
-   subobjects in OFFSETS.  */
+   subobjects in OFFSETS. Return non-zero if the type cannot be nearly
+   empty.  */
 
-static void
+static bool
 build_base_fields (rli, empty_p, offsets)
      record_layout_info rli;
      int *empty_p;
@@ -4126,6 +4134,7 @@ build_base_fields (rli, empty_p, offsets)
   tree rec = rli->t;
   int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
   int i;
+  bool atend = 0;
 
   /* Under the new ABI, the primary base class is always allocated
      first.  */
@@ -4152,8 +4161,9 @@ build_base_fields (rli, empty_p, offsets)
          && !BINFO_PRIMARY_P (base_binfo))
        continue;
 
-      build_base_field (rli, base_binfo, empty_p, offsets);
+      atend |= build_base_field (rli, base_binfo, empty_p, offsets);
     }
+  return atend;
 }
 
 /* Go through the TYPE_METHODS of T issuing any appropriate
@@ -4828,7 +4838,7 @@ layout_virtual_bases (t, offsets)
      multiple such bases at the same location.  */
   eoc = end_of_class (t, /*include_virtuals_p=*/1);
   if (eoc * BITS_PER_UNIT > dsize)
-    dsize = (eoc + 1) * BITS_PER_UNIT;
+    dsize = eoc * BITS_PER_UNIT;
 
   /* Now, make sure that the total size of the type is a multiple of
      its alignment.  */
@@ -4867,6 +4877,7 @@ end_of_class (t, include_virtuals_p)
     {
       tree base_binfo;
       tree offset;
+      tree size;
       unsigned HOST_WIDE_INT end_of_base;
 
       base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
@@ -4876,9 +4887,16 @@ end_of_class (t, include_virtuals_p)
          && !BINFO_PRIMARY_P (base_binfo))
        continue;
 
+      if (is_empty_class (BINFO_TYPE (base_binfo)))
+       /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
+          allocate some space for it. It cannot have virtual bases,
+          so TYPE_SIZE_UNIT is fine.  */
+       size = TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
+      else
+       size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
       offset = size_binop (PLUS_EXPR, 
                           BINFO_OFFSET (base_binfo),
-                          CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo)));
+                          size);
       end_of_base = tree_low_cst (offset, /*pos=*/1);
       if (end_of_base > result)
        result = end_of_base;
@@ -4970,7 +4988,9 @@ layout_class_type (t, empty_p, vfuns_p,
   /* Build FIELD_DECLs for all of the non-virtual base-types.  */
   empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, 
                                       NULL, NULL);
-  build_base_fields (rli, empty_p, empty_base_offsets);
+  if (build_base_fields (rli, empty_p, empty_base_offsets))
+    CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+  
   /* Add pointers to all of our virtual base-classes.  */
   TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
                             TYPE_FIELDS (t));
@@ -5060,7 +5080,7 @@ layout_class_type (t, empty_p, vfuns_p,
   if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
       && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
     {
-      rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc + 1));
+      rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
       rli->bitpos = bitsize_zero_node;
     }
 
@@ -5069,7 +5089,7 @@ layout_class_type (t, empty_p, vfuns_p,
      if it has basetypes.  Therefore, we add the fake field after all
      the other fields; if there are already FIELD_DECLs on the list,
      their offsets will not be disturbed.  */
-  if (*empty_p)
+  if (!eoc && *empty_p)
     {
       tree padding;
 
@@ -6758,8 +6778,11 @@ dump_class_hierarchy (name, t)
         error ("could not open dump file `%s'", name);
       return;
     }
-  fprintf (stream, "%s\n",
-           type_as_string (t, TFF_PLAIN_IDENTIFIER));
+  fprintf (stream, "%s size=", type_as_string (t, TFF_PLAIN_IDENTIFIER));
+  fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
+          tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT);
+  fprintf (stream, " align=%lu\n",
+          (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
   dump_class_hierarchy_r (stream, t, TYPE_BINFO (t), 0);
   fprintf (stream, "\n");
   if (name)
index 8ba71f8..157bbed 100644 (file)
@@ -1,3 +1,8 @@
+2001-04-20  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.abi/empty2.C: New test.
+       * g++.old-deja/g++.abi/empty3.C: New test.
+
 2001-04-20  Jakub Jelinek  <jakub@redhat.com>
 
        * g++.old-deja/g++.other/comdat2.C: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/empty2.C b/gcc/testsuite/g++.old-deja/g++.abi/empty2.C
new file mode 100644 (file)
index 0000000..4116517
--- /dev/null
@@ -0,0 +1,136 @@
+// Build don't link:
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 12 Apr 2001 <nathan@codesourcery.com>
+
+// Check we deal with trailing empty base classes properly
+
+struct A {};
+struct B1 : A {};
+struct B2 : A {};
+struct B3 : A {};
+struct B4 : A {};
+struct B5 : A {};
+struct B6 : A {};
+struct B7 : A {};
+struct B8 : A {};
+
+struct C1 : B1
+{
+  virtual void Foo () {};
+};
+struct C2 : B1, B2
+{
+  virtual void Foo () {};
+};
+struct C3 : B1, B2, B3
+{
+  virtual void Foo () {};
+};
+struct C4 : B1, B2, B3, B4
+{
+  virtual void Foo () {};
+};
+struct C5 : B1, B2, B3, B4, B5
+{
+  virtual void Foo () {};
+};
+struct C6 : B1, B2, B3, B4, B5, B6
+{
+  virtual void Foo () {};
+};
+struct C7 : B1, B2, B3, B4, B5, B6, B7
+{
+  virtual void Foo () {};
+};
+struct C8 : B1, B2, B3, B4, B5, B6, B7, B8
+{
+  virtual void Foo () {};
+};
+
+struct D1 : virtual C1 {};
+struct D2 : virtual C2 {};
+struct D3 : virtual C3 {};
+struct D4 : virtual C4 {};
+struct D5 : virtual C5 {};
+struct D6 : virtual C6 {};
+struct D7 : virtual C7 {};
+struct D8 : virtual C8 {};
+
+unsigned const nearly_empty_size = sizeof (D1);
+
+template <typename Cn, typename Dn> int Check (Dn const &ref)
+{
+  if ((sizeof (Cn) <= nearly_empty_size)
+      != (static_cast <void const *> (&ref)
+         == static_cast <Cn const *> (&ref)))
+    return 1;
+  return 0;
+}
+
+template <typename Bn, typename Cn> int Check ()
+{
+  Cn c[2];
+
+  if (static_cast <A *> (static_cast <B1 *> (&c[1]))
+      == static_cast <A *> (static_cast <Bn *> (&c[0])))
+    return 1;
+  return 0;
+}
+
+  
+int main ()
+{
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+  if (Check<B1, C1> ())
+    return 1;
+  if (Check<B2, C2> ())
+    return 2;
+  if (Check<B3, C3> ())
+    return 3;
+  if (Check<B4, C4> ())
+    return 4;
+  if (Check<B5, C5> ())
+    return 5;
+  if (Check<B6, C6> ())
+    return 6;
+  if (Check<B7, C7> ())
+    return 7;
+  if (Check<B8, C8> ())
+    return 8;
+  
+  if (Check<C1> (D1 ()))
+    return 11;
+  if (Check<C2> (D2 ()))
+    return 12;
+  if (Check<C3> (D3 ()))
+    return 13;
+  if (Check<C4> (D4 ()))
+    return 14;
+  if (Check<C5> (D5 ()))
+    return 15;
+  if (Check<C6> (D6 ()))
+    return 16;
+  if (Check<C7> (D7 ()))
+    return 17;
+  if (Check<C8> (D8 ()))
+    return 18;
+  
+  if (sizeof (C2) == nearly_empty_size)
+    return 22;
+  if (sizeof (C3) == nearly_empty_size)
+    return 23;
+  if (sizeof (C4) == nearly_empty_size)
+    return 24;
+  if (sizeof (C5) == nearly_empty_size)
+    return 25;
+  if (sizeof (C6) == nearly_empty_size)
+    return 26;
+  if (sizeof (C7) == nearly_empty_size)
+    return 27;
+  if (sizeof (C8) == nearly_empty_size)
+    return 28;
+#endif
+  return 0;
+  
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/empty3.C b/gcc/testsuite/g++.old-deja/g++.abi/empty3.C
new file mode 100644 (file)
index 0000000..93e9d9f
--- /dev/null
@@ -0,0 +1,24 @@
+// Build don't link:
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 12 Apr 2001 <nathan@codesourcery.com>
+
+// Check we deal with aligning virtual bases after a trailing empty
+// base class properly
+
+struct A {};
+struct B1 : A {};
+struct B2 : A {};
+struct B3 : A {};
+
+struct C : B1, B2, virtual B3 {};
+
+int main ()
+{
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+  C c;
+  if (((char *)static_cast <B3 *> (&c) - (char *)&c) % __alignof__ (C))
+    return 1;
+#endif
+  return 0;
+}