Access control for implicit calls to copy assignment operators and copy
constructors from implicitly-defined members.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98614 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 2675734..4c25844 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -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,
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 818d369..f0a38d5 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -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,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1b3612d..c27b0d5 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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();