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);
|
bool ForceUnprivileged = false);
|
||||||
void CheckLookupAccess(const LookupResult &R);
|
void CheckLookupAccess(const LookupResult &R);
|
||||||
bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
|
bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
|
||||||
|
bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
|
||||||
|
AccessSpecifier access,
|
||||||
|
QualType objectType);
|
||||||
|
|
||||||
void HandleDependentAccessCheck(const DependentDiagnostic &DD,
|
void HandleDependentAccessCheck(const DependentDiagnostic &DD,
|
||||||
const MultiLevelTemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
|
@ -1507,6 +1507,29 @@ Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
|
||||||
return CheckAccess(*this, E->getMemberLoc(), Entity);
|
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,
|
Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
|
||||||
CXXDestructorDecl *Dtor,
|
CXXDestructorDecl *Dtor,
|
||||||
const PartialDiagnostic &PDiag,
|
const PartialDiagnostic &PDiag,
|
||||||
|
|
|
@ -4397,9 +4397,31 @@ struct SpecialMemberDeletionInfo {
|
||||||
bool shouldDeleteForSubobjectCall(Subobject Subobj,
|
bool shouldDeleteForSubobjectCall(Subobject Subobj,
|
||||||
Sema::SpecialMemberOverloadResult *SMOR,
|
Sema::SpecialMemberOverloadResult *SMOR,
|
||||||
bool IsDtorCallInCtor);
|
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
|
/// Check whether we should delete a special member due to the implicit
|
||||||
/// definition containing a call to a special member of a subobject.
|
/// definition containing a call to a special member of a subobject.
|
||||||
bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
|
bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
|
||||||
|
@ -4414,8 +4436,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
|
||||||
DiagKind = !Decl ? 0 : 1;
|
DiagKind = !Decl ? 0 : 1;
|
||||||
else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
|
else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
|
||||||
DiagKind = 2;
|
DiagKind = 2;
|
||||||
else if (S.CheckDirectMemberAccess(Loc, Decl, S.PDiag())
|
else if (!isAccessible(Subobj, Decl))
|
||||||
!= Sema::AR_accessible)
|
|
||||||
DiagKind = 3;
|
DiagKind = 3;
|
||||||
else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
|
else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
|
||||||
!Decl->isTrivial()) {
|
!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