<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">2016-03-18 0:35 GMT+06:00 Arthur O'Dwyer <span dir="ltr"><<a href="mailto:arthur.j.odwyer@gmail.com" target="_blank">arthur.j.odwyer@gmail.com</a>></span>:<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">I'm not qualified to comment on the implementation, but I'm a bit skeptical that this warning is appropriate in the first place. I've often declared friend non-template functions, e.g. swap(). I've never intended to declare a friend <i>template specialization</i>. Is declaring friend template specializations something that people do often? Is it something that Clang should be encouraging newbies to do <i>more</i> often?</div></blockquote><div><br></div><div><div>It is not about intention but misunderstanding. Users often think that if a function is declared inside a template class and depends on template parameters, it is template. That expect the following code to work:</div><div><br></div><div><font face="monospace, monospace">    template<typename T> void foo(T *x) {…}</font></div><div><font face="monospace, monospace">    template<typename T> class Bar {</font></div><div><font face="monospace, monospace">      void foo(T *x);</font></div><div><font face="monospace, monospace">    }</font></div><div><br></div><div>There are lots of questions in forums (search by keywords "friend template function link error"), in which people feel surprised why such code results in undefined reference. The proposed compiler message is just a hint how to make the code working as expected by a user.</div></div><div> <br></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><br></div><div>GCC suppresses the diagnostic when the friend function is declared inline, which is good, because it shuts up the diagnostic in this very common case:</div><div><div><br></div><div><font face="monospace, monospace">template<class T></font></div><div><font face="monospace, monospace">struct vector {</font></div><div><font face="monospace, monospace">    void swap(vector& b) { /* swap members */ }</font></div><div><font face="monospace, monospace">    friend void swap(vector& a, vector& b) { a.swap(b); }  // friend non-template function</font></div><div><font face="monospace, monospace">};</font></div><div><br></div><div>IMHO you should add an explicit test confirming that the warning is suppressed in this case.</div></div></div></blockquote><div><br></div><div>There is such check already, file `test/SemaCXX/friend.cpp`:</div><div><br></div><div><font face="monospace, monospace">    template <typename T></font></div><div><font face="monospace, monospace">    struct Arg {</font></div><div><font face="monospace, monospace">      friend bool operator==(const Arg& lhs, T rhs) {</font></div><div><font face="monospace, monospace">       return false;</font></div><div><font face="monospace, monospace">      }</font></div><div><font face="monospace, monospace">    …</font></div><div><font face="monospace, monospace">    };</font></div><div><font face="monospace, monospace">    …</font></div><div><font face="monospace, monospace">    bool foo() {</font></div><div><font face="monospace, monospace">      Arg<int> arg;</font></div><div><font face="monospace, monospace">      return (arg == 42) || (arg != 42);</font></div><div><font face="monospace, monospace">    }</font></div><div><br></div><div>Operator `==` is defined inline, no warning expected.</div><div><br></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><div> <br></div></div></div></blockquote><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><div></div><div>The example in PR23342 doesn't seem like a good example, because GCC gives not only the proposed warning for that code, but also a linker error; i.e., there's no danger of someone accidentally getting wrong runtime behavior there. Is there a compelling </div></div></div></blockquote><div><br></div><div>Clang behaves exactly the same, compilation eventually results in a linker error.</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><div>example of how someone could write code that has wrong runtime behavior, <i>and</i> which code would be <i>fixed</i> by the suggested addition of <font face="monospace, monospace">template<></font>? I think it's much more likely that the appropriate fix would be to move the function definition inline.</div></div></div></blockquote><div><br></div><div>There seems to be no danger to get wrong behavior here, only undefined symbols at link stage. If code builds, it works right.</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><div><a href="https://llvm.org/bugs/show_bug.cgi?id=23342" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=23342<br></a></div><div><br></div>Why did you need to suppress the warning in "test/CXX/temp/temp.decls/temp.friend/p1.cpp"? Unless I'm mistaken, GCC doesn't give the diagnostic on that file (and nor should it).</div><div><br></div><div>my $.02,</div></div></blockquote><div><br></div><div>Good catch, thank you for your $0.02 :) There is no point in warnings for class members. Patch fixed accordingly.</div><div> </div><div>Thanks,</div><div>--Serge</div><div><br></div></div></div></div>