Access checking for overloaded operators.

llvm-svn: 94725
This commit is contained in:
John McCall 2010-01-28 01:42:12 +00:00
parent 81310810bd
commit b3a4400554
4 changed files with 68 additions and 5 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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;
}
}