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