[cfe-dev] [Bug] Destructor of temporary objects bound to reference variable not called in expected order.

suyog sarda sardask01 at gmail.com
Sun Jul 6 21:57:45 PDT 2014


Hi Richard,

Thanks for the reply.




On Mon, Jul 7, 2014 at 9:38 AM, Richard Smith <richard at metafoo.co.uk> wrote:

> On Tue, Jul 1, 2014 at 2:22 AM, suyog sarda <sardask01 at gmail.com> wrote:
>
>> Hi,
>>
>> This is a gcc test case
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> *extern "C" int printf (const char *, ...); int c;int r;struct A{   A() {
>> printf ("A()\n"); if (c++) r = 1; }  A(const A&) { printf ("A(const
>> A&)\n"); ++c; }  ~A() { printf ("~A()\n"); --c; }};struct B{  B(int, const
>> A& = A()) { printf ("B()\n"); } };int main(){  B b[] = { 0, 1 };  return
>> r;}*
>>
>> Output from Clang (latest trunk):
>>
>>
>>
>>
>>
>>
>> *A()B()A()B()~A()~A()*
>>
>> Output from gcc 4.8 :
>>
>>
>>
>>
>>
>>
>> *A() B()~A()A()B()~A() *
>>
>> As we can see, the destructor of temporary objects are not called
>> immediately in case of clang.
>> The temporary A passed to the constructor for b[0] should have been
>> destroyed before going on to construct b[1].
>>
>> According to standards,
>>
>> The temporary to which the reference is bound or the temporary that is
>> the complete object of a subobject to which the reference is bound persists
>> for the lifetime of the reference except:
>> -- A temporary bound to a reference member in a constructor's
>> ctor-initializer ( 12.6.2) persists until the constructor exits.
>> -- A temporary bound to a reference parameter in a function call ( 5.2.2)
>> persists until the completion of the full-expression containing the call.
>>
>> So even though A's temporary is bound to reference, it should get
>> destroyed as soon as b[0] gets constructed before going forward to
>> construct b[1].
>>
>
> We (incorrectly, per the C++ standard) treat top-level aggregate
> initialization as a full-expression. However, I'm not entirely convinced
> that this is a bug in Clang rather than a bug in the standard, especially
> in C++11. As a demonstration of why this might be a standard defect:
>
> typedef B BA[];
>
> void f() {
>   BA x = { 1, 2 }; // A(), B(), ~A(), A(), B(), ~A()
>   auto &&y = BA { 1, 2 }; // A(), B(), A(), B(), ~A(), ~A()
> } // ~B(), ~B(), ~B(), ~B()
>
> This seems similar to http://llvm.org/bugs/show_bug.cgi?id=16476
>>
>
> It looks similar, but I think they're completely separate. That issue is
> about end-of-scope cleanups and interleaving of lifetime-extended
> temporaries with array elements. In this case, there is no
> lifetime-extension.
>

Even i noted while debugging that when it checks for lifetime extension, it
returns a nullptr, which indicates, it isn't extending lifetime of the
temporary.


>
> Richard, any comment/help on this from you will be most welcomed (Since
>> bug 16476 was filed by you :)). Does this require major change in code and
>> handling of temporaries?
>>
>
> It would probably be straightforward to track where the full-expression
> boundaries actually are during IR generation. As noted above, I'm not yet
> convinced that Clang is the right place to fix this. =)
>

I will try to look into IR generation and update if any new findings on
this.


>
>
>> Is this also related to
>> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1634 ?
>>
>
> Not in this instance, but there are nearby issues that are related (in
> particular, destruction order if a temporary's destructor throws).
>

Thanks for your valuable review. :)

-- 
With regards,
Suyog Sarda
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140707/85adf7b2/attachment.html>


More information about the cfe-dev mailing list