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]

C++ PATCH: PR 15172


PR c++/15172 was a serious wrong-code regression in G++; an aggregate
initializer could result in a bitwise copy not permitted by the
standard.  As a consequence, the address at which an object was
constructed and the address at which it was destroyed could be
different.

The front-end was generating a CONSTRUCTOR containing a TARGET_EXPR,
which seems like a reasonable representation of the initializer, but
expand_expr was generating the CONSTRUCTOR as a separate object on the
stack and then copying it into the destination location.  RTH wrote
code to split out the non-constant bits of the initializer as runtime
code, but, probably due to a misleading comment in the front end, it
was not being used.  I activated this code all the time.

Tested on i686-pc-linux-gnu, applied on the 3.4 branch and on the
mainline.  The regression did not appear on the mainline, but there is
no reason not to make the same simplification to the code.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-10-31  Mark Mitchell  <mark@codesourcery.com>

	PR c++/15172
	* typeck2.c (store_init_value): Use split_nonconstant_init even
	for types that require construction.
	
2004-10-31  Mark Mitchell  <mark@codesourcery.com>

	PR c++/15172
	* g++.dg/init/aggr2.C: New test.

Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.153.4.3
diff -c -5 -p -r1.153.4.3 typeck2.c
*** cp/typeck2.c	1 Apr 2004 20:47:23 -0000	1.153.4.3
--- cp/typeck2.c	31 Oct 2004 23:47:11 -0000
*************** store_init_value (tree decl, tree init)
*** 443,474 ****
        else
  	/* We get here with code like `int a (2);' */
  	init = build_x_compound_expr_from_list (init, "initializer");
      }
  
-   /* End of special C++ code.  */
- 
    /* Digest the specified initializer into an expression.  */
    value = digest_init (type, init, (tree *) 0);
! 
!   /* Store the expression if valid; else report error.  */
! 
!   if (TREE_CODE (value) == ERROR_MARK)
!     ;
!   /* Other code expects that initializers for objects of types that need
!      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
!      when we output this function.  */
    DECL_INITIAL (decl) = value;
    return NULL_TREE;
  }
  
  
--- 443,464 ----
        else
  	/* We get here with code like `int a (2);' */
  	init = build_x_compound_expr_from_list (init, "initializer");
      }
  
    /* Digest the specified initializer into an expression.  */
    value = digest_init (type, init, (tree *) 0);
!   /* If the initializer is not a constant, fill in DECL_INITIAL with
!      the bits that are constant, and then return an expression that
!      will perform the dynamic initialization.  */
!   if (value != error_mark_node
!       && (! TREE_CONSTANT (value)
! 	  || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
      return split_nonconstant_init (decl, value);
!   /* If the value is a constant, just put it in DECL_INITIAL.  If DECL
!      is an automatic variable, the middle end will turn this into a
!      dynamic initialization later.  */
    DECL_INITIAL (decl) = value;
    return NULL_TREE;
  }
  
  
Index: testsuite/g++.dg/init/aggr2.C
===================================================================
RCS file: testsuite/g++.dg/init/aggr2.C
diff -N testsuite/g++.dg/init/aggr2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/aggr2.C	31 Oct 2004 23:47:18 -0000
***************
*** 0 ****
--- 1,46 ----
+ // PR c++/15172
+ // { dg-do run }
+ 
+ extern "C" int printf (const char *, ...);
+ extern "C" void abort ();
+ 
+ struct A {
+   static A* p;
+ 
+   A() { p = this; }
+   A(const A&);
+   ~A() { if (this != p) abort (); }
+   void print () { }
+ };
+ 
+ A* A::p;
+ 
+ struct B {
+   A a;
+ };
+ 
+ B b = { A () };
+ 
+ struct A2 {
+   static A2* p;
+ 
+   A2() { p = this; }
+   A2(const A2&);
+   ~A2() { if (this != p) abort (); }
+   void print () { }
+ };
+ 
+ A2* A2::p;
+ 
+ struct B2 {
+   A2 a2;
+ };
+ 
+ int main () {
+   b.a.print ();
+   {
+     B2 b2 = { A2() };
+     b2.a2.print ();
+   }
+ } 
+     


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