On Fri, 25 Jan 2019 23:08:52 +0000, kinke wrote: > On Friday, 25 January 2019 at 19:08:55 UTC, Walter Bright wrote: >> On 1/25/2019 2:57 AM, kinke wrote: >>> On Thursday, 24 January 2019 at 23:59:30 UTC, Walter Bright wrote: >>>> On 1/24/2019 1:03 PM, kinke wrote: >>>>> (bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy = >>>>> b();)) , __gate = true , f(__pfx, __pfy); >>>> >>>> There must be an individual gate for each of __pfx and pfy. >>>> With the rewrite above, if b() throws then _pfx won't be destructed. >>> >>> There is no individual gate, there's just one to rule the >>> caller-destruction of all temporaries. >> >> What happens, then, when b() throws? > > `__pfx` goes out of scope, and is dtor expression (cleanup/finally) is > run as part of stack unwinding. Rewritten as block statement:
And nested calls are serialized as you'd expect: int foo(ref S i, ref S j); S bar(ref S i, ref S j); S someRvalue(int i); foo( bar(someRvalue(1), someRvalue(2)), someRvalue(4)); // translates to something like: { bool __gate1 = false; S __tmp1 = void; S __tmp2 = void; S __tmp3 = void; __tmp1 = someRvalue(1); try { __tmp2 = someRvalue(2); __gate1 = true; __tmp3 = bar(__tmp1, __tmp2); } finally { if (!__gate1) __tmp1.__xdtor(); } S __tmp4 = void; bool __gate2 = false; try { __tmp4 = someRvalue(4); __gate2 = true; return foo(__tmp3, __tmp4); } finally { if (!__gate2) { __tmp3.__xdtor(); } } }