aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaAccess.cpp11
-rw-r--r--test/CXX/class.access/class.friend/p1.cpp24
2 files changed, 33 insertions, 2 deletions
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 520a9708c6..352477b859 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -1015,8 +1015,15 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
// Pretend we did this from the context of the newly-parsed
- // declaration.
- EffectiveContext EC(Ctx->getDeclContext());
+ // declaration. If that declaration itself forms a declaration context,
+ // include it in the effective context so that parameters and return types of
+ // befriended functions have that function's access priveledges.
+ DeclContext *DC = Ctx->getDeclContext();
+ if (isa<FunctionDecl>(Ctx))
+ DC = cast<DeclContext>(Ctx);
+ else if (FunctionTemplateDecl *FnTpl = dyn_cast<FunctionTemplateDecl>(Ctx))
+ DC = cast<DeclContext>(FnTpl->getTemplatedDecl());
+ EffectiveContext EC(DC);
AccessTarget Target(DD.getAccessData());
diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp
index 8dffd1dd86..91d7661be3 100644
--- a/test/CXX/class.access/class.friend/p1.cpp
+++ b/test/CXX/class.access/class.friend/p1.cpp
@@ -256,3 +256,27 @@ namespace test7 {
A a; // expected-error {{calling a private constructor}}
}
}
+
+// Return types, parameters and default arguments to friend functions.
+namespace test8 {
+ class A {
+ typedef int I; // expected-note 4 {{declared private here}}
+ static const I x = 0;
+ friend I f(I i);
+ template<typename T> friend I g(I i);
+ };
+
+ // FIXME: This should be on line 264.
+ const A::I A::x; // expected-note {{declared private here}}
+ A::I f(A::I i = A::x) {}
+ template<typename T> A::I g(A::I i) {
+ T t;
+ }
+ template A::I g<A::I>(A::I i);
+
+ A::I f2(A::I i = A::x) {} // expected-error 3 {{is a private member of}}
+ template<typename T> A::I g2(A::I i) { // expected-error 2 {{is a private member of}}
+ T t;
+ }
+ template A::I g2<A::I>(A::I i);
+}