aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-08-07 13:57:06 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2001-08-07 13:57:06 +0000
commit0830ae44cd7f243964cf767561525e0ba194676f (patch)
treebe17021c95979d0552d64010022af0cefd41ff1d /gcc/cp
parent24a285841212403389646af2198d1a34fd0b01e6 (diff)
downloadgcc-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/ChangeLog14
-rw-r--r--gcc/cp/call.c35
-rw-r--r--gcc/cp/class.c25
-rw-r--r--gcc/cp/cp-tree.h2
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))