[cfe-commits] r112360 - in /cfe/trunk: lib/Sema/SemaAccess.cpp test/CXX/class.access/class.protected/p1.cpp

John McCall rjmccall at apple.com
Sat Aug 28 01:47:22 PDT 2010


Author: rjmccall
Date: Sat Aug 28 03:47:21 2010
New Revision: 112360

URL: http://llvm.org/viewvc/llvm-project?rev=112360&view=rev
Log:
That's not the right direction to compute notional accessibility in at all.


Modified:
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/test/CXX/class.access/class.protected/p1.cpp

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=112360&r1=112359&r2=112360&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Sat Aug 28 03:47:21 2010
@@ -586,11 +586,12 @@
                      NamingClass->isDependentContext()),
       EverDependent(false) {}
 
-  /// Check everything in the current path for friendship.
-  bool checkFriendshipAlongPath() {
-    for (llvm::SmallVectorImpl<const CXXRecordDecl*>::iterator
-           I = CurPath.begin(), E = CurPath.end(); I != E; ++I) {
-      switch (GetFriendKind(S, EC, *I)) {
+  /// Check classes in the current path for friendship, starting at
+  /// the given index.
+  bool checkFriendshipAlongPath(unsigned I) {
+    assert(I < CurPath.size());
+    for (unsigned E = CurPath.size(); I != E; ++I) {
+      switch (GetFriendKind(S, EC, CurPath[I])) {
       case AR_accessible:   return true;
       case AR_inaccessible: continue;
       case AR_dependent:    EverDependent = true; continue;
@@ -600,17 +601,16 @@
   }
 
   /// Perform a search starting at the given class.
-  bool findFriendship(const CXXRecordDecl *Cur) {
-    CurPath.push_back(Cur);
-
+  ///
+  /// PrivateDepth is the index of the last (least derived) class
+  /// along the current path such that a notional public member of
+  /// the final class in the path would have access in that class.
+  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
     // If we ever reach the naming class, check the current path for
     // friendship.  We can also stop recursing because we obviously
     // won't find the naming class there again.
-    if (Cur == NamingClass) {
-      bool Result = checkFriendshipAlongPath();
-      CurPath.pop_back();
-      return Result;
-    }
+    if (Cur == NamingClass)
+      return checkFriendshipAlongPath(PrivateDepth);
 
     if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
       EverDependent = true;
@@ -619,12 +619,11 @@
     for (CXXRecordDecl::base_class_const_iterator
            I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
 
-      // If this base specifier has private access, and this isn't the
-      // first step in the derivation chain, then the base does not
-      // have natural access along this derivation path and we should
-      // ignore it.
-      if (I->getAccessSpecifier() == AS_private && CurPath.size() != 1)
-          continue;
+      // If this is private inheritance, then a public member of the
+      // base will not have any access in classes derived from Cur.
+      unsigned BasePrivateDepth = PrivateDepth;
+      if (I->getAccessSpecifier() == AS_private)
+        BasePrivateDepth = CurPath.size() - 1;
 
       const CXXRecordDecl *RD;
 
@@ -641,12 +640,20 @@
       }
 
       // Recurse.  We don't need to clean up if this returns true.
-      if (findFriendship(RD->getCanonicalDecl())) return true;
+      CurPath.push_back(RD);
+      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
+        return true;
+      CurPath.pop_back();
     }
 
-    CurPath.pop_back();
     return false;
   }
+
+  bool findFriendship(const CXXRecordDecl *Cur) {
+    assert(CurPath.empty());
+    CurPath.push_back(Cur);
+    return findFriendship(Cur, 0);
+  }
 };
 }
 

Modified: cfe/trunk/test/CXX/class.access/class.protected/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.protected/p1.cpp?rev=112360&r1=112359&r2=112360&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.protected/p1.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.protected/p1.cpp Sat Aug 28 03:47:21 2010
@@ -405,3 +405,31 @@
     }
   };
 }
+
+// This friendship is considered because a public member of A would be
+// a private member of C.
+namespace test12 {
+  class A { protected: int foo(); };
+  class B : public virtual A {};
+  class C : private B { friend void test(); };
+  class D : private C, public virtual A {};
+
+  void test() {
+    D d;
+    d.A::foo();
+  }
+}
+
+// This friendship is not considered because a public member of A is
+// inaccessible in C.
+namespace test13 {
+  class A { protected: int foo(); }; // expected-note {{declared protected here}}
+  class B : private virtual A {};
+  class C : private B { friend void test(); };
+  class D : public virtual A {};
+
+  void test() {
+    D d;
+    d.A::foo(); // expected-error {{protected member}}
+  }
+}





More information about the cfe-commits mailing list