forked from OSchip/llvm-project
Fix the access check performed as part of the determination of whether
to define a special member function as deleted so that it properly establishes an object context for the accesses to the base subobject members. llvm-svn: 154343
This commit is contained in:
parent
883f2bb1f9
commit
d42742143c
|
@ -4129,6 +4129,9 @@ public:
|
|||
bool ForceUnprivileged = false);
|
||||
void CheckLookupAccess(const LookupResult &R);
|
||||
bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
|
||||
bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
|
||||
AccessSpecifier access,
|
||||
QualType objectType);
|
||||
|
||||
void HandleDependentAccessCheck(const DependentDiagnostic &DD,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||
|
|
|
@ -1507,6 +1507,29 @@ Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
|
|||
return CheckAccess(*this, E->getMemberLoc(), Entity);
|
||||
}
|
||||
|
||||
/// Is the given special member function accessible for the purposes of
|
||||
/// deciding whether to define a special member function as deleted?
|
||||
bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
|
||||
AccessSpecifier access,
|
||||
QualType objectType) {
|
||||
// Fast path.
|
||||
if (access == AS_public || !getLangOpts().AccessControl) return true;
|
||||
|
||||
AccessTarget entity(Context, AccessTarget::Member, decl->getParent(),
|
||||
DeclAccessPair::make(decl, access), objectType);
|
||||
|
||||
// Suppress diagnostics.
|
||||
entity.setDiag(PDiag());
|
||||
|
||||
switch (CheckAccess(*this, SourceLocation(), entity)) {
|
||||
case AR_accessible: return true;
|
||||
case AR_inaccessible: return false;
|
||||
case AR_dependent: llvm_unreachable("dependent for =delete computation");
|
||||
case AR_delayed: llvm_unreachable("cannot delay =delete computation");
|
||||
}
|
||||
llvm_unreachable("bad access result");
|
||||
}
|
||||
|
||||
Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
|
||||
CXXDestructorDecl *Dtor,
|
||||
const PartialDiagnostic &PDiag,
|
||||
|
|
|
@ -4397,9 +4397,31 @@ struct SpecialMemberDeletionInfo {
|
|||
bool shouldDeleteForSubobjectCall(Subobject Subobj,
|
||||
Sema::SpecialMemberOverloadResult *SMOR,
|
||||
bool IsDtorCallInCtor);
|
||||
|
||||
bool isAccessible(Subobject Subobj, CXXMethodDecl *D);
|
||||
};
|
||||
}
|
||||
|
||||
/// Is the given special member inaccessible when used on the given
|
||||
/// sub-object.
|
||||
bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj,
|
||||
CXXMethodDecl *target) {
|
||||
/// If we're operating on a base class, the object type is the
|
||||
/// type of this special member.
|
||||
QualType objectTy;
|
||||
AccessSpecifier access = target->getAccess();;
|
||||
if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) {
|
||||
objectTy = S.Context.getTypeDeclType(MD->getParent());
|
||||
access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access);
|
||||
|
||||
// If we're operating on a field, the object type is the type of the field.
|
||||
} else {
|
||||
objectTy = S.Context.getTypeDeclType(target->getParent());
|
||||
}
|
||||
|
||||
return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy);
|
||||
}
|
||||
|
||||
/// Check whether we should delete a special member due to the implicit
|
||||
/// definition containing a call to a special member of a subobject.
|
||||
bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
|
||||
|
@ -4414,8 +4436,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
|
|||
DiagKind = !Decl ? 0 : 1;
|
||||
else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
|
||||
DiagKind = 2;
|
||||
else if (S.CheckDirectMemberAccess(Loc, Decl, S.PDiag())
|
||||
!= Sema::AR_accessible)
|
||||
else if (!isAccessible(Subobj, Decl))
|
||||
DiagKind = 3;
|
||||
else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
|
||||
!Decl->isTrivial()) {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
// PR12497
|
||||
namespace test0 {
|
||||
class A {
|
||||
protected:
|
||||
A() {}
|
||||
A(const A &) {}
|
||||
~A() {}
|
||||
A &operator=(const A &a) { return *this; }
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
void test() {
|
||||
B b1;
|
||||
B b2 = b1;
|
||||
b1 = b2;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue