On Thu, Sep 6, 2012 at 1:50 PM, Pan, Wei <span dir="ltr"><<a href="mailto:wei.pan@intel.com" target="_blank">wei.pan@intel.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">






<div lang="EN-US" link="blue" vlink="purple">
<div>
<p class="MsoNormal">Hello Clang Dev,<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Recently I looked into the clang bug 12053,<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">template <typename T> auto foo(T t) -> decltype(foo(t)) {}<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><a href="http://llvm.org/bugs/show_bug.cgi?id=12053" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=12053</a><u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">which crashes clang (trunk)  (and gcc 4.6 too).<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">As far as I know,  Clang does realize that there is no candidate
<u></u><u></u></p>
<p class="MsoNormal">available while resolving “decltype(foo(t))”, however BuildRecoveryCallExpr
<u></u><u></u></p>
<p class="MsoNormal">will find  template foo (in DiagnoseTwoPhaseLookup) <u></u><u></u></p>
<p class="MsoNormal">and try to instantiate it again. This leads to the crash.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">I am wondering if the following is the right way to fix this. The basic idea is:
<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Before starting instantiating a function template, we check if the same function<u></u><u></u></p>
<p class="MsoNormal">template instantiation *with the same template arguments* is already in-progress.
<u></u><u></u></p>
<p class="MsoNormal">If yes, then clang is not making any progress and should lead an infinite loop.<u></u><u></u></p>
<p class="MsoNormal">We treat it as an SFINAE.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">The attached patch will fix the clang crashing on the above test and other similar tests like<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">template <typename T> auto foo(T t) -> decltype(bar(t)) {}<u></u><u></u></p>
<p class="MsoNormal">template <typename T> auto bar(T t) -> decltype(foo(t)) {}<u></u><u></u></p>
<p class="MsoNormal">int x = foo(0);<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">This is not a final patch since this change will affect two tests (only these two)
<u></u><u></u></p>
<p class="MsoNormal">instantiation-depth-subst.cpp and instantiation-depth-subst-2.cpp.<u></u><u></u></p>
<p class="MsoNormal"><u></u><u></u></p>
<p class="MsoNormal">Any thoughts?</p></div></div></blockquote><div><br></div><div>I generally like the idea of checking for cyclic function template instantiations, but I'm hesitant about this approach -- scanning through the instantiation stack each time introduces overhead which grows quadratically in the instantiation depth, which could be too slow for deep instantiation stacks.</div>
<div><br></div><div>Also, this approach doesn't solve the entire problem. For instance, in this case, there is no cycle:</div><div><br></div><div>  template<typename T> auto foo(T t) -> decltype(foo(&t)) {}</div>
<div><br></div><div>Perhaps we can solve this more directly, by just disabling BuildRecoveryCallExpr when we're already in the middle of recovery.</div></div>