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

Reply via email to