From 56636589ffd881eac56c57bd06c6b12f19762d16 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 9 Oct 2011 22:38:36 +0000 Subject: [PATCH] The effective context of a friend function is its lexical context. Fixes PR9103. llvm-svn: 141520 --- clang/lib/Sema/SemaAccess.cpp | 6 +++++- clang/test/CXX/class.access/class.friend/p1.cpp | 13 +++++++++++++ clang/test/CXX/class.access/class.protected/p1.cpp | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 14c8ebafe7d2..d322ebd41007 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -103,7 +103,11 @@ struct EffectiveContext { } else if (isa(DC)) { FunctionDecl *Function = cast(DC)->getCanonicalDecl(); Functions.push_back(Function); - DC = Function->getDeclContext(); + + if (Function->getFriendObjectKind()) + DC = Function->getLexicalDeclContext(); + else + DC = Function->getDeclContext(); } else if (DC->isFileContext()) { break; } else { diff --git a/clang/test/CXX/class.access/class.friend/p1.cpp b/clang/test/CXX/class.access/class.friend/p1.cpp index 1668155c1819..68ff83fee83c 100644 --- a/clang/test/CXX/class.access/class.friend/p1.cpp +++ b/clang/test/CXX/class.access/class.friend/p1.cpp @@ -341,3 +341,16 @@ namespace test12 { void *var = static_cast(this)->mem; } } + +namespace PR9103 { + struct base { + protected: + static void foo(void) {} + }; + + struct cls: base { + friend void bar(void) { + base::foo(); + } + }; +} diff --git a/clang/test/CXX/class.access/class.protected/p1.cpp b/clang/test/CXX/class.access/class.protected/p1.cpp index 8698fb1da8a5..79bb6cd67eab 100644 --- a/clang/test/CXX/class.access/class.protected/p1.cpp +++ b/clang/test/CXX/class.access/class.protected/p1.cpp @@ -423,7 +423,7 @@ namespace test12 { // This friendship is not considered because a public member of A is // inaccessible in C. namespace test13 { - class A { protected: int foo(); }; // expected-note {{declared protected here}} + class A { protected: int foo(); }; // expected-note {{object type 'test13::D' must derive from context type 'test13::C'}} class B : private virtual A {}; class C : private B { friend void test(); }; class D : public virtual A {};