[cfe-commits] r103010 - in /cfe/trunk: include/clang/AST/UnresolvedSet.h lib/Sema/SemaDeclCXX.cpp test/SemaCXX/default-assignment-operator.cpp

Douglas Gregor dgregor at apple.com
Tue May 4 08:20:55 PDT 2010


Author: dgregor
Date: Tue May  4 10:20:55 2010
New Revision: 103010

URL: http://llvm.org/viewvc/llvm-project?rev=103010&view=rev
Log:
When creating a call to a base subobject's operator= in an
implicitly-defined copy assignment operator, suppress the protected
access check. This eliminates the remaining failure in the
Boost.SmartPtr library (that was a product of the copy-assignment
generation rewrite) and, presumably, the Boost.TR1 library as well.


Modified:
    cfe/trunk/include/clang/AST/UnresolvedSet.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/default-assignment-operator.cpp

Modified: cfe/trunk/include/clang/AST/UnresolvedSet.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/UnresolvedSet.h?rev=103010&r1=103009&r2=103010&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/UnresolvedSet.h (original)
+++ cfe/trunk/include/clang/AST/UnresolvedSet.h Tue May  4 10:20:55 2010
@@ -45,6 +45,7 @@
 
   NamedDecl *getDecl() const { return ir->getDecl(); }
   AccessSpecifier getAccess() const { return ir->getAccess(); }
+  void setAccess(AccessSpecifier AS) { ir->setAccess(AS); }
   DeclAccessPair getPair() const { return *ir; }
 
   NamedDecl *operator*() const { return getDecl(); }

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=103010&r1=103009&r2=103010&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue May  4 10:20:55 2010
@@ -4134,13 +4134,16 @@
 ///
 /// \param From The expression we are copying from.
 ///
+/// \param CopyingBaseSubobject Whether we're copying a base subobject.
+/// Otherwise, it's a non-static member subobject.
+///
 /// \param Depth Internal parameter recording the depth of the recursion.
 ///
 /// \returns A statement or a loop that copies the expressions.
 static Sema::OwningStmtResult
 BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, 
                       Sema::OwningExprResult To, Sema::OwningExprResult From,
-                      unsigned Depth = 0) {
+                      bool CopyingBaseSubobject, unsigned Depth = 0) {
   typedef Sema::OwningStmtResult OwningStmtResult;
   typedef Sema::OwningExprResult OwningExprResult;
   
@@ -4172,6 +4175,25 @@
     }
     F.done();
     
+    // Suppress the protected check (C++ [class.protected]) for each of the
+    // assignment operators we found. This strange dance is required when 
+    // we're assigning via a base classes's copy-assignment operator. To
+    // ensure that we're getting the right base class subobject (without 
+    // ambiguities), we need to cast "this" to that subobject type; to
+    // ensure that we don't go through the virtual call mechanism, we need
+    // to qualify the operator= name with the base class (see below). However,
+    // this means that if the base class has a protected copy assignment
+    // operator, the protected member access check will fail. So, we
+    // rewrite "protected" access to "public" access in this case, since we
+    // know by construction that we're calling from a derived class.
+    if (CopyingBaseSubobject) {
+      for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end();
+           L != LEnd; ++L) {
+        if (L.getAccess() == AS_protected)
+          L.setAccess(AS_public);
+      }
+    }
+    
     // Create the nested-name-specifier that will be used to qualify the
     // reference to operator=; this is required to suppress the virtual
     // call mechanism.
@@ -4277,7 +4299,8 @@
   // Build the copy for an individual element of the array.
   OwningStmtResult Copy = BuildSingleCopyAssign(S, Loc, 
                                                 ArrayTy->getElementType(),
-                                                move(To), move(From), Depth+1);
+                                                move(To), move(From), 
+                                                CopyingBaseSubobject, Depth+1);
   if (Copy.isInvalid()) {
     InitStmt->Destroy(S.Context);
     return S.StmtError();
@@ -4381,7 +4404,8 @@
 
     // Build the copy.
     OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType,
-                                                  move(To), Owned(From));
+                                                  move(To), Owned(From),
+                                                /*CopyingBaseSubobject=*/true);
     if (Copy.isInvalid()) {
       Invalid = true;
       continue;
@@ -4501,7 +4525,8 @@
     
     // Build the copy of this field.
     OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, 
-                                                  move(To), move(From));
+                                                  move(To), move(From),
+                                              /*CopyingBaseSubobject=*/false);
     if (Copy.isInvalid()) {
       Invalid = true;
       continue;

Modified: cfe/trunk/test/SemaCXX/default-assignment-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/default-assignment-operator.cpp?rev=103010&r1=103009&r2=103010&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/default-assignment-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/default-assignment-operator.cpp Tue May  4 10:20:55 2010
@@ -89,3 +89,31 @@
   e1 = e2; 
 }
 
+namespace ProtectedCheck {
+  struct X {
+  protected:
+    X &operator=(const X&); // expected-note{{declared protected here}}
+  };
+
+  struct Y : public X { };
+
+  void f(Y y) { y = y; }
+
+  struct Z { // expected-error{{'operator=' is a protected member of 'ProtectedCheck::X'}}
+    X x;
+  };
+
+  void f(Z z) { z = z; } // 
+}
+
+namespace MultiplePaths {
+  struct X0 { 
+    X0 &operator=(const X0&);
+  };
+
+  struct X1 : public virtual X0 { };
+
+  struct X2 : X0, X1 { };
+
+  void f(X2 x2) { x2 = x2; }
+}





More information about the cfe-commits mailing list