aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-01-28 01:42:12 +0000
committerJohn McCall <rjmccall@apple.com>2010-01-28 01:42:12 +0000
commit5357b615364c17ea024c757354c58ae2a520d216 (patch)
treeee929cb4cba153752e89f840b7a34312b2cc3c45
parent7e20ffe322866f6a2e820e054da9bd0f6e9b0af4 (diff)
Access checking for overloaded operators.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94725 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaAccess.cpp24
-rw-r--r--lib/Sema/SemaOverload.cpp11
-rw-r--r--test/CXX/class.access/p4.cpp36
4 files changed, 68 insertions, 5 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index fb3ca1c465..8768828365 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2431,6 +2431,8 @@ public:
bool CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
NamedDecl *D,
AccessSpecifier Access);
+ bool CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
+ NamedDecl *D, AccessSpecifier Access);
bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access);
void CheckAccess(const LookupResult &R);
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index f3c10392f7..34c9718014 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -306,6 +306,30 @@ bool Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
return false;
}
+/// Checks access to an overloaded member operator.
+bool Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
+ Expr *ObjectExpr,
+ NamedDecl *MemberOperator,
+ AccessSpecifier Access) {
+ if (!getLangOptions().AccessControl)
+ return false;
+
+ const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
+ assert(RT && "found member operator but object expr not of record type");
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+
+ LookupResult R(*this, DeclarationName(), OpLoc, LookupOrdinaryName);
+ R.suppressDiagnostics();
+
+ R.setNamingClass(NamingClass);
+ if (CheckAccess(R, MemberOperator, Access))
+ return true;
+
+ // FIXME: protected check
+
+ return false;
+}
+
/// Checks access to all the declarations in the given result set.
void Sema::CheckAccess(const LookupResult &R) {
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2d48674228..5506eeb4b2 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5515,10 +5515,10 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// We matched an overloaded operator. Build a call to that
// operator.
- // FIXME: access control
-
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+ CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess());
+
if (PerformObjectArgumentInitialization(Input, Method))
return ExprError();
} else {
@@ -5698,10 +5698,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched an overloaded operator. Build a call to that
// operator.
- // FIXME: access control
-
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+ // Best->Access is only meaningful for class members.
+ CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess());
+
OwningExprResult Arg1
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
@@ -5873,7 +5874,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched an overloaded operator. Build a call to that
// operator.
- // FIXME: access control
+ CheckMemberOperatorAccess(LLoc, Args[0], FnDecl, Best->getAccess());
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp
index 7d89659901..3f4397a28b 100644
--- a/test/CXX/class.access/p4.cpp
+++ b/test/CXX/class.access/p4.cpp
@@ -31,3 +31,39 @@ namespace test0 {
void (A::*c)(Private&) = &A::foo; // expected-error {{access to private member outside any class}}
}
}
+
+// Member operators.
+namespace test1 {
+ class A {
+ public:
+ void operator+(Public&);
+ void operator[](Public&);
+ protected:
+ void operator+(Protected&); // expected-note {{declared protected here}}
+ void operator[](Protected&); // expected-note {{declared protected here}}
+ private:
+ void operator+(Private&); // expected-note {{declared private here}}
+ void operator[](Private&); // expected-note {{declared private here}}
+ void operator-(); // expected-note {{declared private here}}
+ };
+ void operator+(const A &, Public&);
+ void operator+(const A &, Protected&);
+ void operator+(const A &, Private&);
+ void operator-(const A &);
+
+ void test(A &a, Public &pub, Protected &prot, Private &priv) {
+ a + pub;
+ a + prot; // expected-error {{access to protected member}}
+ a + priv; // expected-error {{access to private member}}
+ a[pub];
+ a[prot]; // expected-error {{access to protected member}}
+ a[priv]; // expected-error {{access to private member}}
+ -a; // expected-error {{access to private member}}
+
+ const A &ca = a;
+ ca + pub;
+ ca + prot;
+ ca + priv;
+ -ca;
+ }
+}