<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 6/19/2012 7:14 AM, SHIVA PRASAD
wrote:<br>
</div>
<blockquote
cite="mid:CAJh=txJPZA+9D3HRU9ex_yFFcK6pkKHt6vJROEhxCWUO5T=wKw@mail.gmail.com"
type="cite">Dear LLVM Members,
<div><br>
<div> The below source code from gcc test
suite replicates the problem which i am facing. When it is
built with clang, it throws an <span
style="background-color:rgb(255,0,0)">abort</span>(highlighted).</div>
<div>The following are my observations - </div>
<div><br>
</div>
<div>1. The object(tmp) is not getting destroyed immediately
after the exception is thrown. In case of Clang, the object
is getting destroyed at a later point of time.</div>
<div>2. In case of gcc, the scope of the object created inside
the try-catch block is limited to the block. Once the
exception is thrown, the object(tmp) is destroyed.</div>
<div>3. The assembly files for both clang and gcc were generated
and compared, wherein the sequence of operations look similar.</div>
<div>4. I also tried the MS-Visual Studio compiler, which gives
a result similar to gcc.</div>
</div>
</blockquote>
<br>
This looks specific to clang, not to LLVM, so moving to cfe-dev.<br>
<br>
[Source code below not elided for anyone on cfe-dev who isn't on
llvmdev; I have more comments trailing, so scroll down].<br>
<blockquote
cite="mid:CAJh=txJPZA+9D3HRU9ex_yFFcK6pkKHt6vJROEhxCWUO5T=wKw@mail.gmail.com"
type="cite">
<div>
<div>
<div>As per my understanding of the C++ standard, the object
has to be destroyed as soon as the exception is thrown. </div>
<div>Please let me know which is the correct behavior and
suggest me the changes required.</div>
<div><br>
</div>
<div><br>
</div>
<div>
<div>Thanks & Regards,</div>
<div>Shivaprasad</div>
<div><a moz-do-not-send="true"
href="mailto:shivahms@gmail.com">shivahms@gmail.com</a></div>
</div>
<div><br>
</div>
<div>/******************************************************************Source
Code
Start*******************************************************************/</div>
<div>extern "C" void abort ();</div>
<div><br>
</div>
<div>int thrown;</div>
<div><br>
</div>
<div>int as;</div>
<div>struct a {</div>
<div> a () { ++as; }</div>
<div> ~a () { --as; if (thrown++ == 0) throw 42; }</div>
<div>};</div>
<div><br>
</div>
<div>int f (a const&) { return 1; }</div>
<div>int f (a const&, a const&) { return 1; }</div>
<div><br>
</div>
<div>int bs;</div>
<div>int as_sav;</div>
<div>struct b {</div>
<div> b (...) { ++bs; }</div>
<div> ~b () { --bs; as_sav = as; }</div>
<div>};</div>
<div><br>
</div>
<div>bool p;</div>
<div>void g()</div>
<div>{</div>
<div> if (p) throw 42;</div>
<div>}</div>
<div><br>
</div>
<div><span style="background-color:rgb(255,255,102)">int main
() {</span></div>
<div><span style="background-color:rgb(255,255,102)"> thrown
= 0;</span></div>
<div><span style="background-color:rgb(255,255,102)"> try {</span></div>
<div><span style="background-color:rgb(255,255,102)"> b
tmp(f (a(), a()));</span></div>
<div><span style="background-color:rgb(255,255,102)"><br>
</span></div>
<div><span style="background-color:rgb(255,255,102)"> g();</span></div>
<div><span style="background-color:rgb(255,255,102)"> }</span></div>
<div><span style="background-color:rgb(255,255,102)"> catch
(...) {}</span></div>
<div><br>
</div>
<div> // We throw when the first a is destroyed, which should
destroy b before</div>
<div> // the other a.</div>
<div> if (as_sav != 1)</div>
<div> <span style="background-color:rgb(255,0,0)"> abort ();</span></div>
<div><br>
</div>
<div> thrown = 0;</div>
<div> try {</div>
<div> b tmp(f (a()));</div>
<div><br>
</div>
<div> g();</div>
<div> }</div>
<div> catch (...) {}</div>
<div><br>
</div>
<div> if (bs != 0)</div>
<div> abort ();</div>
<div>}</div>
<div>/******************************************************************Source
Code
End*******************************************************************/</div>
<br>
</div>
</div>
</blockquote>
<br>
What clang is generating can be approximated by the following
pseudocode:<br>
atmp1, atmp2, btmp = alloca space for temporaries<br>
call a::a on atmp1<br>
try {<br>
call a::a on atmp2<br>
try {<br>
call f(atmp1, atmp2)<br>
call b::b on btmp<br>
} catch {<br>
} finally {<br>
call a::~a on atmp2<br>
}<br>
} catch {<br>
} finally {<br>
call a::~a on atmp1<br>
}<br>
// NOW b is "constructed"<br>
<br>
Looking at the output IR, the best interpretation I can give is that
Clang is cleaning up the temporary arguments before calling the new
variable constructed. The question, of course, is whether or not
this is legal per the C++ spec. C++11 section 12.2, par 3 states
that<br>
<blockquote type="cite">Temporary objects are destroyed as the last
step<br>
in evaluating the full-expression (1.9) that (lexically) contains
the point where they were created.</blockquote>
<br>
Section 1.9, par 10 has an example which states that the full
expression associated with the call to the constructor in this case
is indeed the actual constructor call.<br>
<br>
Section 15.2, par 1 states:<br>
<blockquote type="cite">As control passes from a throw-expression to
a handler, destructors are invoked for all automatic objects<br>
constructed since the try block was entered. The automatic objects
are destroyed in the reverse order of the<br>
completion of their construction.</blockquote>
<br>
I'm not 100% what the correct interpretation is in this case. It
comes down to whether b should be considered constructed before or
after the full expression of the declarator is completed.<br>
<pre class="moz-signature" cols="72">--
Joshua Cranmer
News submodule owner
DXR coauthor</pre>
</body>
</html>