<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jan 9, 2015 at 11:35 AM, Nathan Sidwell <span dir="ltr"><<a href="mailto:nathan@acm.org" target="_blank">nathan@acm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">the attached patch fixes bu 18645:<br>
<a href="http://llvm.org/bugs/show_bug.cgi?id=18645" target="_blank">http://llvm.org/bugs/show_bug.<u></u>cgi?id=18645</a><br>
<br>
In c++11, call deduction of a template parameter of type 'T &&' will deduce T as lvalue reference, if the corresponding argument is an lvalue.  The bug occurs when the argument is (for instance) a template-id-expr for a template function.  At the point of checking this behaviour, the id-expr hasn't been resolved and the modification to an lvalue ref doesn't occur.  We end up deducing T as a function type, and further never decay  it to pointer to function.<br>
<br>
It is this bit of code that's trying that test:<br>
-    if (isa<RValueReferenceType>(<u></u>ParamType)) {<br>
-      if (!PointeeType.getQualifiers() &&<br>
-          isa<TemplateTypeParmType>(<u></u>PointeeType) &&<br>
-          Arg->Classify(S.Context).<u></u>isLValue() &&<br>
-          Arg->getType() != S.Context.OverloadTy &&<br>
-          Arg->getType() != S.Context.BoundMemberTy)<br>
<br>
and for an arg of template-id-expr, Arg->getType () is an OverloadTy, so the test fails.<br>
<br>
Just after this test is the following deduction check:<br>
  if (ArgType == S.Context.OverloadTy) {<br>
    ArgType = ResolveOverloadForDeduction(S, TemplateParams,<br>
                                          Arg, ParamType,<br>
                                          ParamRefType != nullptr);<br>
which is doing the template-id resolution needed.  Now, just after that is the following:<br>
<br>
  if (ParamRefType) {<br>
    // C++0x [temp.deduct.call]p3:<br>
    //   [...] If P is of the form T&&, where T is a template parameter, and<br>
    //   the argument is an lvalue, the type A& is used in place of A for<br>
    //   type deduction.<br>
    if (ParamRefType-><u></u>isRValueReferenceType() &&<br>
        ParamRefType->getAs<<u></u>TemplateTypeParmType>() &&  <-- this line<br>
        Arg->isLValue())<br>
      ArgType = S.Context.<u></u>getLValueReferenceType(<u></u>ArgType);<br>
<br>
which is also attempting to do the same check, but it's flubbed the wording on the indicated line by checking ParamRefType not ParamRefType->getPointeeType () (aka ParamType at this point).<br>
<br>
Just fixing that line would work, but it is unnecessary and wrong to have the check remain in two places.  Hence I removed the checking from before the call to ResolveOverloadForDeduction and moved it all into the lower if conditional. For good measure I moved the earlier check about incomplete array types there too, to keep the reference parameter handling all in one place.  The only piece of this check that happens before the ROFD call is to remove the referenceness from ParamType.<br>
<br>
built and tested on x86_64-linux.  ok?</blockquote><div><br></div><div>You have a tab character on the </div><div><br></div><div>+<span class="" style="white-space:pre">       </span>isa<TemplateTypeParmType>(ParamType) &&<br></div><div><br></div><div>line; please convert to spaces.</div><div><br></div><div>You can make the test a bit simpler:</div><div><br></div><div>  template<typename F> F Quux(F &&f);</div><div>  float (&Baz)(float&&) = Quux(Quux<float>);<br></div><div><br></div><div>Other than that, LGTM.</div><div><br></div><div>(The BoundMemberTy check is missing compared to the original, but it looks like that never actually did anything here, because we'd fall through into the second copy of the 'create an lvalue reference' code regardless.)</div><div><br></div><div>Thank you!</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class=""><font color="#888888"><br>
nathan<br>
</font></span></blockquote></div><br></div></div>