<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Dec 6, 2014 at 5:35 AM, Mario Lang <span dir="ltr"><<a href="mailto:mlang@delysid.org" target="_blank">mlang@delysid.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 class=""><div class="h5">Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> writes:<br>
<br>
> On Fri, Dec 5, 2014 at 3:55 AM, Mario Lang <<a href="mailto:mlang@delysid.org">mlang@delysid.org</a>> wrote:<br>
><br>
>> Hi.<br>
>><br>
>> I sort of have a suspicion that this might be a known issue, but I<br>
>> haven't found anything so far.  The code below compiles just fine with<br>
>> GCC, but Clang complains:<br>
>><br>
>> ---<snip>---<br>
>> class c { template<class> friend bool f(c) { return false; } };<br>
>> template<> bool f<int>(c) { return true; }<br>
>><br>
>> int main(){}<br>
>> ---<snip>---<br>
>><br>
>> cl.cc:2:1: error: extraneous 'template<>' in declaration of variable 'f'<br>
>> template<> bool f<int>(c) { return true; }<br>
>> ^~~~~~~~~~<br>
>> cl.cc:2:17: error: redefinition of 'f' as different kind of symbol<br>
>> template<> bool f<int>(c) { return true; }<br>
>>                 ^<br>
>> cl.cc:1:39: note: previous definition is here<br>
>> class c { template<class> friend bool f(c) { return false; } };<br>
>>                                       ^<br>
>><br>
>> As I am not an expert on the standard at all, the first question that<br>
>> comes to mind is: is this actually legal?  Given how inline friend<br>
>> functions usually work, I have a feeling it should be legal.<br>
>><br>
><br>
> I don't think this is legal. For an explicit specialization to be valid,<br>
> name lookup must find the template being explicitly specialized. Name<br>
> lookup for 'f' after the definition of 'c' does not find anything, so the<br>
> declaration appears to be ill-formed. (See [temp.names]p2 and p3.)<br>
<br>
</div></div>I wonder why name-lookup doesn't find anything.  At least non-templated<br>
free friend functions have always worked that way.</blockquote><div><br></div><div>That's not the case; try this:</div><div><br></div><div>struct S {</div><div>  friend void f(int);</div><div>};</div><div>void g() { f(0); } // error, undeclared identifier 'f'</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">Or is this a GCC<br>
extension I am not aware of?<br>
<br>
class d {<br>
  ...<br>
  friend bool operator==(d, d) { ... }<br>
};<br>
// here, d{} == d{} is found<br></blockquote><div><br></div><div>There's a special lookup rule used for function calls that allows it to find declarations that are not in scope; see <a href="http://en.wikipedia.org/wiki/Argument-dependent_name_lookup">http://en.wikipedia.org/wiki/Argument-dependent_name_lookup</a>. This only applies to function calls, and not, for instance, to explicit specializations.</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">
[...]<br>
<span class=""><br>
>> So the FunctionTemplateDecl looks fine, but AST print is a bit messy:<br>
>><br>
>> class c {<br>
>>     friend template <class > bool f(c)     {<br>
>>         return false;<br>
>>     }<br>
>><br>
>> ;<br>
>> };<br>
>> int main() {<br>
>> }<br>
>><br>
>> Note, the extra semicolon (likely harmless) and the swapped 'friend'<br>
>> keyword position.  I don't know if 'friend' can be switched around like<br>
>> this, but GCC *and* clang actually fail to compile that.<br>
>><br>
>> I guess the AST printer doesn't really require to always produce valid<br>
>> source code (or does it), but this AST print seems to hint at some gaps<br>
>> in AST handling around FriendDecl and nested TemplateFunctionDecl.<br>
><br>
> We don't guarantee that the AST printer always produces valid code.<br>
<br>
</span>Guessed that.<br>
<span class=""><br>
> The AST dump looks fine to me for this case, though.<br>
<br>
</span>Note friend template<class> vs template<class> friend.<br></blockquote><div><br></div><div>Right, the AST pretty-printing is obviously producing ill-formed code. But the AST dump looks fine.</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">
The original code was:<br>
<span class=""><br>
>> class c { template<class> friend bool f(c) { return false; } };<br>
<br>
</span>and ast-print switched that around to:<br>
<span class=""><br>
>>     friend template <class > bool f(c)     {<br>
<br>
</span>which fails to compile on gcc and clang.<br>
<div class=""><div class="h5"><br>
--<br>
CYa,<br>
  ⡍⠁⠗⠊⠕<br>
<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br></div></div>