aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2010-04-18 08:23:21 +0000
committerChandler Carruth <chandlerc@gmail.com>2010-04-18 08:23:21 +0000
commit630eb01b2568d0958118eb1a0ded02bebecb2b0f (patch)
tree04dc97e076b99d38363f9b8d20ff87a6cbbdab5e
parent2559a7045a74679c80376305397a5953d038e1d0 (diff)
Fix the access checking of function and function template argument types,
return types, and default arguments. This fixes PR6855 along with several similar cases where we rejected valid code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101706 91177308-0d34-0410-b5e6-96231b3b80d8
-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);
+}