Commit cd8ed629 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (CLEAR_DECL_C_BIT_FIELD): New macro.

	* 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.

From-SVN: r32631
parent 3ca3ce41
2000-03-18 Mark Mitchell <mark@codesourcery.com> 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 * class.c (check_bitfield_decl): Remove restriction on really long
bitfields. bitfields.
(layout_class_type): Implement new ABI handling of bitfields (layout_class_type): Implement new ABI handling of bitfields
......
...@@ -3616,22 +3616,20 @@ check_bitfield_decl (field) ...@@ -3616,22 +3616,20 @@ check_bitfield_decl (field)
tree field; tree field;
{ {
tree type = TREE_TYPE (field); tree type = TREE_TYPE (field);
tree w = NULL_TREE;
/* Invalid bit-field size done by grokfield. */ /* Detect invalid bit-field type. */
/* 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. */
if (DECL_INITIAL (field) if (DECL_INITIAL (field)
&& ! INTEGRAL_TYPE_P (TREE_TYPE (field))) && ! INTEGRAL_TYPE_P (TREE_TYPE (field)))
{ {
cp_error_at ("bit-field `%#D' with non-integral 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. */ /* Detect and ignore out of range field width. */
if (DECL_INITIAL (field)) if (DECL_INITIAL (field))
{ {
tree w = DECL_INITIAL (field); w = DECL_INITIAL (field);
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */ /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (w); STRIP_NOPS (w);
...@@ -3646,17 +3644,17 @@ check_bitfield_decl (field) ...@@ -3646,17 +3644,17 @@ check_bitfield_decl (field)
{ {
cp_error_at ("bit-field `%D' width not an integer constant", cp_error_at ("bit-field `%D' width not an integer constant",
field); field);
DECL_INITIAL (field) = NULL_TREE; w = error_mark_node;
} }
else if (tree_int_cst_sgn (w) < 0) else if (tree_int_cst_sgn (w) < 0)
{ {
DECL_INITIAL (field) = NULL;
cp_error_at ("negative width in bit-field `%D'", field); cp_error_at ("negative width in bit-field `%D'", field);
w = error_mark_node;
} }
else if (integer_zerop (w) && DECL_NAME (field) != 0) else if (integer_zerop (w) && DECL_NAME (field) != 0)
{ {
DECL_INITIAL (field) = NULL;
cp_error_at ("zero width for bit-field `%D'", field); cp_error_at ("zero width for bit-field `%D'", field);
w = error_mark_node;
} }
else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0 else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
&& TREE_CODE (type) != ENUMERAL_TYPE && TREE_CODE (type) != ENUMERAL_TYPE
...@@ -3672,30 +3670,37 @@ check_bitfield_decl (field) ...@@ -3672,30 +3670,37 @@ check_bitfield_decl (field)
TREE_UNSIGNED (type))))) TREE_UNSIGNED (type)))))
cp_warning_at ("`%D' is too small to hold all values of `%#T'", cp_warning_at ("`%D' is too small to hold all values of `%#T'",
field, type); 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)) if (w != error_mark_node)
{ {
DECL_INITIAL (field) = NULL_TREE; DECL_SIZE (field) = convert (bitsizetype, w);
DECL_SIZE (field) = convert (bitsizetype, w); DECL_BIT_FIELD (field) = 1;
DECL_BIT_FIELD (field) = 1;
if (integer_zerop (w)) if (integer_zerop (w))
{ {
#ifdef EMPTY_FIELD_BOUNDARY #ifdef EMPTY_FIELD_BOUNDARY
DECL_ALIGN (field) = MAX (DECL_ALIGN (field), DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
EMPTY_FIELD_BOUNDARY); EMPTY_FIELD_BOUNDARY);
#endif #endif
#ifdef PCC_BITFIELD_TYPE_MATTERS #ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS) if (PCC_BITFIELD_TYPE_MATTERS)
DECL_ALIGN (field) = MAX (DECL_ALIGN (field), DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
TYPE_ALIGN (type)); TYPE_ALIGN (type));
#endif #endif
}
} }
} }
else 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 /* FIELD is a non bit-field. We are finishing the processing for its
...@@ -4678,7 +4683,10 @@ dfs_propagate_binfo_offsets (binfo, data) ...@@ -4678,7 +4683,10 @@ dfs_propagate_binfo_offsets (binfo, data)
tree offset = (tree) data; tree offset = (tree) data;
/* Update the BINFO_OFFSET for this base. */ /* 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); SET_BINFO_MARKED (binfo);
...@@ -4744,8 +4752,7 @@ dfs_set_offset_for_unshared_vbases (binfo, data) ...@@ -4744,8 +4752,7 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
tree offset; tree offset;
vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t); vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t);
offset = size_binop (MINUS_EXPR, offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
propagate_binfo_offsets (binfo, offset); propagate_binfo_offsets (binfo, offset);
} }
......
...@@ -2347,6 +2347,8 @@ extern int flag_new_for_scope; ...@@ -2347,6 +2347,8 @@ extern int flag_new_for_scope;
&& DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield) && DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield)
#define SET_DECL_C_BIT_FIELD(NODE) \ #define SET_DECL_C_BIT_FIELD(NODE) \
(DECL_LANG_SPECIFIC (FIELD_DECL_CHECK (NODE))->decl_flags.bitfield = 1) (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. */ /* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
#define DECL_UNINLINABLE(NODE) \ #define DECL_UNINLINABLE(NODE) \
......
...@@ -240,7 +240,13 @@ cp_convert_to_pointer (type, expr) ...@@ -240,7 +240,13 @@ cp_convert_to_pointer (type, expr)
{ {
if (TYPE_PTRMEMFUNC_P (type)) if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0); 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; TREE_TYPE (expr) = type;
return expr; return expr;
} }
......
...@@ -65,11 +65,18 @@ cplus_expand_constant (cst) ...@@ -65,11 +65,18 @@ cplus_expand_constant (cst)
bit_position (member), bit_position (member),
bitsize_int (BITS_PER_UNIT))); bitsize_int (BITS_PER_UNIT)));
/* We offset all pointer to data members by 1 so that we if (flag_new_abi)
can distinguish between a null pointer to data member /* Under the new ABI, we use -1 to represent the NULL
and the first data member of a structure. */ pointer; non-NULL values simply contain the offset of
offset = size_binop (PLUS_EXPR, offset, size_one_node); the data member. */
cst = cp_convert (type, offset); ;
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 else
{ {
......
...@@ -1821,11 +1821,13 @@ resolve_offset_ref (exp) ...@@ -1821,11 +1821,13 @@ resolve_offset_ref (exp)
addr = convert_pointer_to (basetype, addr); addr = convert_pointer_to (basetype, addr);
member = cp_convert (ptrdiff_type_node, member); member = cp_convert (ptrdiff_type_node, member);
/* Pointer to data members are offset by one, so that a null if (!flag_new_abi)
pointer with a real value of 0 is distinguishable from an /* Pointer to data members are offset by one, so that a null
offset of the first member of a structure. */ pointer with a real value of 0 is distinguishable from an
member = build_binary_op (MINUS_EXPR, member, offset of the first member of a structure. */
cp_convert (ptrdiff_type_node, integer_one_node)); member = build_binary_op (MINUS_EXPR, member,
cp_convert (ptrdiff_type_node,
integer_one_node));
return build1 (INDIRECT_REF, type, return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, build_pointer_type (type), build (PLUS_EXPR, build_pointer_type (type),
......
...@@ -2858,7 +2858,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) ...@@ -2858,7 +2858,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
{ {
idx = build_binary_op (TRUNC_DIV_EXPR, idx = build_binary_op (TRUNC_DIV_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3), build1 (NOP_EXPR, vtable_index_type, e3),
integer_two_node); TYPE_SIZE_UNIT (vtable_entry_type));
e1 = build_binary_op (BIT_AND_EXPR, e1 = build_binary_op (BIT_AND_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3), build1 (NOP_EXPR, vtable_index_type, e3),
integer_one_node); integer_one_node);
...@@ -6332,11 +6332,12 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2) ...@@ -6332,11 +6332,12 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2)
} }
else else
{ {
/* Under the new ABI, we set PFN to twice the index, plus /* Under the new ABI, we set PFN to the vtable offset, plus
one. */ one, at which the function can be found. */
*idx = NULL_TREE; *idx = NULL_TREE;
*pfn = fold (build (MULT_EXPR, integer_type_node, *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, *pfn = fold (build (PLUS_EXPR, integer_type_node, *pfn,
integer_one_node)); integer_one_node));
*pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
......
// 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) */
...@@ -82,16 +82,16 @@ main () ...@@ -82,16 +82,16 @@ main ()
if (xp->adj != delta) if (xp->adj != delta)
return 8; return 8;
// For a virtual function, we should see twice the vtable index, // For a virtual function, we should see the vtable offset, plus
// plus one. `T::h' is in the third slot: there's the RTTI entry, // one. `T::h' is in the second slot: the vtable pointer points to
// then the two virtual functions. // the first virtual function.
y = &T::h; y = &T::h;
if ((ptrdiff_t) yp->ptr != 7) if ((ptrdiff_t) yp->ptr != sizeof (void *) + 1)
return 9; return 9;
if (yp->adj != 0) if (yp->adj != 0)
return 10; return 10;
x = (sp) y; x = (sp) y;
if ((ptrdiff_t) xp->ptr != 7) if ((ptrdiff_t) xp->ptr != sizeof (void *) + 1)
return 11; return 11;
if (xp->adj != delta) if (xp->adj != delta)
return 12; return 12;
...@@ -103,9 +103,14 @@ main () ...@@ -103,9 +103,14 @@ main ()
if (__alignof__ (sdp) != __alignof__ (ptrdiff_t)) if (__alignof__ (sdp) != __alignof__ (ptrdiff_t))
return 14; return 14;
// The value of a pointer-to-data member should be the offset from
// the start of the structure.
sdp z = &S::j; 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; return 15;
z = 0;
if (*((ptrdiff_t *) &z) != -1)
return 16;
} }
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */ #else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment