<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Aug 12, 2014 at 8:09 PM, Michael Park <span dir="ltr"><<a href="mailto:mcypark@gmail.com" target="_blank">mcypark@gmail.com</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>Hello,</div></div></blockquote><div><br>
</div><div>Hi and welcome! (And sorry for the delay.)</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">
<div dir="ltr"><div>I'm new to clang development and was hoping to get some help in tackling this bug that I found/filed: <a href="http://llvm.org/bugs/show_bug.cgi?id=20625" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=20625</a></div>
<div><br></div><div>Example:</div><div><br></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">template <typename T><br>
void F() {<br> struct Num {<br> static constexpr int Get() { return 42; }<br> };<br> constexpr int n = Num::Get();<br>}<br>int main() {<br> F<int>();<br>}</blockquote></div><div><br></div><div>The summary of the issue is that the local struct <b>Num</b> and its static constexpr function <b>Get</b> is not yet instantiated when we validate the constexpr variable initialization of <b>n</b> during <b>F</b>'s instantiation.</div>
<div><br></div><div>More details:</div><div><br></div><div><div><b>Num</b> and <b>Get</b> gets added to <b>PendingLocalImplicitInstantiations</b> in <b>SubstStmt</b> at <i>SemaTemplateInstantiationDecl.cpp:3437</i>, and is instantiated later by <b>PerformPendingInstantiations</b> at<b> </b><i>SemaTemplateInstantiationDecl.cpp:3458</i>. However, the validation of the constexpr variable initialization of <b>n</b> happens in <b>SubstStmt</b> at which point we don't yet have the definition of <b>Get</b> instantiated.</div>
<div><br></div></div><div>I'm not exactly sure what the correct approach would be to solve the problem. It seems that the local implicit instantiations need to be performed earlier, or the validation of constexpr variables need to be delayed.</div>
<div><br></div><div>If someone can point me in the right direction it would be appreciated.</div></div></blockquote><div><br></div><div>The implicit instantiations should be performed sooner. (FWIW, the same problem will affect member functions of local classes that have deduced return types.) Perhaps the easiest way to address this would be to perform all the local implicit instantiations discovered while instantiating a local class when we reach the end of that local class, instead of delaying them until the end of the surrounding function. We try to delay these instantiations as much as we can, to reduce the stack usage in recursive template instantiation, but that's probably not going to be significant here because there's not likely to be many layers of AST between the function and the class definition.</div>
<div><br></div><div>One place to put this fix would be around SemaTemplateInstantiateDecl.cpp:1104:</div><div><br></div><div><div> // DR1484 clarifies that the members of a local class are instantiated as part</div><div>
// of the instantiation of their enclosing entity.</div><div> if (D->isCompleteDefinition() && D->isLocalClass()) {</div><div> SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,</div>
<div> TSK_ImplicitInstantiation,</div><div> /*Complain=*/true);</div><div> SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,</div><div> TSK_ImplicitInstantiation);</div>
<div> }</div></div><div><br></div><div>You could save, perform, and restore the pending local implicit instantiations around these calls.</div></div></div></div>