summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2000-03-19 05:22:04 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2000-03-19 05:22:04 +0000
commitad63a0fca1c16a7b56f4f29888a87ee535cb9f4c (patch)
tree27221340a82ba130909a03491572338e80e9b132
parent562b698d89a7c68dd22d8452a67bd34e4e65871f (diff)
downloadgcc-ad63a0fca1c16a7b56f4f29888a87ee535cb9f4c.tar.gz
* cp-tree.h (CLEAR_DECL_C_BIT_FIELD): New macro.
* class.c (check_bitfield_decl): Turn illegal bitfields into non-bitfields. (dfs_propagate_binfo_offsets): Adjust for new size_binop semantics. (dfs_offset_for_unshared_vbases): Likewise. * cvt.c (cp_convert_to_pointer): Convert NULL to a pointer-to-member correctly under the new ABI. * expr.c (cplus_expand_constant): Don't use cp_convert when turning an offset into a pointer-to-member. * init.c (resolve_offset_ref): Don't adjust pointers-to-members when dereferencing them under the new ABI. * typeck.c (get_member_function_from_ptrfunc): Tweak calculation of pointers-to-members under the new ABI. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32631 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/class.c61
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/cvt.c8
-rw-r--r--gcc/cp/expr.c17
-rw-r--r--gcc/cp/init.c12
-rw-r--r--gcc/cp/typeck.c9
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/empty.C68
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C17
9 files changed, 161 insertions, 48 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 892a466bd2e..fbaaad904ca 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,20 @@
2000-03-18 Mark Mitchell <mark@codesourcery.com>
+ * cp-tree.h (CLEAR_DECL_C_BIT_FIELD): New macro.
+ * class.c (check_bitfield_decl): Turn illegal bitfields into
+ non-bitfields.
+ (dfs_propagate_binfo_offsets): Adjust for new size_binop
+ semantics.
+ (dfs_offset_for_unshared_vbases): Likewise.
+ * cvt.c (cp_convert_to_pointer): Convert NULL to a
+ pointer-to-member correctly under the new ABI.
+ * expr.c (cplus_expand_constant): Don't use cp_convert when
+ turning an offset into a pointer-to-member.
+ * init.c (resolve_offset_ref): Don't adjust pointers-to-members
+ when dereferencing them under the new ABI.
+ * typeck.c (get_member_function_from_ptrfunc): Tweak calculation
+ of pointers-to-members under the new ABI.
+
* class.c (check_bitfield_decl): Remove restriction on really long
bitfields.
(layout_class_type): Implement new ABI handling of bitfields
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 5475ac4ba92..02424928d0d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3616,22 +3616,20 @@ check_bitfield_decl (field)
tree field;
{
tree type = TREE_TYPE (field);
+ tree w = NULL_TREE;
- /* Invalid bit-field size done by grokfield. */
- /* Detect invalid bit-field type. Simply checking if TYPE is
- integral is insufficient, as that is the array core of the field
- type. If TREE_TYPE (field) is integral, then TYPE must be the same. */
+ /* Detect invalid bit-field type. */
if (DECL_INITIAL (field)
&& ! INTEGRAL_TYPE_P (TREE_TYPE (field)))
{
cp_error_at ("bit-field `%#D' with non-integral type", field);
- DECL_INITIAL (field) = NULL;
+ w = error_mark_node;
}
/* Detect and ignore out of range field width. */
if (DECL_INITIAL (field))
{
- tree w = DECL_INITIAL (field);
+ w = DECL_INITIAL (field);
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (w);
@@ -3646,17 +3644,17 @@ check_bitfield_decl (field)
{
cp_error_at ("bit-field `%D' width not an integer constant",
field);
- DECL_INITIAL (field) = NULL_TREE;
+ w = error_mark_node;
}
else if (tree_int_cst_sgn (w) < 0)
{
- DECL_INITIAL (field) = NULL;
cp_error_at ("negative width in bit-field `%D'", field);
+ w = error_mark_node;
}
else if (integer_zerop (w) && DECL_NAME (field) != 0)
{
- DECL_INITIAL (field) = NULL;
cp_error_at ("zero width for bit-field `%D'", field);
+ w = error_mark_node;
}
else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
&& TREE_CODE (type) != ENUMERAL_TYPE
@@ -3672,30 +3670,37 @@ check_bitfield_decl (field)
TREE_UNSIGNED (type)))))
cp_warning_at ("`%D' is too small to hold all values of `%#T'",
field, type);
+ }
+
+ /* Remove the bit-field width indicator so that the rest of the
+ compiler does not treat that value as an initializer. */
+ DECL_INITIAL (field) = NULL_TREE;
- if (DECL_INITIAL (field))
- {
- DECL_INITIAL (field) = NULL_TREE;
- DECL_SIZE (field) = convert (bitsizetype, w);
- DECL_BIT_FIELD (field) = 1;
+ if (w != error_mark_node)
+ {
+ DECL_SIZE (field) = convert (bitsizetype, w);
+ DECL_BIT_FIELD (field) = 1;
- if (integer_zerop (w))
- {
+ if (integer_zerop (w))
+ {
#ifdef EMPTY_FIELD_BOUNDARY
- DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
- EMPTY_FIELD_BOUNDARY);
+ DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
+ EMPTY_FIELD_BOUNDARY);
#endif
#ifdef PCC_BITFIELD_TYPE_MATTERS
- if (PCC_BITFIELD_TYPE_MATTERS)
- DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
- TYPE_ALIGN (type));
+ if (PCC_BITFIELD_TYPE_MATTERS)
+ DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
+ TYPE_ALIGN (type));
#endif
- }
}
}
else
- /* Non-bit-fields are aligned for their type. */
- DECL_ALIGN (field) = MAX (DECL_ALIGN (field), TYPE_ALIGN (type));
+ {
+ /* Non-bit-fields are aligned for their type. */
+ DECL_BIT_FIELD (field) = 0;
+ CLEAR_DECL_C_BIT_FIELD (field);
+ DECL_ALIGN (field) = MAX (DECL_ALIGN (field), TYPE_ALIGN (type));
+ }
}
/* FIELD is a non bit-field. We are finishing the processing for its
@@ -4678,7 +4683,10 @@ dfs_propagate_binfo_offsets (binfo, data)
tree offset = (tree) data;
/* Update the BINFO_OFFSET for this base. */
- BINFO_OFFSET (binfo) = size_binop (PLUS_EXPR, BINFO_OFFSET (binfo), offset);
+ BINFO_OFFSET (binfo) = fold (build (PLUS_EXPR,
+ sizetype,
+ BINFO_OFFSET (binfo),
+ offset));
SET_BINFO_MARKED (binfo);
@@ -4744,8 +4752,7 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
tree offset;
vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t);
- offset = size_binop (MINUS_EXPR,
- BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
+ offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
propagate_binfo_offsets (binfo, offset);
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fd87926fd03..3e6f1c98066 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2347,6 +2347,8 @@ extern int flag_new_for_scope;
&& DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield)
#define SET_DECL_C_BIT_FIELD(NODE) \
(DECL_LANG_SPECIFIC (FIELD_DECL_CHECK (NODE))->decl_flags.bitfield = 1)
+#define CLEAR_DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_SPECIFIC (FIELD_DECL_CHECK (NODE))->decl_flags.bitfield = 0)
/* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
#define DECL_UNINLINABLE(NODE) \
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 9743f3753d5..d3c24093b63 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -240,7 +240,13 @@ cp_convert_to_pointer (type, expr)
{
if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
- expr = build_int_2 (0, 0);
+
+ if (flag_new_abi && TYPE_PTRMEM_P (type))
+ /* Under the new ABI, a NULL pointer-to-member is represented
+ by -1, not by zero. */
+ expr = build_int_2 (-1, -1);
+ else
+ expr = build_int_2 (0, 0);
TREE_TYPE (expr) = type;
return expr;
}
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index e97a65d55e8..230fa6a154b 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -65,11 +65,18 @@ cplus_expand_constant (cst)
bit_position (member),
bitsize_int (BITS_PER_UNIT)));
- /* We offset all pointer to data members by 1 so that we
- can distinguish between a null pointer to data member
- and the first data member of a structure. */
- offset = size_binop (PLUS_EXPR, offset, size_one_node);
- cst = cp_convert (type, offset);
+ if (flag_new_abi)
+ /* Under the new ABI, we use -1 to represent the NULL
+ pointer; non-NULL values simply contain the offset of
+ the data member. */
+ ;
+ else
+ /* We offset all pointer to data members by 1 so that we
+ can distinguish between a null pointer to data member
+ and the first data member of a structure. */
+ offset = size_binop (PLUS_EXPR, offset, size_one_node);
+
+ cst = fold (build1 (NOP_EXPR, type, offset));
}
else
{
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 960f46b0ac3..8994f604239 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1821,11 +1821,13 @@ resolve_offset_ref (exp)
addr = convert_pointer_to (basetype, addr);
member = cp_convert (ptrdiff_type_node, member);
- /* Pointer to data members are offset by one, so that a null
- pointer with a real value of 0 is distinguishable from an
- offset of the first member of a structure. */
- member = build_binary_op (MINUS_EXPR, member,
- cp_convert (ptrdiff_type_node, integer_one_node));
+ if (!flag_new_abi)
+ /* Pointer to data members are offset by one, so that a null
+ pointer with a real value of 0 is distinguishable from an
+ offset of the first member of a structure. */
+ member = build_binary_op (MINUS_EXPR, member,
+ cp_convert (ptrdiff_type_node,
+ integer_one_node));
return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, build_pointer_type (type),
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a92c1febfcf..43bd1bc4952 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2858,7 +2858,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
{
idx = build_binary_op (TRUNC_DIV_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3),
- integer_two_node);
+ TYPE_SIZE_UNIT (vtable_entry_type));
e1 = build_binary_op (BIT_AND_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3),
integer_one_node);
@@ -6332,11 +6332,12 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2)
}
else
{
- /* Under the new ABI, we set PFN to twice the index, plus
- one. */
+ /* Under the new ABI, we set PFN to the vtable offset, plus
+ one, at which the function can be found. */
*idx = NULL_TREE;
*pfn = fold (build (MULT_EXPR, integer_type_node,
- DECL_VINDEX (fn), integer_two_node));
+ DECL_VINDEX (fn),
+ TYPE_SIZE_UNIT (vtable_entry_type)));
*pfn = fold (build (PLUS_EXPR, integer_type_node, *pfn,
integer_one_node));
*pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/empty.C b/gcc/testsuite/g++.old-deja/g++.abi/empty.C
new file mode 100644
index 00000000000..b7a791f0a94
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/empty.C
@@ -0,0 +1,68 @@
+// Special g++ Options: -w
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+struct S0
+{
+};
+
+struct S1 : public S0
+{
+};
+
+struct S2 : public S1
+{
+ char c;
+};
+
+// In S3, the S1 instance is allocated first at offset zero. The S2
+// instance has to be allocated at a subsequent offset; it's first
+// part is also an S1.
+
+struct S3 : public S1, public S2
+{
+};
+
+struct S4
+{
+ int i;
+};
+
+// In S4, in contrast to S3, S2 is allocated first, and S1 can be
+// allocated on top of S4.
+
+struct S5 : public S2, public S1, public S4
+{
+};
+
+// The T classes are by-hand layouts that should be equivalent to the
+// S classes.
+
+struct T3
+{
+ S1 s1;
+ S2 s2;
+};
+
+struct T5
+{
+ S2 s2;
+ S4 s4;
+};
+
+int main ()
+{
+ if (sizeof (S3) != sizeof (T3))
+ return 1;
+ else if (sizeof (S5) != sizeof (T5))
+ return 2;
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main ()
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
index 8dc3ee46a5c..975d9397ded 100644
--- a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
+++ b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
@@ -82,16 +82,16 @@ main ()
if (xp->adj != delta)
return 8;
- // For a virtual function, we should see twice the vtable index,
- // plus one. `T::h' is in the third slot: there's the RTTI entry,
- // then the two virtual functions.
+ // For a virtual function, we should see the vtable offset, plus
+ // one. `T::h' is in the second slot: the vtable pointer points to
+ // the first virtual function.
y = &T::h;
- if ((ptrdiff_t) yp->ptr != 7)
+ if ((ptrdiff_t) yp->ptr != sizeof (void *) + 1)
return 9;
if (yp->adj != 0)
return 10;
x = (sp) y;
- if ((ptrdiff_t) xp->ptr != 7)
+ if ((ptrdiff_t) xp->ptr != sizeof (void *) + 1)
return 11;
if (xp->adj != delta)
return 12;
@@ -103,9 +103,14 @@ main ()
if (__alignof__ (sdp) != __alignof__ (ptrdiff_t))
return 14;
+ // The value of a pointer-to-data member should be the offset from
+ // the start of the structure.
sdp z = &S::j;
- if ((char *) &s.j - (char *) &s != *((ptrdiff_t *) &z) - 1)
+ if ((char *) &s.j - (char *) &s != *((ptrdiff_t *) &z))
return 15;
+ z = 0;
+ if (*((ptrdiff_t *) &z) != -1)
+ return 16;
}
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */