[cfe-commits] [patch] Bug 5077

Douglas Gregor dgregor at apple.com
Mon Oct 12 09:24:22 PDT 2009


Hi Dimitri,

On Oct 8, 2009, at 11:54 PM, Dimitri Tcaciuc wrote:

> The attached is the proposed fix and test case for 5077.

Thank you! Some comments below.

> I've discussed it for some time on IRC and it seems this is not a
> perfect solution, however at this point I'm a bit stumped to find an
> alternative and I figured I would get more results with mail list
> discussions. The train of thought is the following:
>
> * Member initializers can accept one or more expressions which can
> emit temporaries that need to be cleaned up.

Right.

>   * Assuming expressions are correctly generated and use
> EmitCXXExprWithTemporaries, can we assume that there can only be one
> leftover temporary per argument?

I don't think we can assume that. Any given argument could involve  
computing many temporaries. For example, our initializer could be

	std::string() + "hello" + ", " + world

which has 4 temporaries.

> * The temporary needs to persist until after member constructor call.

Specifically, until the end of the "full expression", which is the  
member initializer itself. It doesn't have to be a constructor call to  
have temporaries.

> * CXXBaseOrMemberInitializer is not an Expr and cannot be wrapped
> with EmitCXXExprWithTemporaries

Right.

> * (?) There should be no meaningful temporaries left after member
> initializer completes.

Temporaries can live after the member initializer completes if they  
were bound to a reference member (12.2p5). In this case, the  
temporaries are destroyed at the end of the constructor.

> Thus, we can do the same thing as in EmitCXXExprWithTemporaries , that
> is perform a check right after member constructor completes and any
> new live temporaries still kicking around are safe to dispose of.
>
> Started nibbling on clang only a relatively short time ago, so
> comments and guidance are much appreciated!

I think your approach is right. However, I think that the cleanup code

+          // Cleaning up whatever temporaries occurred due to
+          // argument expressions to member intializer.
+          while (LiveTemporaries.size() > OldNumLiveTemporaries) {
+            PopCXXTemporary();
+          }

is in the wrong place, since temporaries can be created for base-class  
initializers and member initializers that don't involve constructor  
calls, in addition to the case you're currently handling. I suggest  
putting this temporary-cleanup code at the end of the "for" loop  
(which you'll need to restructure a little bit due to the "continue"),  
so that we handle temporaries the same way for the various different  
kinds of ctor-initializers.

I've attached an executable test case that shows some temporaries  
being created when the members are not class types. I believe that the  
current output is:

Before construction
Default-constructed X<1>
Destroyed X<1>
Default-constructed X<2>
Default-constructed X<3>
Destroyed X<3>
Default-constructed X<4>
In constructor body
Destroyed X<4>
Before destruction
Destroyed X<2>

Although GCC 4.2 seems to be destroying the temporary bound to  
HasMembers::i4 too early (it happens before "In constructor body").

Thanks for working on this!

	- Doug

-------------- next part --------------
A non-text attachment was scrubbed...
Name: meminit.cpp
Type: application/octet-stream
Size: 575 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20091012/cc04d67d/attachment.obj>


More information about the cfe-commits mailing list