MemberNonce _,
CXXRecordDecl *NamingClass,
DeclAccessPair FoundDecl,
- QualType BaseObjectType)
- : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
+ QualType BaseObjectType,
+ bool IsUsingDecl = false)
+ : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType),
+ IsUsingDeclaration(IsUsingDecl) {
initialize();
}
DeclaringClass = DeclaringClass->getCanonicalDecl();
}
+ bool IsUsingDeclaration : 1;
bool HasInstanceContext : 1;
mutable bool CalculatedInstanceContext : 1;
mutable const CXXRecordDecl *InstanceContext;
DiagnoseAccessPath(S, EC, Entity);
}
+/// MSVC has a bug where if during an using declaration name lookup,
+/// the declaration found is unaccessible (private) and that declaration
+/// was bring into scope via another using declaration whose target
+/// declaration is accessible (public) then no error is generated.
+/// Example:
+/// class A {
+/// public:
+/// int f();
+/// };
+/// class B : public A {
+/// private:
+/// using A::f;
+/// };
+/// class C : public B {
+/// private:
+/// using B::f;
+/// };
+///
+/// Here, B::f is private so this should fail in Standard C++, but
+/// because B::f refers to A::f which is public MSVC accepts it.
+static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
+ SourceLocation AccessLoc,
+ AccessTarget &Entity) {
+ if (UsingShadowDecl *Shadow =
+ dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
+ const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
+ if (Entity.getTargetDecl()->getAccess() == AS_private &&
+ (OrigDecl->getAccess() == AS_public ||
+ OrigDecl->getAccess() == AS_protected)) {
+ S.Diag(AccessLoc, diag::war_ms_using_declaration_inaccessible)
+ << Shadow->getUsingDecl()->getQualifiedNameAsString()
+ << OrigDecl->getQualifiedNameAsString();
+ return true;
+ }
+ }
+ return false;
+}
+
/// Determines whether the accessed entity is accessible. Public members
/// have been weeded out by this point.
static AccessResult IsAccessible(Sema &S,
AccessTarget &Entity) {
assert(Entity.getAccess() != AS_public && "called for public access!");
+ if (S.getLangOptions().Microsoft &&
+ IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
+ return AR_accessible;
+
switch (IsAccessible(S, EC, Entity)) {
case AR_dependent:
DelayDependentAccess(S, EC, Loc, Entity);
if (I.getAccess() != AS_public) {
AccessTarget Entity(Context, AccessedEntity::Member,
R.getNamingClass(), I.getPair(),
- R.getBaseObjectType());
+ R.getBaseObjectType(), R.isUsingDeclaration());
Entity.setDiag(diag::err_access);
-
CheckAccess(*this, R.getNameLoc(), Entity);
}
}