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]
Other format: [Raw text]

GCC-3.3.4 PATCH: PR 10776


There have been various attempts at fixing this PR in 3.4.x and 3.5.x by
Jan and RTH.  I've elected to backport only the fix by RTH which looks
to me as attacking the root of the problem.  Jan's patches are
interesting too, but since there are mostly middle-end and come into
stages, I've decided not to apply them.

Bootstrapped and regtested on an i686-pc-linux-gnu.

-- Gaby

Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/ChangeLog,v
retrieving revision 1.3076.2.259
diff -p -r1.3076.2.259 ChangeLog
*** ChangeLog	9 Mar 2004 16:23:42 -0000	1.3076.2.259
--- ChangeLog	12 Mar 2004 20:52:34 -0000
***************
*** 1,3 ****
--- 1,15 ----
+ 2004-03-12  Gabriel Dos Reis  <gdr@integrable-solutions.net>
+ 
+ 	Backport:
+ 	2004-01-12  Richard Henderson  <rth@redhat.com>
+ 	PR opt/10776
+ 	* typeck2.c (split_nonconstant_init_1, split_nonconstant_init): New.
+ 	(store_init_value): Use it.
+ 	* decl.c (check_initializer): Expect full initialization code
+ 	from store_init_value.
+ 	* init.c (expand_aggr_init_1): Likewise.
+ 	* decl2.c (maybe_emit_vtables): Abort if runtime init needed.
+ 
  2004-03-09  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
  
  	PR c++/14409
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.965.2.77
diff -p -r1.965.2.77 decl.c
*** decl.c	2 Mar 2004 02:49:21 -0000	1.965.2.77
--- decl.c	12 Mar 2004 20:52:43 -0000
*************** static tree
*** 8428,8433 ****
--- 8428,8434 ----
  check_initializer (tree decl, tree init, int flags, tree *cleanup)
  {
    tree type = TREE_TYPE (decl);
+   tree init_code = NULL;
  
    /* If `start_decl' didn't like having an initialization, ignore it now.  */
    if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
*************** check_initializer (tree decl, tree init,
*** 8538,8544 ****
  	{
  	dont_use_constructor:
  	  if (TREE_CODE (init) != TREE_VEC)
! 	    init = store_init_value (decl, init);
  	}
      }
    else if (DECL_EXTERNAL (decl))
--- 8539,8548 ----
  	{
  	dont_use_constructor:
  	  if (TREE_CODE (init) != TREE_VEC)
! 	    {
! 	      init_code = store_init_value (decl, init);
! 	      init = NULL;
! 	    }
  	}
      }
    else if (DECL_EXTERNAL (decl))
*************** check_initializer (tree decl, tree init,
*** 8561,8569 ****
      check_for_uninitialized_const_var (decl);
  
    if (init && init != error_mark_node)
!     init = build (INIT_EXPR, type, decl, init);
  
!   return init;
  }
  
  /* If DECL is not a local variable, give it RTL.  */
--- 8565,8573 ----
      check_for_uninitialized_const_var (decl);
  
    if (init && init != error_mark_node)
!     init_code = build (INIT_EXPR, type, decl, init);
  
!   return init_code;
  }
  
  /* If DECL is not a local variable, give it RTL.  */
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.575.2.35
diff -p -r1.575.2.35 decl2.c
*** decl2.c	8 Sep 2003 19:05:42 -0000	1.575.2.35
--- decl2.c	12 Mar 2004 20:52:45 -0000
*************** maybe_emit_vtables (tree ctype)
*** 1851,1857 ****
        import_export_vtable (vtbl, ctype, 1);
        mark_vtable_entries (vtbl);
        if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
! 	store_init_value (vtbl, DECL_INITIAL (vtbl));
  
        if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
  	{
--- 1851,1861 ----
        import_export_vtable (vtbl, ctype, 1);
        mark_vtable_entries (vtbl);
        if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
! 	{
! 	  /* It had better be all done at compile-time.  */
! 	  if (store_init_value (vtbl, DECL_INITIAL (vtbl)))
! 	    abort ();
! 	}
  
        if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
  	{
Index: init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.299.2.14
diff -p -r1.299.2.14 init.c
*** init.c	5 Feb 2004 13:22:09 -0000	1.299.2.14
--- init.c	12 Mar 2004 20:52:47 -0000
*************** expand_aggr_init_1 (binfo, true_exp, exp
*** 1286,1293 ****
        /* If store_init_value returns NULL_TREE, the INIT has been
  	 record in the DECL_INITIAL for EXP.  That means there's
  	 nothing more we have to do.  */
!       if (store_init_value (exp, init))
! 	finish_expr_stmt (build (INIT_EXPR, type, exp, init));
        return;
      }
  
--- 1286,1294 ----
        /* If store_init_value returns NULL_TREE, the INIT has been
  	 record in the DECL_INITIAL for EXP.  That means there's
  	 nothing more we have to do.  */
!       init = store_init_value (exp, init);
!       if (init)
! 	finish_expr_stmt (init);
        return;
      }
  
Index: typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.132.4.4
diff -p -r1.132.4.4 typeck2.c
*** typeck2.c	17 Sep 2003 23:48:25 -0000	1.132.4.4
--- typeck2.c	12 Mar 2004 20:52:48 -0000
*************** cxx_incomplete_type_error (value, type)
*** 296,301 ****
--- 296,403 ----
  }
  
  
+ /* The recursive part of split_nonconstant_init.  DEST is an lvalue
+    expression to which INIT should be assigned.  INIT is a CONSTRUCTOR.
+    PCODE is a pointer to the tail of a chain of statements being emitted.
+    The return value is the new tail of that chain after new statements
+    are generated.  */
+ 
+ static tree *
+ split_nonconstant_init_1 (tree dest, tree init, tree *pcode)
+ {
+   tree *pelt, elt, type = TREE_TYPE (dest);
+   tree sub, code, inner_type = NULL;
+   bool array_type_p = false;
+ 
+   pelt = &CONSTRUCTOR_ELTS (init);
+   switch (TREE_CODE (type))
+     {
+     case ARRAY_TYPE:
+       inner_type = TREE_TYPE (type);
+       array_type_p = true;
+       /* FALLTHRU */
+ 
+     case RECORD_TYPE:
+     case UNION_TYPE:
+     case QUAL_UNION_TYPE:
+       while ((elt = *pelt))
+ 	{
+ 	  tree field_index = TREE_PURPOSE (elt);
+ 	  tree value = TREE_VALUE (elt);
+ 
+ 	  if (!array_type_p)
+ 	    inner_type = TREE_TYPE (field_index);
+ 
+ 	  if (TREE_CODE (value) == CONSTRUCTOR)
+ 	    {
+ 	      if (array_type_p)
+ 	        sub = build (ARRAY_REF, inner_type, dest, field_index);
+ 	      else
+ 	        sub = build (COMPONENT_REF, inner_type, dest, field_index);
+ 
+ 	      pcode = split_nonconstant_init_1 (sub, value, pcode);
+ 	    }
+ 	  else if (!initializer_constant_valid_p (value, inner_type))
+ 	    {
+ 	      *pelt = TREE_CHAIN (elt);
+ 
+ 	      if (array_type_p)
+ 	        sub = build (ARRAY_REF, inner_type, dest, field_index);
+ 	      else
+ 	        sub = build (COMPONENT_REF, inner_type, dest, field_index);
+ 
+ 	      code = build (MODIFY_EXPR, inner_type, sub, value);
+ 	      code = build_stmt (EXPR_STMT, code);
+ 
+ 	      *pcode = code;
+ 	      pcode = &TREE_CHAIN (code);
+ 	      continue;
+ 	    }
+ 	  pelt = &TREE_CHAIN (elt);
+ 	}
+       break;
+ 
+     case VECTOR_TYPE:
+       if (!initializer_constant_valid_p (init, type))
+ 	{
+ 	  CONSTRUCTOR_ELTS (init) = NULL;
+ 	  code = build (MODIFY_EXPR, type, dest, init);
+ 	  code = build_stmt (EXPR_STMT, code);
+ 	  pcode = &TREE_CHAIN (code);
+ 	}
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+   return pcode;
+ }
+ 
+ /* A subroutine of store_init_value.  Splits non-constant static 
+    initializer INIT into a constant part and generates code to
+    perform the non-constant part of the initialization to DEST.
+    Returns the code for the runtime init.  */
+ 
+ static tree
+ split_nonconstant_init (tree dest, tree init)
+ {
+   tree code;
+ 
+   if (TREE_CODE (init) == CONSTRUCTOR)
+     {
+       code = build_stmt (COMPOUND_STMT, NULL_TREE);
+       split_nonconstant_init_1 (dest, init, &COMPOUND_BODY (code));
+       code = build1 (STMT_EXPR, void_type_node, code);
+       TREE_SIDE_EFFECTS (code) = 1;
+       DECL_INITIAL (dest) = init;
+     }
+   else
+     code = build (INIT_EXPR, TREE_TYPE (dest), dest, init);
+ 
+   return code;
+ }
+ 
  /* Perform appropriate conversions on the initial value of a variable,
     store it in the declaration DECL,
     and print any error messages that are appropriate.
*************** cxx_incomplete_type_error (value, type)
*** 311,319 ****
     into a CONSTRUCTOR and use standard initialization techniques.
     Perhaps a warning should be generated?
  
!    Returns value of initializer if initialization could not be
!    performed for static variable.  In that case, caller must do
!    the storing.  */
  
  tree
  store_init_value (decl, init)
--- 413,420 ----
     into a CONSTRUCTOR and use standard initialization techniques.
     Perhaps a warning should be generated?
  
!    Returns code to be executed if initialization could not be performed
!    for static variable.  In that case, caller must emit the code.  */
  
  tree
  store_init_value (decl, init)
*************** store_init_value (decl, init)
*** 385,395 ****
       constructing never make it into DECL_INITIAL, and passes 'init' to
       build_aggr_init without checking DECL_INITIAL.  So just return.  */
    else if (TYPE_NEEDS_CONSTRUCTING (type))
!     return value;
    else if (TREE_STATIC (decl)
  	   && (! TREE_CONSTANT (value)
  	       || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
!     return value;
    
    /* Store the VALUE in DECL_INITIAL.  If we're building a
       statement-tree we will actually expand the initialization later
--- 486,496 ----
       constructing never make it into DECL_INITIAL, and passes 'init' to
       build_aggr_init without checking DECL_INITIAL.  So just return.  */
    else if (TYPE_NEEDS_CONSTRUCTING (type))
!     return build (INIT_EXPR, type, decl, value);
    else if (TREE_STATIC (decl)
  	   && (! TREE_CONSTANT (value)
  	       || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
!     return split_nonconstant_init (decl, value);
    
    /* Store the VALUE in DECL_INITIAL.  If we're building a
       statement-tree we will actually expand the initialization later


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