<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Apr 12, 2016 at 5:34 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</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"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="">On Tue, Apr 12, 2016 at 5:22 PM, Akira Hatanaka via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.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"><div dir="ltr"><div>I was wondering whether someone could answer a few questions about variable templates. I'm trying to come up with a patch that fixes the crash described in PR27015.</div><div><br></div><div><a href="https://llvm.org/bugs/show_bug.cgi?id=27015" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=27015</a><br></div><div><br></div><div>The crash happens when clang compiles a code that has a variable template initialized with a generic lambda. For example,</div><div><br></div><div>$ cat test1.c</div><div><br></div>template<typename T> auto fn = [](auto a) { return a + T(1); };<br><br><div>template <typename X><br>int func() {<br>  X a = 0x61;<br>  fn<char>(a);<br>  return 0;<br>}<br><br></div><div>int main() {<br>  func<int>();<div>}<p></p><p></p></div></div><div>First question, is this legal c++14 code? I didn't find anything that suggests it isn't legal, but I haven't found any code that uses variable templates like this either other than the provided test case.</div></div></blockquote><div><br></div></span><div>Yes, sadly, this is valid C++14 code.</div><span class=""><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"><div dir="ltr"><div>Second question, what would the closure type look like in this case? My understanding is that the closure type for generic lambda without template parameters looks like this:</div><div><br></div><div>class Class {</div><div>template<typename AT></div><div>  AT operator()(AT a) { ... }</div><div>  ...</div><div>};</div><div><br></div><div>With template parameter, would it look like this?</div><div><br></div><div>template<typename T></div><div><div>class Class {</div><div>template<typename AT></div><div>  AT operator()(AT a) { return a + T(1); }</div><div>  ...</div><div>};</div></div></div></blockquote><div><br></div></span><div>No. Each instantiation of 'fn' gets its own closure type. The closure type from the template itself should be treated as being in a dependent context, even though there is no dependent DeclContext to contain it. </div></div></div></div>
</blockquote></div><br></div><div class="gmail_extra">After the template declaration for func is parsed, VarTemplateSpecialization for fn looks like this in the AST:</div><div class="gmail_extra"><br></div><div class="gmail_extra"><span class="">`-</span><span class=""><b>VarTemplateSpecializationDecl</b></span><span class=""> 0x10d001a00</span><span class=""> <</span><span class="">line:23:22</span><span class="">, </span><span class="">col:62</span><span class="">> </span><span class="">col:27</span><span class=""> referenced</span><span class=""><b> fn</b></span><span class=""> </span><span class="">'auto'</span><span class=""> cinit</span><br></div><div class="gmail_extra"><span class=""><br></span></div><div class="gmail_extra"><span class="">I think this is not correct as the type of the VarTemplateSpecializationDecl at this point should be the closure type for fn<char> instead of 'auto'. Is that correct?</span></div><div class="gmail_extra"><span class=""><br></span></div><div class="gmail_extra"><span class="">I'm still trying to understand how instantiation of variable templates works, but it seems like one of the problem is that Sema::createLambdaClosureType is returning a type that is dependent (CXXRecordDecl::isDependentType() returns true</span>), which looks like is preventing the type of VarTemplateSpecialization from being replaced.</div></div>