On Tue, Mar 19, 2013 at 6:53 PM, John McCall <[email protected]> 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 > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
