r178698 - Complain about attempts to befriend declarations via a using
Stephen Lin
swlin at post.harvard.edu
Wed Apr 3 15:18:44 PDT 2013
Hmm, just realized this actually doesn't address attempts to befriend
functions via using declarations with an unqualified name lookup.
namespace A {
namespace B {
void C();
}
using B::C;
class D {
friend void C();
private:
~D() { }
};
}
gcc and icc reject the above, clang (before and after this patch)
accepts it but I can't quite figure out what it's accepting it
as...B::C() doesn't seem to be friended, but there also doesn't seem
to be a new A::C() declared or ::C() declared either.
I don't really know if this code is supposed to be legal or not,
actually: the illegality of the qualified name case seems to rest on
this quote, which only applies to the qualified name case:
"When the declarator-id is qualified, the declaration shall refer
to a previously declared member of the class or namespace to which the
qualifier refers ... the member shall not merely have been introduced
by a using-declaration in the scope of the class or namespace
nominated by the nested-name-specifier of the declarator-id."
So I could either resolve this by allowing `friend void C();` to
friend `B::C()` above or disallow it like gcc and icc do...
I guess just go with the latter since this is so minor? Anyone have
any thoughts?
Stephen
On Wed, Apr 3, 2013 at 5:19 PM, John McCall <rjmccall at apple.com> wrote:
> Author: rjmccall
> Date: Wed Apr 3 16:19:47 2013
> New Revision: 178698
>
> URL: http://llvm.org/viewvc/llvm-project?rev=178698&view=rev
> Log:
> Complain about attempts to befriend declarations via a using
> declaration. Patch by Stephen Lin!
>
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaOverload.cpp
> cfe/trunk/test/SemaCXX/friend.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=178698&r1=178697&r2=178698&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 3 16:19:47 2013
> @@ -867,6 +867,8 @@ def err_friend_def_in_local_class : Erro
> "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 |"
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=178698&r1=178697&r2=178698&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Apr 3 16:19:47 2013
> @@ -2277,6 +2277,15 @@ bool Sema::MergeFunctionDecl(FunctionDec
> 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);
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=178698&r1=178697&r2=178698&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Apr 3 16:19:47 2013
> @@ -920,7 +920,8 @@ Sema::CheckOverload(Scope *S, FunctionDe
> // 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)) {
>
> Modified: cfe/trunk/test/SemaCXX/friend.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend.cpp?rev=178698&r1=178697&r2=178698&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/friend.cpp (original)
> +++ cfe/trunk/test/SemaCXX/friend.cpp Wed Apr 3 16:19:47 2013
> @@ -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}}
> + };
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list