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: Useless code generated by gcc 2.95.2????



	What follows is a summary of discussions between Martin and
myself which have uncovered a cleaner way to handle call's to new.

	I'm also willing to try my hand at implementing the change but
I could definitely use a few pointers.

>>>>> "ML" == Martin v Loewis <martin@mira.isdn.cs.tu-berlin.de> writes:

>> I don't think some of the extra code is caused by a bug, but rather
>> the addition of a feature.  LL5 non-removal however is a bug, that
>> I suspect someone introduced.  A binary search of cvs could tell
>> how broke it and how they broke it.  That would then prompt them
>> into fixing it (maybe).

ML> Indeed. As we've found later on, the mainline *does* remove the
ML> additional __builtin_delete call.

ML> I'm not sure whether this really is a regression over egcs 1.1 -
ML> in egcs 1.1, the processing of the implicit call to the
ML> deallocator was quite different. So it may not be the case that
ML> egcs 2.9x (with x>3, x<6) ever did the right thing. FWIW, the
ML> change activating the current front-end behavior was

ML> 1998-10-22 Martin von Löwis <loewis@informatik.hu-berlin.de>

ML> * init.c (build_new_1): Delay cleanup until end of full
ML> 	  expression.


	Martin and I have discussed the reasons behind the change
introduced above.  It concerns the life span of temporaries in the
call to a constructor called via new who's results is a parameter to a
function call.  Here is the example we used:


f(new Foo(A(), B(), ...), ...);

	In particular the lifespan of A, B must extend until
'f' returns (which wasn't true in egcs 1.1).  This turns out to be
very tricky to accomplish given the requirement that any memory
allocated by new must be deallocated if, Foo::Foo, A::A, or B::B throw
an error.  This is because in the simplest expansion of this code:

	 {
	   Foo *tmp = ::new(sizeof(Foo), ...);
   +- +-
   |  |	   A a();
   |  1	   B b();
   2  |	   Foo::Foo(tmp, a, b, ...);
   |  +-
   |       f(tmp, ...)
   +-----}

	You need to catch and delete 'tmp' in region 1 but the
lifespan of a & b needs to be '2'.  This is not trivial (possible?) to
communicate to the back end, and it is impossible for normal C++ code
to generate such a situation.

	The patch referenced above introduced a sentry variable which
prevented the error handler from deleting the allocated memory after
region 1 completed, although the error handler was in effect for all
of region 2.

	Fortunately, the C++ standard allows you some freedom in
rewriting this simple version of the code, in particular you are free
to rearrange the call to new with the construction of parameters for
the constructor [see 5.3.4 sec 21 in final C++ Spec (sec 22 in CD2)]:

	    Whether the allocation function is called before
	evaluating the constructor arguments or after evaluating the
	constructor arguments but before entering the constructor is
	unspecified. It is also unspecified whether the arguments to a
	constructor are evaluated if the allocation function returns
	the null pointer or exits using an exception.

Given this we can safely rewrite the above code as:

{
  A a();
  B b();

  Foo *tmp = ::new(sizeof(Foo), ...);
  try {
    Foo::Foo(tmp, a, b);
  } catch(...) {
   ::delete(tmp, ...);
  }

  f(tmp, ...);
}

	In this case if the construction of 'a', or 'b' throws an
error you don't need to catch the error and free the memory since you
haven't allocated it yet!!!

	This should (hopefully) lead to much less convoluted code in
all cases.  However, now that I have a possible solution I would
appreciate pointers to any places where similar sorts of rewriting are
done, as well as where in the c++ font end such rewriting should be
done.

	Any help and or comments are appreciated.

-- 
							Thomas DeWeese
deweese@kodak.com
			"The only difference between theory and practice is
			 that in theory there isn't any." -- unknown


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