On Wed, May 15, 2013 at 9:44 PM, Rafael Espíndola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.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 class="im">On 15 May 2013 17:18, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:<br>
> Patch looks good, but don't you need to also change all the other calls to<br>
> QualType::getLinkageAndVisibility? In C++14 at least, a no-linkage type can<br>
> completely leak out of a function and be used as a type of a non-type<br>
> template parameter. For instance:<br>
><br>
> inline auto f() {<br>
>   struct S {};<br>
>   return S();<br>
> }<br>
> template<decltype(f())*> struct X { X() {} };<br>
> X<nullptr> x;<br>
><br>
> Right now, this incorrectly generates @x as an internal-linkage symbol. You<br>
> can probably observe the same bug in C++11 by passing S to a template like<br>
> this:<br>
><br>
> template<typename T> struct Outer { template<T *p> struct Inner { ... }; };<br>
<br>
</div>So, I am trying to create a full c++11 testcase. The closest I have so far is<br>
<br>
template <typename T><br>
struct foo {<br>
  template <T *P> static void f() {<br>
  }<br>
  static void *g() {<br>
    static T x;<br>
    return (void*)f<&x>;<br></blockquote><div><br></div><div>Yeah, it's as you suspect: 'x' has no linkage, so its address can't be used as a non-type template parameter. f<nullptr> here works, and exhibits the bug. The following should also work, but is rejected, because we incorrectly think that foo<S>::x has no linkage (with or without the inline keyword):</div>
<div><br></div><div><div>template <typename T></div><div>struct foo {</div><div>  template <T *P> static void f() {</div><div>  }</div><div>  static void *g() {</div><div>    f<&x>();</div><div>  }</div>
<div>  static T x;</div><div>};</div><div>template<typename T> T foo<T>::x;</div><div><br></div><div>/*inline*/ void *f() {</div><div>  struct S {</div><div>  };</div><div>  return foo<S>::g();</div><div>
}</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  }<br>
};<br>
<br>
inline void *f() {<br>
  struct S {<br>
  };<br>
  return foo<S>::g();<br>
}<br>
<br>
but this fails to compile with<br>
<br>
address of overloaded function 'f' does not match required type 'void'<br>
<br>
which I assume is because I am trying to use an object without linkage<br>
in a non type template argument. Is that supposed to work?<br>
<br>
Cheers,<br>
Rafael<br>
</blockquote></div><br>