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
This commit is contained in:
parent
24a2858412
commit
0830ae44cd
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
|
@ -1,3 +1,7 @@
|
||||
2001-08-07 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* g++.dg/abi/empty4.C: New test.
|
||||
|
||||
2001-08-06 David Billinghurst <David.Billinghurst@riotinto.com>
|
||||
|
||||
* g77.f-torture/execute/f90-intrinsic-bit.x: XFAIL on irix6.* and
|
||||
|
86
gcc/testsuite/g++.dg/abi/empty4.C
Normal file
86
gcc/testsuite/g++.dg/abi/empty4.C
Normal file
@ -0,0 +1,86 @@
|
||||
// { dg-do run }
|
||||
|
||||
// Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
// Contributed by Nathan Sidwell 31 Jul 2001 <nathan@codesourcery.com>
|
||||
|
||||
// Bug 3820. We were bit copying empty bases including the
|
||||
// padding. Which clobbers whatever they overlay.
|
||||
|
||||
struct Empty {};
|
||||
|
||||
struct Inter : Empty {};
|
||||
|
||||
int now = 0;
|
||||
|
||||
struct NonPod
|
||||
{
|
||||
int m;
|
||||
|
||||
NonPod () {m = 0x12345678;}
|
||||
NonPod (int m_) {m = m_;}
|
||||
NonPod &operator= (NonPod const &src) {now = m; m = src.m;}
|
||||
NonPod (NonPod const &src) {m = src.m;}
|
||||
};
|
||||
|
||||
struct A : Inter
|
||||
{
|
||||
A (int c) {m = c;}
|
||||
|
||||
NonPod m;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
Inter empty;
|
||||
NonPod m;
|
||||
|
||||
B (int c) {m = c;}
|
||||
};
|
||||
|
||||
struct C : NonPod, Inter
|
||||
{
|
||||
C (int c) : NonPod (c), Inter () {}
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
A a (0x12131415);
|
||||
|
||||
int was = a.m.m;
|
||||
|
||||
a = 0x22232425;
|
||||
|
||||
if (was != now)
|
||||
return 1; // we copied the empty base which clobbered a.m.m's
|
||||
// original value.
|
||||
|
||||
A b (0x32333435);
|
||||
*(Inter *)&a = *(Inter *)&b;
|
||||
|
||||
if (a.m.m != 0x22232425)
|
||||
return 2; // we copied padding, which clobbered a.m.m
|
||||
|
||||
A b2 (0x32333435);
|
||||
(Inter &)b2 = Inter ();
|
||||
if (b2.m.m != 0x32333435)
|
||||
return 2; // we copied padding, which clobbered b2.m.m
|
||||
|
||||
B c (0x12131415);
|
||||
was = c.m.m;
|
||||
c = 0x22232425;
|
||||
if (was != now)
|
||||
return 3;
|
||||
|
||||
B d (0x32333435);
|
||||
c.empty = d.empty;
|
||||
|
||||
if (c.m.m != 0x22232425)
|
||||
return 4;
|
||||
|
||||
C e (0x32333435);
|
||||
|
||||
if (e.m != 0x32333435)
|
||||
return 2; // we copied padding
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user