This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: gcc 3.0.1 & C++ ABI issues
Jason Merrill wrote:
> Perhaps something like TYPE_UNPADDED_SIZE would make sense. Much simpler
> than TYPE_NONCOPIED_PARTS.
yeah, my thoughts exactly. Something for 3.1 though.
Thanks, for clarification on NRVO
> Yes, your change to the assignment case is good; I was only thinking about
> initialization. The case I still want to optimize is the case of
> initializing an empty class object from a temporary.
ok,
> No, that's wrong; we can't replace a copy ctor with a default ctor.
In general, you are correct. However, we have determined that the default
ctor & the copy_ctor are NO-OPs. But that was overly complex.
Here's an updated patch. I'm running a bootstrap now. Ok to install if
boots ok?
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
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.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.255.2.15
diff -c -3 -p -r1.255.2.15 call.c
*** call.c 2001/07/26 08:12:57 1.255.2.15
--- call.c 2001/08/07 10:46:12
*************** build_over_call (cand, args, flags)
*** 4245,4274 ****
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
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));
! /* 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);
address = build_unary_op (ADDR_EXPR, val, 0);
/* Avoid a warning about this expression, if the address is
never used. */
--- 4245,4263 ----
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
else if (! real_lvalue_p (arg)
! /* 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));
! 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. */
*************** build_over_call (cand, args, flags)
*** 4284,4291 ****
(build_indirect_ref (TREE_VALUE (converted_args), 0));
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
! val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
return val;
}
--- 4273,4286 ----
(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 (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to);
! }
! else
! val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
return val;
}
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.358.2.33
diff -c -3 -p -r1.358.2.33 class.c
*** class.c 2001/07/31 08:57:07 1.358.2.33
--- class.c 2001/08/07 10:46:14
*************** check_bases_and_members (t, empty_p)
*** 4646,4652 ****
|| 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);
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
--- 4646,4652 ----
|| 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_CONTAINS_VPTR_P (t);
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
*************** layout_class_type (t, empty_p, vfuns_p,
*** 5133,5140 ****
TYPE_FIELDS (t));
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
! we have to save this before we start modifying
! TYPE_NONCOPIED_PARTS. */
fixup_inline_methods (t);
/* Layout the non-static data members. */
--- 5133,5139 ----
TYPE_FIELDS (t));
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
! we have to save this before we zap TYPE_NONCOPIED_PARTS. */
fixup_inline_methods (t);
/* Layout the non-static data members. */
*************** layout_class_type (t, empty_p, vfuns_p,
*** 5232,5240 ****
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
--- 5231,5236 ----
*************** finish_struct_1 (t)
*** 5493,5512 ****
/* 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);
! }
hack_incomplete_structures (t);
--- 5489,5497 ----
/* Build the VTT for T. */
build_vtt (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);
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.572.2.32
diff -c -3 -p -r1.572.2.32 cp-tree.h
*** cp-tree.h 2001/07/25 09:37:25 1.572.2.32
--- cp-tree.h 2001/08/07 10:46:15
*************** extern int flag_new_for_scope;
*** 2593,2599 ****
#define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \
(TYPE_LANG_FLAG_4(NODE))
! /* Nonzero for class type means that 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))
--- 2593,2599 ----
#define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \
(TYPE_LANG_FLAG_4(NODE))
! /* 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))