summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2002-10-22 05:04:48 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2002-10-22 05:04:48 +0000
commit64f10f70b459140b86edfb3101a5c6d3f8715a08 (patch)
tree4b99387bab5f35027f255ee22e338f0031a4d558 /gcc
parent0725d7debf0dc1956b9fdcda2f1ff8ca48f97a30 (diff)
downloadgcc-64f10f70b459140b86edfb3101a5c6d3f8715a08.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@58397 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/class.c44
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/abi/vbase13.C17
-rw-r--r--gcc/testsuite/g++.dg/abi/vbase14.C6
5 files changed, 75 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6fa961f6ad5..ed176188426 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 4923b00fb8a..1439833b209 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4fc092cc836..314b222aa40 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..6a0bff484d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/vbase13.C
@@ -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
index 00000000000..99290b85720
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/vbase14.C
@@ -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" }