This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]