[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