From: John McCall Date: Thu, 28 Jan 2010 01:42:12 +0000 (+0000) Subject: Access checking for overloaded operators. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5357b615364c17ea024c757354c58ae2a520d216;p=clang Access checking for overloaded operators. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94725 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(); + assert(RT && "found member operator but object expr not of record type"); + CXXRecordDecl *NamingClass = cast(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(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(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(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; + } +}