diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-05-17 07:42:26 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-05-17 07:42:26 +0000 |
commit | c1aa4de772757f0c5afb61f8ebcf58550fc62a83 (patch) | |
tree | b1c29c81f940d1d1cf394201e11ed95b079eafcf /gcc | |
parent | c15398de775ea6bb100d761e7ebad03d2daec8a4 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/call.c | 40 | ||||
-rw-r--r-- | gcc/cp/class.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/empty1.C | 23 |
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 ()); +} |