This is the mail archive of the gcc-patches@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: [c++] gcc-2.96(today) broken ctor-initializers



Here's a patch to undo some of the damage I've done over the last
couple of days. :-) 

This should fix the problem Loring reported with conditional
expressions, the one Benjamin reported with member initializers, and
one bad conversion bug I found all by myself.

The way we were handling default initialization was truly obscure; we
were finding that we were initializing a class without constructors,
then called its constructor (passing it a CONSTRUCTOR), which caused
us to create myriad TARGET_EXPRs all of which we then cleverly
optimized away to get back where we started.  Nifty, but not as
circumspect as one might hope for.  :-) Now, we just build an
INIT_EXPR and get on with life.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-07-28  Mark Mitchell  <mark@codesourcery.com>

	* call.c (conditional_conversion): Don't build BASE_CONVs for
	conversions between things that have the same type.
	(build_conditional_expr): Tweak.
	(convert_like): Some BASE_CONVs really do require the generation
	of code.
	
	* init.c (perform_member_init): Don't go through build_modify_expr
	for simple initializations.

Index: cond2.C
===================================================================
RCS file: cond2.C
diff -N cond2.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- cond2.C	Wed Jul 28 01:09:48 1999
***************
*** 0 ****
--- 1,11 ----
+ // Build don't link:
+ // Origin: Loring Holden <lsh@cs.brown.edu>
+ 
+ class Wpt {};
+ 
+ class RAYhit {
+    protected:
+       Wpt       _nearpt;
+    public:
+       Wpt       surf        () const { return true ? Wpt(): _nearpt; } 
+ };
Index: init14.C
===================================================================
RCS file: init14.C
diff -N init14.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- init14.C	Wed Jul 28 01:09:48 1999
***************
*** 0 ****
--- 1,22 ----
+ // Build don't link:
+ // Origin: bkoz@nabi.net
+ 
+ typedef struct
+ {
+   int count;
+ } mbstate_t;
+ 
+ struct fpos
+ {
+   mbstate_t  _M_st;
+   fpos(int __pos)
+     : _M_st() { 
+   }
+ };
+ 
+ int main ()
+ {
+   fpos f (2);
+ }
+ 
+ 
Index: ref3.C
===================================================================
RCS file: ref3.C
diff -N ref3.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- ref3.C	Wed Jul 28 01:09:48 1999
***************
*** 0 ****
--- 1,30 ----
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ struct B1
+ {
+   int i;
+ };
+ 
+ struct B2
+ {
+   int j;
+ };
+ 
+ struct D: public B1, B2 
+ {
+ };
+ 
+ bool f (B2& b)
+ {
+   return b.j == 7;
+ }
+ 
+ int main ()
+ {
+   D d;
+   d.i = 2;
+   d.j = 7;
+   if (!f (d))
+     return 1;
+ }
+ 
Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.153
diff -c -p -r1.153 call.c
*** call.c	1999/07/26 18:12:15	1.153
--- call.c	1999/07/28 07:53:35
*************** conditional_conversion (e1, e2)
*** 2716,2722 ****
        if (at_least_as_qualified_p (t2, t1))
  	{
  	  conv = build1 (IDENTITY_CONV, t1, e1);
! 	  conv = build_conv (BASE_CONV, t2, conv);
  	  return conv;
  	}
        else
--- 2716,2724 ----
        if (at_least_as_qualified_p (t2, t1))
  	{
  	  conv = build1 (IDENTITY_CONV, t1, e1);
! 	  if (!same_type_p (TYPE_MAIN_VARIANT (t1), 
! 			    TYPE_MAIN_VARIANT (t2)))
! 	    conv = build_conv (BASE_CONV, t2, conv);
  	  return conv;
  	}
        else
*************** build_conditional_expr (arg1, arg2, arg3
*** 2865,2875 ****
--- 2867,2888 ----
        else if (conv2 && !ICS_BAD_FLAG (conv2))
  	{
  	  arg2 = convert_like (conv2, arg2);
+ 	  /* That may not quite have done the trick.  If the two types
+ 	     are cv-qualified variants of one another, we will have
+ 	     just used an IDENTITY_CONV.  (There's no conversion from
+ 	     an lvalue of one class type to an lvalue of another type,
+ 	     even a cv-qualified variant, and we don't want to lose
+ 	     lvalue-ness here.)  So, we manually add a NOP_EXPR here
+ 	     if necessary.  */
+ 	  if (!same_type_p (TREE_TYPE (arg2), arg3_type))
+ 	    arg2 = build1 (NOP_EXPR, arg3_type, arg2);
  	  arg2_type = TREE_TYPE (arg2);
  	}
        else if (conv3 && !ICS_BAD_FLAG (conv3))
  	{
  	  arg3 = convert_like (conv3, arg3);
+ 	  if (!same_type_p (TREE_TYPE (arg3), arg2_type))
+ 	    arg2 = build1 (NOP_EXPR, arg2_type, arg3);
  	  arg3_type = TREE_TYPE (arg3);
  	}
      }
*************** convert_like (convs, expr)
*** 3647,3658 ****
  	return expr;
        /* else fall through */
      case BASE_CONV:
!       if (TREE_CODE (convs) == BASE_CONV
! 	  && !NEED_TEMPORARY_P (convs))
! 	/* We are going to bind a reference directly to a base-class
! 	   subobject of EXPR.  We don't have to generate any code
! 	   here.  */
! 	return expr;
        {
  	tree cvt_expr = build_user_type_conversion
  	  (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
--- 3660,3678 ----
  	return expr;
        /* else fall through */
      case BASE_CONV:
!       if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs))
! 	{
! 	  /* We are going to bind a reference directly to a base-class
! 	     subobject of EXPR.  */
! 	  tree base_ptr = build_pointer_type (TREE_TYPE (convs));
! 
! 	  /* Build an expression for `*((base*) &expr)'.  */
! 	  expr = build_unary_op (ADDR_EXPR, expr, 0);
! 	  expr = perform_implicit_conversion (base_ptr, expr);
! 	  expr = build_indirect_ref (expr, "implicit conversion");
! 	  return expr;
! 	}
! 
        {
  	tree cvt_expr = build_user_type_conversion
  	  (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.114
diff -c -p -r1.114 init.c
*** init.c	1999/07/26 08:18:17	1.114
--- init.c	1999/07/28 07:53:37
*************** perform_member_init (member, name, init,
*** 194,206 ****
  	    {
  	      /* default-initialization.  */
  	      if (AGGREGATE_TYPE_P (type))
- 		init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
-  	      else if (TREE_CODE (type) == REFERENCE_TYPE)
  		{
! 		  cp_error ("default-initialization of `%#D', which has reference type",
! 			    member);
! 		  init = error_mark_node;
  		}
  	      else
  		init = integer_zero_node;
  	    }
--- 195,215 ----
  	    {
  	      /* default-initialization.  */
  	      if (AGGREGATE_TYPE_P (type))
  		{
! 		  /* This is a default initialization of an aggregate,
! 		     but not one of non-POD class type.  We cleverly
! 		     notice that the initialization rules in such a
! 		     case are the same as for initialization with an
! 		     empty brace-initialization list.  We don't want
! 		     to call build_modify_expr as that will go looking
! 		     for constructors and such.  */
! 		  tree e = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
! 		  TREE_SIDE_EFFECTS (e) = 1;
! 		  expand_expr_stmt (build (INIT_EXPR, type, decl, e));
  		}
+  	      else if (TREE_CODE (type) == REFERENCE_TYPE)
+ 		cp_error ("default-initialization of `%#D', which has reference type",
+ 			  member);
  	      else
  		init = integer_zero_node;
  	    }
*************** perform_member_init (member, name, init,
*** 221,232 ****
  	    init = TREE_VALUE (init);
  	}
  
!       /* We only build this with a null init if we got it from the
! 	 current_member_init_list.  */
!       if (init || explicit)
! 	{
! 	  expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
! 	}
      }
  
    expand_end_target_temps ();
--- 230,237 ----
  	    init = TREE_VALUE (init);
  	}
  
!       if (init)
! 	expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
      }
  
    expand_end_target_temps ();


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