Hi Andrew,<div><br></div><div><div class="gmail_quote">On Wed, Mar 21, 2012 at 10:27 AM, Andrew Sutton <span dir="ltr"><<a href="mailto:asutton.list@gmail.com" target="_blank">asutton.list@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>> I was going to try to fix this problem, but I'm not sure where to<br>
> start. What's the right way to ensure that the definition of an<br>
> instantiated template is available in this context i.e., not deferred?<br>
<br>
</div>This solves the problem, but causes a couple regressions.<br>
<br>
So, it seems that the problem is that constexpr function template<br>
calls in the signatures of function templates cannot be evaluated<br>
because their uses occur in dependent contexts (apparently<br>
instantiating a function template signature as part of overload<br>
resolution occurs within the context of the function template being<br>
instantiated?). The result is that body of the constexpr function<br>
template isn't instantiated in time to be evaluated, hence the<br>
substitution failures.<br>
<br>
This patch just ensures that definitions are emitted for those calls.<br>
I tested against the examples given in the bug report, and they seemed<br>
to compile just fine. I also ran the patch against some of my own<br>
examples, and they work well. I neglected to include those in the<br>
patch though.<br>
<br>
Unfortunately the patch causes definitions to be emitted for some<br>
functions that aren't actually used, so I didn't quite get it right.<br>
Is there a deeper problem, or do the criteria for generating<br>
definitions just need to be adjusted?</blockquote><div><br></div><div>I don't think this patch is quite the right approach -- we should not be instantiating function template specializations which are called within unevaluated operands, even if they're constexpr.</div>



<div><br></div><div>One problem is in IsPotentiallyEvaluatedContext: we do not instantiate functions and variables if they are used within a dependent context. This causes us to incorrectly reject code such as:</div><div>
<br></div><div><div>  template<typename T> struct S {</div><div>    static const int n;</div><div>  };</div><div>  template<typename T> const int S<T>::n = sizeof(T);</div><div>  template<typename T> void g() {</div>
<div>    int arr[S<int>::n] = { 1, 2, 3, 4 };</div><div>  }</div></div><div><br></div><div>It looks like fixing that is sufficient for us to correctly handle instantiations of constexpr functions triggered by explicitly-specified template arguments (we treat such substitutions as being in a dependent context). Interestingly, my testing indicates that g++ instantiates non-dependent specializations which are odr-used in dependent contexts in C++11 mode, and does not instantiate them in C++98 mode.<br>
</div><div><br></div><div>Another problem is that we treat some of the relevant contexts as unevaluated contexts (in particular, when substituting deduced template arguments into a declaration), when they are not. This also causes other bugs, such as our incorrectly accepting this:</div>
<div><br></div><div>template<typename T> void f(T) {</div><div>  static_assert(sizeof(T) == 100, "");</div><div>}</div><div>template<typename T, void(*)(T) = f> struct S {};</div><div>template<typename T> S<T> g(T);</div>
<div>void h() { g(0); }<br></div><div><br></div><div>The substitution of T=int into S<T> is incorrectly being treated as an unevaluated context, resulting in us failing to notice that f<int> is odr-used and thus failing to instantiate it.</div>
<div><br></div><div>- Richard</div>

</div></div>