* class.c (empty_base_at_nonzero_offset_p): New function.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Oct 2002 05:04:48 +0000 (05:04 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Oct 2002 05:04:48 +0000 (05:04 +0000)
(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.

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

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 6fa961f..ed17618 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 4923b00..1439833 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 4fc092c..314b222 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" }