class.c (empty_base_at_nonzero_offset_p): New function.
authorMark Mitchell <mark@codesourcery.com>
Tue, 22 Oct 2002 05:04:48 +0000 (05:04 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 22 Oct 2002 05:04:48 +0000 (05:04 +0000)
* class.c (empty_base_at_nonzero_offset_p): New function.
(layout_nonempty_base_or_field): Do not check for conflicts when
laying out a virtual base using the GCC 3.2 ABI.
(build_base_field): Correct checking for presence of empty classes
at non-zero offsets when clearing CLASSTYPE_NEARLY_EMPTY_P.

* g++.dg/abi/vbase13.C: New test.
* g++.dg/abi/vbase14.C: Likewise.

From-SVN: r58397

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/vbase13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/vbase14.C [new file with mode: 0644]

index 6fa961f6ad5f229d4b6ff5cf00b85390a09f281a..ed176188426ceef7fa29f392cdb77f2a3f4b1ce1 100644 (file)
@@ -1,5 +1,11 @@
 2002-10-21  Mark Mitchell  <mark@codesourcery.com>
 
+       * class.c (empty_base_at_nonzero_offset_p): New function.
+       (layout_nonempty_base_or_field): Do not check for conflicts when
+       laying out a virtual base using the GCC 3.2 ABI.
+       (build_base_field): Correct checking for presence of empty classes
+       at non-zero offsets when clearing CLASSTYPE_NEARLY_EMPTY_P.
+
        * class.c (include_empty_classes): Use normalize_rli.
        (layout_class_type): Likewise.
 
index 4923b00fb8a163b28a97f860ba65dbe71810d614..1439833b209d12f032a5f79ac21789db20a9e23a 100644 (file)
@@ -209,6 +209,7 @@ static bool type_requires_array_cookie PARAMS ((tree));
 static bool contains_empty_class_p (tree);
 static tree dfs_base_derived_from (tree, void *);
 static bool base_derived_from (tree, tree);
+static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
 
 /* Macros for dfs walking during vtt construction. See
    dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
@@ -3674,6 +3675,10 @@ layout_nonempty_base_or_field (record_layout_info rli,
         empty class, have nonzero size, any overlap can happen only
         with a direct or indirect base-class -- it can't happen with
         a data member.  */
+      /* G++ 3.2 did not check for overlaps when placing a non-empty
+        virtual base.  */
+      if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
+       break;
       if (layout_conflict_p (type, offset, offsets, field_p))
        {
          /* Strip off the size allocated to this field.  That puts us
@@ -3708,6 +3713,16 @@ layout_nonempty_base_or_field (record_layout_info rli,
                             t);
 }
 
+/* Returns true if TYPE is empty and OFFSET is non-zero.  */
+
+static int
+empty_base_at_nonzero_offset_p (tree type,
+                               tree offset,
+                               splay_tree offsets ATTRIBUTE_UNUSED)
+{
+  return is_empty_class (type) && !integer_zerop (offset);
+}
+
 /* 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
@@ -3816,14 +3831,37 @@ build_base_field (record_layout_info rli, tree binfo,
   else
     {
       tree eoc;
+      bool atend;
 
       /* On some platforms (ARM), even empty classes will not be
         byte-aligned.  */
       eoc = round_up (rli_size_unit_so_far (rli),
                      CLASSTYPE_ALIGN_UNIT (basetype));
-      if (layout_empty_base (binfo, eoc, offsets, t))
-       CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
-
+      atend = layout_empty_base (binfo, eoc, offsets, t);
+      /* A nearly-empty class "has no proper base class that is empty,
+        not morally virtual, and at an offset other than zero."  */
+      if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
+       {
+         if (atend)
+           CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+         /* The check above (used in G++ 3.2) is insufficient  because
+            an empty class placed at offset zero might itself have an
+            empty base at a non-zero offset.  */
+         else if (walk_subobject_offsets (basetype, 
+                                          empty_base_at_nonzero_offset_p,
+                                          size_zero_node,
+                                          /*offsets=*/NULL,
+                                          /*max_offset=*/NULL_TREE,
+                                          /*vbases_p=*/true))
+           {
+             if (abi_version_at_least (2))
+               CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+             else if (warn_abi)
+               warning ("class `%T' will be considered nearly empty in a "
+                        "future version of GCC", t);
+           }
+       }
+       
       /* We do not create a FIELD_DECL for empty base classes because
         it might overlap some other field.  We want to be able to
         create CONSTRUCTORs for the class by iterating over the
index 4fc092cc836108c218581f104c7e4f9feb2f85a9..314b222aa40f633e1b938f2bb03edc129e3b6bb7 100644 (file)
@@ -1,3 +1,8 @@
+2002-10-21  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/vbase13.C: New test.
+       * g++.dg/abi/vbase14.C: Likewise.
+
 2002-10-21  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/tls/pic-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/abi/vbase13.C b/gcc/testsuite/g++.dg/abi/vbase13.C
new file mode 100644 (file)
index 0000000..6a0bff4
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do run }
+// { dg-options "-fabi-version=0 -w" }
+
+struct E1 {};
+struct E2 : public E1 {};
+struct E : public E1, public E2 {};
+struct N : public E { virtual void f () {} };
+
+struct X : virtual public N {
+};
+
+int main () {
+  X x;
+  /* N should not be the primary base of X; it is not nearly empty.  */
+  if ((void*)&x == (void*)(N*)&x)
+    return 1;
+}
diff --git a/gcc/testsuite/g++.dg/abi/vbase14.C b/gcc/testsuite/g++.dg/abi/vbase14.C
new file mode 100644 (file)
index 0000000..99290b8
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-options "-Wabi" }
+
+struct E1 {};
+struct E2 : public E1 {}; // { dg-warning "layout" }
+struct E : public E1, public E2 {}; // { dg-warning "layout|ambiguity" }
+struct N : public E { virtual void f () {} };  // { dg-warning "nearly" }