]> granicus.if.org Git - clang/commitdiff
Complain about attempts to befriend declarations via a using
authorJohn McCall <rjmccall@apple.com>
Wed, 3 Apr 2013 21:19:47 +0000 (21:19 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 3 Apr 2013 21:19:47 +0000 (21:19 +0000)
declaration.  Patch by Stephen Lin!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178698 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaOverload.cpp
test/SemaCXX/friend.cpp

index 858df1754b02d0abe7561d54950613f4b34a33b7..c4815cd7ea6c55016c52017e5ca30ad72936afd4 100644 (file)
@@ -867,6 +867,8 @@ def err_friend_def_in_local_class : Error<
   "friend function cannot be defined in a local class">;
 def err_friend_not_first_in_declaration : Error<
   "'friend' must appear first in a non-function declaration">;
+def err_using_decl_friend : Error<
+  "cannot befriend target of using declaration">;
   
 def err_invalid_member_in_interface : Error<
   "%select{data member |non-public member function |static member function |"
index a6ba68060dfd3e2d95630d7daab0ae228a4abcd8..12885684016294b522de84c123a9624ec800fc42 100644 (file)
@@ -2277,6 +2277,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
     Old = dyn_cast<FunctionDecl>(OldD);
   if (!Old) {
     if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
+      if (New->getFriendObjectKind()) {
+        Diag(New->getLocation(), diag::err_using_decl_friend);
+        Diag(Shadow->getTargetDecl()->getLocation(),
+             diag::note_using_decl_target);
+        Diag(Shadow->getUsingDecl()->getLocation(),
+             diag::note_using_decl) << 0;
+        return true;
+      }
+
       Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
       Diag(Shadow->getTargetDecl()->getLocation(),
            diag::note_using_decl_target);
index 5d931cfcafb29af6a0bcd2942d2723577a35b39f..89d495ddc197f2e0251e7450ab4188d185f25d1e 100644 (file)
@@ -920,7 +920,8 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
     // function templates hide function templates with different
     // return types or template parameter lists.
     bool UseMemberUsingDeclRules =
-      (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord();
+      (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() &&
+      !New->getFriendObjectKind();
 
     if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
       if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) {
index c5b11eb5a33854b3eebde11c1ae8eb65c4f88350..b401a06a7ecfe66e010f8b8f347f05836a6dd6f6 100644 (file)
@@ -138,3 +138,19 @@ namespace test7 {
     };
   }
 }
+
+// PR15485
+namespace test8 {
+  namespace ns1 {
+    namespace ns2 {
+      template<class T> void f(T t); // expected-note {{target of using declaration}}
+    }
+    using ns2::f; // expected-note {{using declaration}}
+  }
+  struct A { void f(); }; // expected-note {{target of using declaration}}
+  struct B : public A { using A::f; }; // expected-note {{using declaration}}
+  struct X {
+    template<class T> friend void ns1::f(T t); // expected-error {{cannot befriend target of using declaration}}
+    friend void B::f(); // expected-error {{cannot befriend target of using declaration}}
+  };
+}