aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-10-09 22:38:36 +0000
committerDouglas Gregor <dgregor@apple.com>2011-10-09 22:38:36 +0000
commitac57f0b9097e04f70a631549383a2944f74ad844 (patch)
tree65de43b5481fcb0b85e0fdcbfb0011835576410c
parent6c73a2975ba9112787380abd878876336957b3f6 (diff)
The effective context of a friend function is its lexical
context. Fixes PR9103. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141520 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaAccess.cpp6
-rw-r--r--test/CXX/class.access/class.friend/p1.cpp13
-rw-r--r--test/CXX/class.access/class.protected/p1.cpp2
3 files changed, 19 insertions, 2 deletions
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 14c8ebafe7..d322ebd410 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -103,7 +103,11 @@ struct EffectiveContext {
} else if (isa<FunctionDecl>(DC)) {
FunctionDecl *Function = cast<FunctionDecl>(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/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp
index 1668155c18..68ff83fee8 100644
--- a/test/CXX/class.access/class.friend/p1.cpp
+++ b/test/CXX/class.access/class.friend/p1.cpp
@@ -341,3 +341,16 @@ namespace test12 {
void *var = static_cast<B*>(this)->mem;
}
}
+
+namespace PR9103 {
+ struct base {
+ protected:
+ static void foo(void) {}
+ };
+
+ struct cls: base {
+ friend void bar(void) {
+ base::foo();
+ }
+ };
+}
diff --git a/test/CXX/class.access/class.protected/p1.cpp b/test/CXX/class.access/class.protected/p1.cpp
index 8698fb1da8..79bb6cd67e 100644
--- a/test/CXX/class.access/class.protected/p1.cpp
+++ b/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 {};