sepavloff updated this revision to Diff 51017. sepavloff added a comment. Do not emit warning on class methods.
http://reviews.llvm.org/D16579 Files: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/CXX/drs/dr3xx.cpp test/CXX/drs/dr5xx.cpp test/SemaCXX/friend.cpp test/SemaCXX/overload-call.cpp
Index: test/SemaCXX/overload-call.cpp =================================================================== --- test/SemaCXX/overload-call.cpp +++ test/SemaCXX/overload-call.cpp @@ -574,13 +574,15 @@ // Ensure that overload resolution attempts to complete argument types when // performing ADL. template<typename T> struct S { - friend int f(const S&); + friend int f(const S&); // expected-warning{{friend declaration 'IncompleteArg::f' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} }; extern S<int> s; int k = f(s); template<typename T> struct Op { - friend bool operator==(const Op &, const Op &); + friend bool operator==(const Op &, const Op &); // expected-warning{{friend declaration 'IncompleteArg::operator==' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} }; extern Op<char> op; bool b = op == op; Index: test/SemaCXX/friend.cpp =================================================================== --- test/SemaCXX/friend.cpp +++ test/SemaCXX/friend.cpp @@ -363,3 +363,47 @@ f_pr6954(5); // expected-error{{undeclared identifier 'f_pr6954'}} } + +template<typename T> void pr23342_func(T x); +template<typename T> +struct pr23342_C1 { + friend void pr23342_func<>(T x); + friend bool func(T x); // expected-warning{{friend declaration 'func' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} + friend bool func2(int x); + template<typename T2> friend bool func3(T2 x); + friend T func4(); // expected-warning{{friend declaration 'func4' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} +}; + +namespace pr23342 { + +template<typename T> +struct C1 { + friend void pr23342_func<>(T x); + friend bool func(T x); // expected-warning{{friend declaration 'pr23342::func' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} + friend bool func2(int x); + template<typename T2> friend bool func3(T2 x); + friend T func4(); // expected-warning{{friend declaration 'pr23342::func4' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}}}; +}; + +template <typename T> +struct Arg { + friend bool operator==(const Arg& lhs, T rhs) { + return false; + } + friend bool operator!=(const Arg& lhs, T rhs); // expected-warning{{friend declaration 'pr23342::operator!=' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}}}; +}; +template <typename T> +bool operator!=(const Arg<T>& lhs, T rhs) { + return true; +} +bool foo() { + Arg<int> arg; + return (arg == 42) || (arg != 42); +} + +} Index: test/CXX/drs/dr5xx.cpp =================================================================== --- test/CXX/drs/dr5xx.cpp +++ test/CXX/drs/dr5xx.cpp @@ -581,8 +581,10 @@ namespace dr557 { // dr557: yes template<typename T> struct S { - friend void f(S<T> *); - friend void g(S<S<T> > *); + friend void f(S<T> *); // expected-warning{{friend declaration 'dr557::f' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} + friend void g(S<S<T> > *); // expected-warning{{friend declaration 'dr557::g' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} }; void x(S<int> *p, S<S<int> > *q) { f(p); Index: test/CXX/drs/dr3xx.cpp =================================================================== --- test/CXX/drs/dr3xx.cpp +++ test/CXX/drs/dr3xx.cpp @@ -291,7 +291,8 @@ template void g(N::A<0>::B<0>); namespace N { - template<typename> struct I { friend bool operator==(const I&, const I&); }; + template<typename> struct I { friend bool operator==(const I&, const I&); }; // expected-warning{{friend declaration 'dr321::N::operator==' declares a non-template function}} + // expected-note@-1{{if this is not what you intended, make sure the function template has already been declared and add <> after the function name here}} } N::I<int> i, j; bool x = i == j; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -8424,6 +8424,15 @@ AddToScope = false; } + if (isFriend && !NewFD->isInvalidDecl()) { + if (R->isDependentType() && TemplateParamLists.empty() && + !DC->isRecord() && !isFunctionTemplateSpecialization && + (D.getFunctionDefinitionKind() == FDK_Declaration)) { + Diag(NameInfo.getLoc(), diag::warn_non_template_friend) << NewFD; + Diag(NameInfo.getLoc(), diag::note_non_template_friend); + } + } + return NewFD; } Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1150,6 +1150,11 @@ "enclosing namespace is a Microsoft extension; add a nested name specifier">, InGroup<MicrosoftUnqualifiedFriend>; def err_pure_friend : Error<"friend declaration cannot have a pure-specifier">; +def warn_non_template_friend : Warning<"friend declaration %q0 declares a " + "non-template function">, InGroup<NonTemplateFriend>; +def note_non_template_friend : Note<"if this is not what you intended, make " + "sure the function template has already been declared and add <> after the " + "function name here">; def err_invalid_member_in_interface : Error< "%select{data member |non-public member function |static member function |" Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -273,6 +273,7 @@ def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; def NonPODVarargs : DiagGroup<"non-pod-varargs">; +def NonTemplateFriend : DiagGroup<"non-template-friend">; def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>; def : DiagGroup<"nonportable-cfstrings">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits