[cfe-commits] r98614 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaAccess.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/class.access/p4.cpp

John McCall rjmccall at apple.com
Mon Mar 15 23:11:48 PDT 2010


Author: rjmccall
Date: Tue Mar 16 01:11:48 2010
New Revision: 98614

URL: http://llvm.org/viewvc/llvm-project?rev=98614&view=rev
Log:
Access control for implicit calls to copy assignment operators and copy
constructors from implicitly-defined members.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/class.access/p4.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=98614&r1=98613&r2=98614&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 16 01:11:48 2010
@@ -447,6 +447,20 @@
 def err_access_dtor_var :
     Error<"variable of type %1 has %select{private|protected}2 destructor">,
     NoSFINAE;
+def err_access_assign_field :
+    Error<"field of type %1 has %select{private|protected}2 copy assignment"
+          " operator">,
+    NoSFINAE;
+def err_access_assign_base :
+    Error<"base class %0 has %select{private|protected}1 copy assignment"
+          " operator">,
+    NoSFINAE;
+def err_access_copy_field :
+    Error<"field of type %1 has %select{private|protected}2 copy constructor">,
+    NoSFINAE;
+def err_access_copy_base :
+    Error<"base class %0 has %select{private|protected}1 copy constructor">,
+    NoSFINAE;
 def note_previous_access_declaration : Note<
   "previously declared '%1' here">;
 def err_access_outside_class : Error<

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=98614&r1=98613&r2=98614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 16 01:11:48 2010
@@ -2628,6 +2628,9 @@
   AccessResult CheckDestructorAccess(SourceLocation Loc,
                                      CXXDestructorDecl *Dtor,
                                      const PartialDiagnostic &PDiag);
+  AccessResult CheckDirectMemberAccess(SourceLocation Loc,
+                                       NamedDecl *D,
+                                       const PartialDiagnostic &PDiag);
   AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
                                          Expr *ObjectExpr,
                                          Expr *ArgExpr,

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=98614&r1=98613&r2=98614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Tue Mar 16 01:11:48 2010
@@ -495,6 +495,23 @@
   return CheckAccess(*this, UseLoc, Entity);
 }
 
+/// Checks direct (i.e. non-inherited) access to an arbitrary class
+/// member.
+Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
+                                                 NamedDecl *Target,
+                                           const PartialDiagnostic &Diag) {
+  AccessSpecifier Access = Target->getAccess();
+  if (!getLangOptions().AccessControl ||
+      Access == AS_public)
+    return AR_accessible;
+
+  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
+  AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Target);
+  Entity.setDiag(Diag);
+  return CheckAccess(*this, UseLoc, Entity);
+}
+                                           
+
 /// Checks access to an overloaded member operator, including
 /// conversion operators.
 Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=98614&r1=98613&r2=98614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar 16 01:11:48 2010
@@ -3862,8 +3862,14 @@
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXMethodDecl *BaseAssignOpMethod =
           getAssignOperatorMethod(CurrentLocation, MethodDecl->getParamDecl(0), 
-                                  BaseClassDecl))
+                                  BaseClassDecl)) {
+      CheckDirectMemberAccess(Base->getSourceRange().getBegin(),
+                              BaseAssignOpMethod,
+                              PartialDiagnostic(diag::err_access_assign_base)
+                                << Base->getType());
+
       MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod);
+    }
   }
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
        E = ClassDecl->field_end(); Field != E; ++Field) {
@@ -3875,8 +3881,14 @@
         = cast<CXXRecordDecl>(FieldClassType->getDecl());
       if (CXXMethodDecl *FieldAssignOpMethod =
           getAssignOperatorMethod(CurrentLocation, MethodDecl->getParamDecl(0), 
-                                  FieldClassDecl))
+                                  FieldClassDecl)) {
+        CheckDirectMemberAccess(Field->getLocation(),
+                                FieldAssignOpMethod,
+                                PartialDiagnostic(diag::err_access_assign_field)
+                                  << Field->getDeclName() << Field->getType());
+
         MarkDeclarationReferenced(CurrentLocation, FieldAssignOpMethod);
+      }
     } else if (FieldType->isReferenceType()) {
       Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
       << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
@@ -3951,8 +3963,14 @@
     CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     if (CXXConstructorDecl *BaseCopyCtor =
-        BaseClassDecl->getCopyConstructor(Context, TypeQuals))
+        BaseClassDecl->getCopyConstructor(Context, TypeQuals)) {
+      CheckDirectMemberAccess(Base->getSourceRange().getBegin(),
+                              BaseCopyCtor,
+                              PartialDiagnostic(diag::err_access_copy_base)
+                                << Base->getType());
+
       MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
+    }
   }
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
                                   FieldEnd = ClassDecl->field_end();
@@ -3964,8 +3982,14 @@
       CXXRecordDecl *FieldClassDecl
         = cast<CXXRecordDecl>(FieldClassType->getDecl());
       if (CXXConstructorDecl *FieldCopyCtor =
-          FieldClassDecl->getCopyConstructor(Context, TypeQuals))
+          FieldClassDecl->getCopyConstructor(Context, TypeQuals)) {
+        CheckDirectMemberAccess(Field->getLocation(),
+                                FieldCopyCtor,
+                                PartialDiagnostic(diag::err_access_copy_field)
+                                  << Field->getDeclName() << Field->getType());
+
         MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
+      }
     }
   }
   CopyConstructor->setUsed();

Modified: cfe/trunk/test/CXX/class.access/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=98614&r1=98613&r2=98614&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/p4.cpp (original)
+++ cfe/trunk/test/CXX/class.access/p4.cpp Tue Mar 16 01:11:48 2010
@@ -183,3 +183,40 @@
   Private test1(Derived4 &d) { return d; }
   Public test2(Derived4 &d) { return d; }
 }
+
+// Implicit copy assignment operator uses.
+namespace test5 {
+  class A {
+    void operator=(const A &); // expected-note 2 {{declared private here}}
+  };
+
+  class Test1 { A a; }; // expected-error {{field of type 'test5::A' has private copy assignment operator}}
+  void test1() {
+    Test1 a;
+    a = Test1();
+  }
+
+  class Test2 : A {}; // expected-error {{base class 'test5::A' has private copy assignment operator}}
+  void test2() {
+    Test2 a;
+    a = Test2();
+  }
+}
+
+// Implicit copy constructor uses.
+namespace test6 {
+  class A {
+    public: A();
+    private: A(const A &); // expected-note 2 {{declared private here}}
+  };
+
+  class Test1 { A a; }; // expected-error {{field of type 'test6::A' has private copy constructor}}
+  void test1(const Test1 &t) {
+    Test1 a = t;
+  }
+
+  class Test2 : A {}; // expected-error {{base class 'test6::A' has private copy constructor}}
+  void test2(const Test2 &t) {
+    Test2 a = t;
+  }
+}





More information about the cfe-commits mailing list