aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-05-17 07:42:26 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-05-17 07:42:26 +0000
commitc1aa4de772757f0c5afb61f8ebcf58550fc62a83 (patch)
treeb1c29c81f940d1d1cf394201e11ed95b079eafcf /gcc
parentc15398de775ea6bb100d761e7ebad03d2daec8a4 (diff)
downloadgcc-c1aa4de772757f0c5afb61f8ebcf58550fc62a83.zip
gcc-c1aa4de772757f0c5afb61f8ebcf58550fc62a83.tar.gz
gcc-c1aa4de772757f0c5afb61f8ebcf58550fc62a83.tar.bz2
call.c (build_over_call): Don't throw away initializations/copies of empty classes...
* call.c (build_over_call): Don't throw away initializations/copies of empty classes; use MODIFY_EXPR and INIT_EXPR as for non-empty classes. * class.c (finish_struct_1): Put the padding byte for an empty class on the TYPE_NONCOPIED_PARTS list for the class. From-SVN: r26970
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c40
-rw-r--r--gcc/cp/class.c19
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/empty1.C23
4 files changed, 71 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5147952..a43dedd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+1999-05-17 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_over_call): Don't throw away
+ initializations/copies of empty classes; use MODIFY_EXPR and
+ INIT_EXPR as for non-empty classes.
+ * class.c (finish_struct_1): Put the padding byte for an empty
+ class on the TYPE_NONCOPIED_PARTS list for the class.
+
1999-05-16 Mark Mitchell <mark@codesourcery.com>
* decl2.c (build_expr_from_tree): Handle COMPONENT_REFs that
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1dccabcf..496cf91 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3426,20 +3426,34 @@ build_over_call (cand, args, flags)
else if (! real_lvalue_p (arg)
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
+ tree address;
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0));
- /* Don't copy the padding byte; it might not have been allocated
- if to is a base subobject. */
- if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
- return build_unary_op
- (ADDR_EXPR, build (COMPOUND_EXPR, TREE_TYPE (to),
- cp_convert (void_type_node, arg), to),
- 0);
-
- val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
+ /* 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_CLASS_CONTEXT (fn))
+ ? MODIFY_EXPR : INIT_EXPR,
+ DECL_CONTEXT (fn), to, arg);
TREE_SIDE_EFFECTS (val) = 1;
- return build_unary_op (ADDR_EXPR, val, 0);
+ address = build_unary_op (ADDR_EXPR, val, 0);
+ /* Avoid a warning about this expression, if the address is
+ never used. */
+ TREE_USED (address) = 1;
+ return address;
}
}
else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
@@ -3451,12 +3465,6 @@ build_over_call (cand, args, flags)
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
- /* Don't copy the padding byte; it might not have been allocated
- if to is a base subobject. */
- if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
- return build (COMPOUND_EXPR, TREE_TYPE (to),
- cp_convert (void_type_node, arg), to);
-
val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
TREE_SIDE_EFFECTS (val) = 1;
return val;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1466e94..f7998c1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3133,6 +3133,7 @@ finish_struct_1 (t, warn_anon)
int aggregate = 1;
int empty = 1;
int has_pointers = 0;
+ tree inline_friends;
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
pedwarn ("anonymous class type not used to declare any objects");
@@ -3740,6 +3741,13 @@ finish_struct_1 (t, warn_anon)
if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
}
+
+ /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
+ we have to save this before we start modifying
+ TYPE_NONCOPIED_PARTS. */
+ inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
+ CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
+
if (empty)
{
/* C++: do not let empty structures exist. */
@@ -3747,7 +3755,11 @@ finish_struct_1 (t, warn_anon)
(FIELD_DECL, NULL_TREE, char_type_node);
TREE_CHAIN (decl) = fields;
TYPE_FIELDS (t) = decl;
+ TYPE_NONCOPIED_PARTS (t)
+ = tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
+ TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
+
if (n_baseclasses)
TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
@@ -4021,8 +4033,7 @@ finish_struct_1 (t, warn_anon)
}
/* Write out inline function definitions. */
- do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
- CLASSTYPE_INLINE_FRIENDS (t) = 0;
+ do_inline_function_hair (t, inline_friends);
if (CLASSTYPE_VSIZE (t) != 0)
{
@@ -4049,7 +4060,9 @@ finish_struct_1 (t, warn_anon)
/* 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) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
+ TYPE_NONCOPIED_PARTS (t)
+ = tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)),
+ vfield, TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
diff --git a/gcc/testsuite/g++.old-deja/g++.other/empty1.C b/gcc/testsuite/g++.old-deja/g++.other/empty1.C
new file mode 100644
index 0000000..0789884
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/empty1.C
@@ -0,0 +1,23 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+extern "C" void abort();
+extern "C" void printf(const char*, ...);
+
+int i;
+
+struct A;
+
+struct A* as[10];
+
+struct A {
+ A () { as[i++] = this; }
+ A (const A&) { as[i++] = this; }
+ ~A() { if (i == 0 || as[--i] != this) abort(); }
+};
+
+A f() { return A(); }
+
+int main ()
+{
+ A a (f ());
+}