When filtering out previous declarations of friend functions, consider the

lookup context, not the direct semantic context.  Fixes PR7230.

llvm-svn: 104917
This commit is contained in:
John McCall 2010-05-28 01:41:47 +00:00
parent 3743b8cf49
commit 4583186b8b
2 changed files with 32 additions and 8 deletions

View File

@ -5762,13 +5762,18 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
LookupQualifiedName(Previous, DC);
// If searching in that context implicitly found a declaration in
// a different context, treat it like it wasn't found at all.
// Ignore things found implicitly in the wrong scope.
// TODO: better diagnostics for this case. Suggesting the right
// qualified scope would be nice...
// FIXME: getRepresentativeDecl() is not right here at all
if (Previous.empty() ||
!Previous.getRepresentativeDecl()->getDeclContext()->Equals(DC)) {
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
if (!D->getDeclContext()->getLookupContext()->Equals(DC))
F.erase();
}
F.done();
if (Previous.empty()) {
D.setInvalidType();
Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
return DeclPtrTy();

View File

@ -6,9 +6,6 @@
// its friends, if any, by way of friend declarations. Such declarations give
// special access rights to the friends, but they do not make the nominated
// friends members of the befriending class.
//
// FIXME: Add tests for access control when implemented. Currently we only test
// for parsing.
struct S { static void f(); };
S* g() { return 0; }
@ -287,3 +284,25 @@ namespace test9 {
friend class test9;
};
}
// PR7230
namespace test10 {
extern "C" void f(void);
extern "C" void g(void);
namespace NS {
class C {
void foo(void); // expected-note {{declared private here}}
friend void test10::f(void);
};
static C* bar;
}
void f(void) {
NS::bar->foo();
}
void g(void) {
NS::bar->foo(); // expected-error {{private member}}
}
}