forked from OSchip/llvm-project
Don't look outside the innermost enclosing namespace when
performing unqualified lookup for a friend class declaration. rdar://13393749 llvm-svn: 177473
This commit is contained in:
parent
be99cc3a3e
commit
3c581bf152
|
@ -9467,6 +9467,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
// 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();
|
||||
|
@ -9478,6 +9480,27 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
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.
|
||||
if (Previous.isAmbiguous())
|
||||
return 0;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue