r177473 - Don't look outside the innermost enclosing namespace when
David Blaikie
dblaikie at gmail.com
Tue Mar 19 19:13:16 PDT 2013
On Tue, Mar 19, 2013 at 6:53 PM, John McCall <rjmccall at apple.com> wrote:
> Author: rjmccall
> Date: Tue Mar 19 20:53:00 2013
> New Revision: 177473
>
> URL: http://llvm.org/viewvc/llvm-project?rev=177473&view=rev
> Log:
> Don't look outside the innermost enclosing namespace when
> performing unqualified lookup for a friend class declaration.
>
> rdar://13393749
AKA PR15496
Thanks for the fix, John!
- David
>
> Modified:
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=177473&r1=177472&r2=177473&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 19 20:53:00 2013
> @@ -9467,6 +9467,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned
> // shouldn't be diagnosing.
> LookupName(Previous, S);
>
> + // When declaring or defining a tag, ignore ambiguities introduced
> + // by types using'ed into this scope.
> if (Previous.isAmbiguous() &&
> (TUK == TUK_Definition || TUK == TUK_Declaration)) {
> LookupResult::Filter F = Previous.makeFilter();
> @@ -9476,6 +9478,27 @@ Decl *Sema::ActOnTag(Scope *S, unsigned
> F.erase();
> }
> F.done();
> + }
> +
> + // C++11 [namespace.memdef]p3:
> + // If the name in a friend declaration is neither qualified nor
> + // a template-id and the declaration is a function or an
> + // elaborated-type-specifier, the lookup to determine whether
> + // the entity has been previously declared shall not consider
> + // any scopes outside the innermost enclosing namespace.
> + //
> + // Does it matter that this should be by scope instead of by
> + // semantic context?
> + if (!Previous.empty() && TUK == TUK_Friend) {
> + DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext();
> + LookupResult::Filter F = Previous.makeFilter();
> + while (F.hasNext()) {
> + NamedDecl *ND = F.next();
> + DeclContext *DC = ND->getDeclContext()->getRedeclContext();
> + if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext()))
> + F.erase();
> + }
> + F.done();
> }
>
> // Note: there used to be some attempt at recovery here.
>
> Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp?rev=177473&r1=177472&r2=177473&view=diff
> ==============================================================================
> --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp (original)
> +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp Tue Mar 19 20:53:00 2013
> @@ -91,3 +91,104 @@ namespace test5 {
> template void f<int>(int);
> template void f<long>(long); //expected-note {{instantiation}}
> }
> +
> +// rdar://13393749
> +namespace test6 {
> + class A;
> + namespace ns {
> + class B {
> + static void foo(); // expected-note {{implicitly declared private here}}
> + friend union A;
> + };
> +
> + union A {
> + void test() {
> + B::foo();
> + }
> + };
> + }
> +
> + class A {
> + void test() {
> + ns::B::foo(); // expected-error {{'foo' is a private member of 'test6::ns::B'}}
> + }
> + };
> +}
> +
> +// We seem to be following a correct interpretation with these, but
> +// the standard could probably be a bit clearer.
> +namespace test7a {
> + namespace ns {
> + class A;
> + }
> +
> + using namespace ns;
> + class B {
> + static void foo();
> + friend class A;
> + };
> +
> + class ns::A {
> + void test() {
> + B::foo();
> + }
> + };
> +}
> +namespace test7b {
> + namespace ns {
> + class A;
> + }
> +
> + using ns::A;
> + class B {
> + static void foo();
> + friend class A;
> + };
> +
> + class ns::A {
> + void test() {
> + B::foo();
> + }
> + };
> +}
> +namespace test7c {
> + namespace ns1 {
> + class A;
> + }
> +
> + namespace ns2 {
> + // ns1::A appears as if declared in test7c according to [namespace.udir]p2.
> + // I think that means we aren't supposed to find it.
> + using namespace ns1;
> + class B {
> + static void foo(); // expected-note {{implicitly declared private here}}
> + friend class A;
> + };
> + }
> +
> + class ns1::A {
> + void test() {
> + ns2::B::foo(); // expected-error {{'foo' is a private member of 'test7c::ns2::B'}}
> + }
> + };
> +}
> +namespace test7d {
> + namespace ns1 {
> + class A;
> + }
> +
> + namespace ns2 {
> + // Honor the lexical context of a using-declaration, though.
> + using ns1::A;
> + class B {
> + static void foo();
> + friend class A;
> + };
> + }
> +
> + class ns1::A {
> + void test() {
> + ns2::B::foo();
> + }
> + };
> +}
>
>
> _______________________________________________
> 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