[cfe-commits] r102999 - in /cfe/trunk: lib/Sema/SemaAccess.cpp test/CXX/class.access/p4.cpp
John McCall
rjmccall at apple.com
Mon May 3 22:11:28 PDT 2010
Author: rjmccall
Date: Tue May 4 00:11:27 2010
New Revision: 102999
URL: http://llvm.org/viewvc/llvm-project?rev=102999&view=rev
Log:
An access is permitted if the current template instantiates to the appropriate
class. Add some conservative support for the idea. Fixes PR 7024.
Modified:
cfe/trunk/lib/Sema/SemaAccess.cpp
cfe/trunk/test/CXX/class.access/p4.cpp
Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=102999&r1=102998&r2=102999&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Tue May 4 00:11:27 2010
@@ -222,6 +222,22 @@
}
+/// Checks whether one class might instantiate to the other.
+static bool MightInstantiateTo(const CXXRecordDecl *From,
+ const CXXRecordDecl *To) {
+ // Declaration names are always preserved by instantiation.
+ if (From->getDeclName() != To->getDeclName())
+ return false;
+
+ const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
+ const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
+ if (FromDC == ToDC) return true;
+ if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
+
+ // Be conservative.
+ return true;
+}
+
/// Checks whether one class is derived from another, inclusively.
/// Properly indicates when it couldn't be determined due to
/// dependence.
@@ -234,6 +250,10 @@
if (Derived == Target) return AR_accessible;
+ bool CheckDependent = Derived->isDependentContext();
+ if (CheckDependent && MightInstantiateTo(Derived, Target))
+ return AR_dependent;
+
AccessResult OnFailure = AR_inaccessible;
llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
@@ -246,10 +266,10 @@
QualType T = I->getType();
if (const RecordType *RT = T->getAs<RecordType>()) {
RD = cast<CXXRecordDecl>(RT->getDecl());
+ } else if (const InjectedClassNameType *IT
+ = T->getAs<InjectedClassNameType>()) {
+ RD = IT->getDecl();
} else {
- // It's possible for a base class to be the current
- // instantiation of some enclosing template, but I'm guessing
- // nobody will ever care that we just dependently delay here.
assert(T->isDependentType() && "non-dependent base wasn't a record?");
OnFailure = AR_dependent;
continue;
@@ -257,6 +277,9 @@
RD = RD->getCanonicalDecl();
if (RD == Target) return AR_accessible;
+ if (CheckDependent && MightInstantiateTo(RD, Target))
+ OnFailure = AR_dependent;
+
Queue.push_back(RD);
}
@@ -563,6 +586,9 @@
if (ECRecord == NamingClass)
return AR_accessible;
+ if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
+ OnFailure = AR_dependent;
+
// [B3] and [M3]
} else {
assert(Access == AS_protected);
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=102999&r1=102998&r2=102999&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/p4.cpp (original)
+++ cfe/trunk/test/CXX/class.access/p4.cpp Tue May 4 00:11:27 2010
@@ -363,3 +363,58 @@
}
}
+// PR 7024
+namespace test15 {
+ template <class T> class A {
+ private:
+ int private_foo; // expected-note {{declared private here}}
+ static int private_sfoo; // expected-note {{declared private here}}
+ protected:
+ int protected_foo; // expected-note 4 {{declared protected here}}
+ static int protected_sfoo; // expected-note 3 {{declared protected here}}
+
+ int test1(A<int> &a) {
+ return a.private_foo; // expected-error {{private member}}
+ }
+
+ int test2(A<int> &a) {
+ return a.private_sfoo; // expected-error {{private member}}
+ }
+
+ int test3(A<int> &a) {
+ return a.protected_foo; // expected-error {{protected member}}
+ }
+
+ int test4(A<int> &a) {
+ return a.protected_sfoo; // expected-error {{protected member}}
+ }
+ };
+
+ template class A<int>;
+ template class A<long>; // expected-note 4 {{in instantiation}}
+
+ template <class T> class B : public A<T> {
+ // TODO: These first two accesses can be detected as ill-formed at
+ // definition time because they're member accesses and A<int> can't
+ // be a subclass of B<T> for any T.
+
+ int test1(A<int> &a) {
+ return a.protected_foo; // expected-error 2 {{protected member}}
+ }
+
+ int test2(A<int> &a) {
+ return a.protected_sfoo; // expected-error {{protected member}}
+ }
+
+ int test3(B<int> &b) {
+ return b.protected_foo; // expected-error {{protected member}}
+ }
+
+ int test4(B<int> &b) {
+ return b.protected_sfoo; // expected-error {{protected member}}
+ }
+ };
+
+ template class B<int>; // expected-note {{in instantiation}}
+ template class B<long>; // expected-note 4 {{in instantiation}}
+}
More information about the cfe-commits
mailing list