<div dir="ltr">I think the test case looks correct but my analysis is inconsistent with yours. However I agree there is a bug. Interestingly, while looking into it just now I wrote my own test case which revealed a separate (but perhaps related) bug in an old version of g++ (4.1.2) where destructors were being called twice. The current version appears to be correct though. Anyway, my test case follows:<div>
<br></div><div><div>#include <iostream></div><div>class Foo</div><div>{</div><div>private:</div><div> static int n;</div><div> static bool thrown;</div><div> int m_n;</div><div>public:</div><div> Foo():m_n(n++) { std::cout << "Constructor " << m_n << std::endl; }</div>
<div> ~Foo() noexcept(false) { std::cout << "Destructor " << m_n << std::endl; </div><div> if(!thrown) { </div><div> thrown = true; </div><div> std::cout << "Throwing exception" << std::endl; </div>
<div> throw 0; </div><div> }</div><div> }</div><div>};</div><div><br></div><div>int Foo::n = 0;</div><div>bool Foo::thrown = false;</div><div><br></div><div>Foo bar(Foo a, Foo b) { return Foo(); }</div><div>
<br></div><div>int main()</div><div>{</div><div> try </div><div> {</div><div> Foo foo = bar(Foo(), Foo());</div><div> }</div><div> catch(...)</div><div> {</div><div> std::cout << "In exception handler" << std::endl;</div>
<div> }</div><div> std::cout << "Out of exception handler" << std::endl;</div><div>}</div></div><div><br></div><div><br></div><div>I expect the following output:</div><div><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Constructor 0
Constructor 1
Constructor 2
Destructor 1
Throwing exception
Destructor 2
Destructor 0
In exception handler
Out of exception handler</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
<br></pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
With clang++ 3.4 I'm getting the following output:</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Constructor 0</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Constructor 1</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Constructor 2</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Destructor 1</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Throwing exception</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Destructor 0</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
In exception handler</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
Out of exception handler</pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
<br></pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
<br></pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
So it looks like the destructor for the returned object is not being called at all (not in the wrong order). I get the same behavior in C++11 mode, too (though you have to add noexcept(false) to the destructor due to the implicit noexcept).</pre>
<pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
<br></pre><pre class="" style="font-family:Monaco,Menlo,Consolas,'Courier New',monospace;font-size:13px;color:rgb(51,51,51);border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;border:0px;padding:0px!important;margin-top:0px!important;margin-bottom:0px!important">
-- Matthew P. Del Buono</pre></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Apr 4, 2014 at 9:39 AM, suyog sarda <span dir="ltr"><<a href="mailto:sardask01@gmail.com" target="_blank">sardask01@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Gentle Ping !! Please help to verify if this is a bug and if my analysis is correct.<br></div><div class="HOEnZb">
<div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Apr 1, 2014 at 10:18 PM, suyog sarda <span dir="ltr"><<a href="mailto:sardask01@gmail.com" target="_blank">sardask01@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Hi all,<br><br></div><div>This is a test g++ test case for checking correct exception handling.<br>
<br></div><div><i>#ifdef __GXX_EXPERIMENTAL_CXX0X__<br>#define NOEXCEPT_FALSE noexcept (false)<br>#else<br>
#define NOEXCEPT_FALSE<br>#endif<br><br>extern "C" void abort ();<br> <br>int thrown;<br><br>int as;<br>struct a {<br> a () { ++as; }<br> ~a () NOEXCEPT_FALSE { --as; if (thrown++ == 0) throw 42; }<br>};<br> <br>
int f (a const&) { return 1; }<br>int f (a const&, a const&) { return 1; }<br><br>int bs;<br>int as_sav;<br>struct b {<br> b (...) { ++bs; }<br> ~b () { --bs; as_sav = as; }<br>};<br><br>bool p;<br>void g()<br>
{<br> if (p) throw 42;<br>}<br><br>int main () {<br> thrown = 0;<br> try {<br> b tmp(f (a(), a()));<br><br> g();<br> } <br> catch (...) {}<br><br> // We throw when the first a is destroyed, which should destroy b before<br>
// the other a.<br> if (as_sav != 1)<br> abort ();<br><br> thrown = 0;<br> try {<br> b tmp(f (a()));<br><br> g();<br> } <br> catch (...) {}<br> <br> if (bs != 0)<br> abort ();<br>} </i><br clear="all">
</div><div><br></div><div>This Test Case aborts on ARM as well as X86 with clang latest trunk while with g++ no aborts are seen .<br><br></div><div>Here, when first temporary object '<i>a'</i> gets destroyed, its destructor is called where we throw an exception. This should immediately call destructor of <i>'b'</i> and before calling constructor of second temporary object <i>'a'</i>. Instead, with clang, it is waiting for second temporary object <i>'a'</i> to get destroyed and then calling its own destructor.<br>
<br></div><div>In my opinion, the compiler is not generating correct landing pad for the exception. Can someone please help in validating this reason? If it is a genuine bug then i will file a bug and try to work out solution for it. <br>
</div><div><br>-- <br>With regards,<br>Suyog Sarda<br></div>
</div>
</blockquote></div><br><br clear="all"><br>-- <br>With regards,<br>Suyog Sarda<br>
</div>
</div></div><br>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div>