diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-03-19 05:22:04 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-03-19 05:22:04 +0000 |
commit | ad63a0fca1c16a7b56f4f29888a87ee535cb9f4c (patch) | |
tree | 27221340a82ba130909a03491572338e80e9b132 | |
parent | 562b698d89a7c68dd22d8452a67bd34e4e65871f (diff) | |
download | gcc-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/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/class.c | 61 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 8 | ||||
-rw-r--r-- | gcc/cp/expr.c | 17 | ||||
-rw-r--r-- | gcc/cp/init.c | 12 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.abi/empty.C | 68 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C | 17 |
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) */ |