]> granicus.if.org Git - clang/commitdiff
Access checking for overloaded operators.
authorJohn McCall <rjmccall@apple.com>
Thu, 28 Jan 2010 01:42:12 +0000 (01:42 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 28 Jan 2010 01:42:12 +0000 (01:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94725 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaAccess.cpp
lib/Sema/SemaOverload.cpp
test/CXX/class.access/p4.cpp

index fb3ca1c46540153663536a06bbd959421a38aecc..8768828365e564683b445fdf50c3a32c3df9735d 100644 (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);
 
index f3c10392f7c9e25cba63bbb07bcc5e42b5c60163..34c9718014c8292eed39df0cfbe6584be62a10e3 100644 (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)
index 2d48674228f077e0f9b7eed3917d8e54abeb6db2..5506eeb4b2dc8d0d1e60935c9d7fc8da8308ac36 100644 (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);
index 7d89659901ae67a351ea824fd01b353e642987c3..3f4397a28b4bf6cebb88c1b7fe2a54bb3397fbc3 100644 (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;
+  }
+}