From 78037ac3e7562aa3e306eaba97f1c609b86337d9 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 3 Apr 2013 21:19:47 +0000 Subject: [PATCH] Complain about attempts to befriend declarations via a using 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 | 2 ++ lib/Sema/SemaDecl.cpp | 9 +++++++++ lib/Sema/SemaOverload.cpp | 3 ++- test/SemaCXX/friend.cpp | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 858df1754b..c4815cd7ea 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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 |" diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a6ba68060d..1288568401 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2277,6 +2277,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { Old = dyn_cast(OldD); if (!Old) { if (UsingShadowDecl *Shadow = dyn_cast(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); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 5d931cfcaf..89d495ddc1 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(OldD)) { if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) { diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp index c5b11eb5a3..b401a06a7e 100644 --- a/test/SemaCXX/friend.cpp +++ b/test/SemaCXX/friend.cpp @@ -138,3 +138,19 @@ namespace test7 { }; } } + +// PR15485 +namespace test8 { + namespace ns1 { + namespace ns2 { + template 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 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}} + }; +}