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]

C++ PATCH: Fix PR2372



This was an obscure tree-based inlining bug.  We had a function that
took a `const S' where `S' was a class with a constructor.  If we
compile that function out-of-line, we construct the object in the
caller, and pass a pointer, which means that the structure is readonly
in the callee, so we set TREE_READONLY on the PARM_DECL.  

When we inline, we make a corresponding VAR_DECL, and run the
constructor on this VAR_DECL.  Even if the PARM_DECL is TREE_READONLY,
this VAR_DECL is certainly not; the construcotr is going to scribble
all over it.  So, we must not set TREE_READONLY on it.

Otherwise, the optimizer may make invalid assumptions; in this case it
decided it could interchange a read and a write from the constructed
object, with predictable results.

Tested on i686-pc-linux-gnu, installed on the branch and on the
mainline.

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

2001-05-22  Mark Mitchell  <mark@codesourcery.com>

	* optimize.c (initialize_inlined_parameters): Don't set
	TREE_READONLY for a VAR_DECL taking the place of an inlined
	PARM_DECL.

Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/optimize.c,v
retrieving revision 1.51.2.17
diff -c -p -r1.51.2.17 optimize.c
*** optimize.c	2001/05/20 13:41:07	1.51.2.17
--- optimize.c	2001/05/23 02:04:29
*************** initialize_inlined_parameters (id, args,
*** 498,503 ****
--- 498,515 ----
  	DECL_INITIAL (var) = value;
        else
  	{
+ 	  /* Even if P was TREE_READONLY, the new VAR should not be.
+ 	     In the original code, we would have constructed a
+ 	     temporary, and then the function body would have never
+ 	     changed the value of P.  However, now, we will be
+ 	     constructing VAR directly.  The constructor body may
+ 	     change its value multiple times as it is being
+ 	     constructed.  Therefore, it must not be TREE_READONLY;
+ 	     the back-end assumes that TREE_READONLY variable is
+ 	     assigned to only once.  */
+ 	  TREE_READONLY (var) = 0;
+ 
+ 	  /* Build a run-time initialization.  */
  	  init_stmt = build_stmt (EXPR_STMT,
  				  build (INIT_EXPR, TREE_TYPE (p),
  					 var, value));
Index: testsuite/g++.old-deja/g++.other/inline21.C
===================================================================
RCS file: inline21.C
diff -N inline21.C
*** /dev/null	Tue May  5 13:32:27 1998
--- inline21.C	Tue May 22 19:04:26 2001
***************
*** 0 ****
--- 1,39 ----
+ // Special g++ Options: -O2
+ // Origin: suckfish@ihug.co.nz
+ 
+ // DECLARATIONS
+ 
+ struct Record {
+    Record (int bb) :
+       b (bb)
+       { }
+    int extra;   // Having an extra member in record is crucial.
+    int b;
+ };
+       
+ struct Container {
+    Record record;
+    // The const on the next line is crucial.
+    Container ( const Record  b) : record(b) {}
+ };
+ 
+ 
+ // TEST FOR CORRECT BEHAVIOUR
+ 
+ int myArray[3];
+ int * intp = myArray;
+ 
+ void use_pair (const Container & c)
+ {
+    *intp++ = c.record.b;
+ }
+ 
+ extern "C" int printf (const char *,...);
+ 
+ int main()
+ {
+   use_pair (Container (1234));
+ 
+   if (myArray[0] != 1234)
+     return 1;
+ }


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