aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaAccess.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-05-04 05:11:27 +0000
committerJohn McCall <rjmccall@apple.com>2010-05-04 05:11:27 +0000
commit01ebd9d1883e82c4188325900a4eb9c1e16353bb (patch)
treebe62d9b946d1950c07ae9e62f2798d3e098449b6 /lib/Sema/SemaAccess.cpp
parent3d6c1782c4fc2ed3e6a924c15042edb1f56fee36 (diff)
An access is permitted if the current template instantiates to the appropriate
class. Add some conservative support for the idea. Fixes PR 7024. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102999 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaAccess.cpp')
-rw-r--r--lib/Sema/SemaAccess.cpp32
1 files changed, 29 insertions, 3 deletions
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 30c53ed75a..444ee79858 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -222,6 +222,22 @@ private:
}
+/// 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 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
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 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
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 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
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 @@ static AccessResult HasAccess(Sema &S,
if (ECRecord == NamingClass)
return AR_accessible;
+ if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
+ OnFailure = AR_dependent;
+
// [B3] and [M3]
} else {
assert(Access == AS_protected);