diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2001-08-07 13:57:06 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2001-08-07 13:57:06 +0000 |
commit | 0830ae44cd7f243964cf767561525e0ba194676f (patch) | |
tree | be17021c95979d0552d64010022af0cefd41ff1d /gcc/cp | |
parent | 24a285841212403389646af2198d1a34fd0b01e6 (diff) | |
download | gcc-0830ae44cd7f243964cf767561525e0ba194676f.zip gcc-0830ae44cd7f243964cf767561525e0ba194676f.tar.gz gcc-0830ae44cd7f243964cf767561525e0ba194676f.tar.bz2 |
re PR c++/3820 (GCC 3.0 crashes with empty base class)
cp:
PR c++/3820
Stop using TYPE_NONCOPIED_PARTS.
* call.c (build_over_call): Be careful when copy constructing
or assigning to an empty class.
* class.c (check_bases_and_members): It has a
COMPLEX_ASSIGN_REF if it has a vptr.
(layout_class_type): Don't add empty class padding to
TYPE_NONCOPIED_PARTS.
(finish_struct_1): Don't add the VFIELD either.
* cp-tree.h (TYPE_HAS_TRIVIAL_INIT_REF): Mention _copy_
initialization.
testsuite:
* g++.dg/abi/empty4.C: New test.
From-SVN: r44691
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/call.c | 35 | ||||
-rw-r--r-- | gcc/cp/class.c | 25 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 |
4 files changed, 35 insertions, 41 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dbde805..b2d3d3c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2001-08-07 Nathan Sidwell <nathan@codesourcery.com> + + PR c++/3820 + Stop using TYPE_NONCOPIED_PARTS. + * call.c (build_over_call): Be careful when copy constructing + or assigning to an empty class. + * class.c (check_bases_and_members): It has a + COMPLEX_ASSIGN_REF if it has a vptr. + (layout_class_type): Don't add empty class padding to + TYPE_NONCOPIED_PARTS. + (finish_struct_1): Don't add the VFIELD either. + * cp-tree.h (TYPE_HAS_TRIVIAL_INIT_REF): Mention _copy_ + initialization. + 2001-08-07 Jason Merrill <jason_merrill@redhat.com> * tree.c (walk_tree): Walk siblings even if !walk_subtrees. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index bbe6c48..6278095 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4259,30 +4259,19 @@ build_over_call (cand, args, flags) return build_target_expr_with_type (arg, DECL_CONTEXT (fn)); } else if (! real_lvalue_p (arg) - || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) + /* Empty classes have padding which can be hidden + inside an (empty) base of the class. This must not + be touched as it might overlay things. When the + gcc core learns about empty classes, we can treat it + like other classes. */ + || (!is_empty_class (DECL_CONTEXT (fn)) + && TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))) { tree address; tree to = stabilize_reference (build_indirect_ref (TREE_VALUE (args), 0)); - /* If we're initializing an empty class, then we actually - have to use a MODIFY_EXPR rather than an INIT_EXPR. The - reason is that the dummy padding member in the target may - not actually be allocated if TO is a base class - subobject. Since we've set TYPE_NONCOPIED_PARTS on the - padding, a MODIFY_EXPR will preserve its value, which is - the right thing to do if it's not really padding at all. - - It's not safe to just throw away the ARG if we're looking - at an empty class because the ARG might contain a - TARGET_EXPR which wants to be bound to TO. If it is not, - expand_expr will assign a dummy slot for the TARGET_EXPR, - and we will call a destructor for it, which is wrong, - because we will also destroy TO, but will never have - constructed it. */ - val = build (is_empty_class (DECL_CONTEXT (fn)) - ? MODIFY_EXPR : INIT_EXPR, - DECL_CONTEXT (fn), to, arg); + val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg); address = build_unary_op (ADDR_EXPR, val, 0); /* Avoid a warning about this expression, if the address is never used. */ @@ -4298,8 +4287,14 @@ build_over_call (cand, args, flags) (build_indirect_ref (TREE_VALUE (converted_args), 0)); arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0); + if (is_empty_class (TREE_TYPE (to))) + { + TREE_USED (arg) = 1; - val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg); + val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to); + } + else + val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg); return val; } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 42c03713..a187bc3 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4386,7 +4386,7 @@ check_bases_and_members (t, empty_p) || TYPE_HAS_ASSIGN_REF (t)); TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); TYPE_HAS_COMPLEX_ASSIGN_REF (t) - |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); + |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t); /* Synthesize any needed methods. Note that methods will be synthesized for anonymous unions; grok_x_components undoes that. */ @@ -4877,8 +4877,7 @@ layout_class_type (t, empty_p, vfuns_p, CLASSTYPE_NEARLY_EMPTY_P (t) = 0; /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus, - we have to save this before we start modifying - TYPE_NONCOPIED_PARTS. */ + we have to save this before we zap TYPE_NONCOPIED_PARTS. */ fixup_inline_methods (t); /* Layout the non-static data members. */ @@ -4974,9 +4973,6 @@ layout_class_type (t, empty_p, vfuns_p, padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node); place_field (rli, padding); - TYPE_NONCOPIED_PARTS (t) - = tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t)); - TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1; } /* Let the back-end lay out the type. Note that at this point we @@ -5233,20 +5229,9 @@ finish_struct_1 (t) /* Build the VTT for T. */ build_vtt (t); - if (TYPE_VFIELD (t)) - { - /* In addition to this one, all the other vfields should be listed. */ - /* Before that can be done, we have to have FIELD_DECLs for them, and - a place to find them. */ - TYPE_NONCOPIED_PARTS (t) - = tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)), - TYPE_VFIELD (t), TYPE_NONCOPIED_PARTS (t)); - - if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t) - && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE) - cp_warning ("`%#T' has virtual functions but non-virtual destructor", - t); - } + if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t) + && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE) + cp_warning ("`%#T' has virtual functions but non-virtual destructor", t); hack_incomplete_structures (t); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0bc60ae..fd079d2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2469,7 +2469,7 @@ extern int flag_new_for_scope; #define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \ (TYPE_LANG_FLAG_4(NODE)) -/* Nonzero for class type means that initialization of this type can use +/* Nonzero for class type means that copy initialization of this type can use a bitwise copy. */ #define TYPE_HAS_TRIVIAL_INIT_REF(NODE) \ (TYPE_HAS_INIT_REF (NODE) && ! TYPE_HAS_COMPLEX_INIT_REF (NODE)) |