Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 12d8d80

Browse files
committed
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154343 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent ae7e939 commit 12d8d80

File tree

4 files changed

+69
-2
lines changed

4 files changed

+69
-2
lines changed

Diff for: include/clang/Sema/Sema.h

+3
Original file line numberDiff line numberDiff line change
@@ -4129,6 +4129,9 @@ class Sema {
41294129
bool ForceUnprivileged = false);
41304130
void CheckLookupAccess(const LookupResult &R);
41314131
bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
4132+
bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
4133+
AccessSpecifier access,
4134+
QualType objectType);
41324135

41334136
void HandleDependentAccessCheck(const DependentDiagnostic &DD,
41344137
const MultiLevelTemplateArgumentList &TemplateArgs);

Diff for: lib/Sema/SemaAccess.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,29 @@ Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
15071507
return CheckAccess(*this, E->getMemberLoc(), Entity);
15081508
}
15091509

1510+
/// Is the given special member function accessible for the purposes of
1511+
/// deciding whether to define a special member function as deleted?
1512+
bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
1513+
AccessSpecifier access,
1514+
QualType objectType) {
1515+
// Fast path.
1516+
if (access == AS_public || !getLangOpts().AccessControl) return true;
1517+
1518+
AccessTarget entity(Context, AccessTarget::Member, decl->getParent(),
1519+
DeclAccessPair::make(decl, access), objectType);
1520+
1521+
// Suppress diagnostics.
1522+
entity.setDiag(PDiag());
1523+
1524+
switch (CheckAccess(*this, SourceLocation(), entity)) {
1525+
case AR_accessible: return true;
1526+
case AR_inaccessible: return false;
1527+
case AR_dependent: llvm_unreachable("dependent for =delete computation");
1528+
case AR_delayed: llvm_unreachable("cannot delay =delete computation");
1529+
}
1530+
llvm_unreachable("bad access result");
1531+
}
1532+
15101533
Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
15111534
CXXDestructorDecl *Dtor,
15121535
const PartialDiagnostic &PDiag,

Diff for: lib/Sema/SemaDeclCXX.cpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -4397,9 +4397,31 @@ struct SpecialMemberDeletionInfo {
43974397
bool shouldDeleteForSubobjectCall(Subobject Subobj,
43984398
Sema::SpecialMemberOverloadResult *SMOR,
43994399
bool IsDtorCallInCtor);
4400+
4401+
bool isAccessible(Subobject Subobj, CXXMethodDecl *D);
44004402
};
44014403
}
44024404

4405+
/// Is the given special member inaccessible when used on the given
4406+
/// sub-object.
4407+
bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj,
4408+
CXXMethodDecl *target) {
4409+
/// If we're operating on a base class, the object type is the
4410+
/// type of this special member.
4411+
QualType objectTy;
4412+
AccessSpecifier access = target->getAccess();;
4413+
if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) {
4414+
objectTy = S.Context.getTypeDeclType(MD->getParent());
4415+
access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access);
4416+
4417+
// If we're operating on a field, the object type is the type of the field.
4418+
} else {
4419+
objectTy = S.Context.getTypeDeclType(target->getParent());
4420+
}
4421+
4422+
return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy);
4423+
}
4424+
44034425
/// Check whether we should delete a special member due to the implicit
44044426
/// definition containing a call to a special member of a subobject.
44054427
bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
@@ -4414,8 +4436,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
44144436
DiagKind = !Decl ? 0 : 1;
44154437
else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
44164438
DiagKind = 2;
4417-
else if (S.CheckDirectMemberAccess(Loc, Decl, S.PDiag())
4418-
!= Sema::AR_accessible)
4439+
else if (!isAccessible(Subobj, Decl))
44194440
DiagKind = 3;
44204441
else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
44214442
!Decl->isTrivial()) {

Diff for: test/CXX/class.access/class.protected/p1-cxx11.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
3+
// PR12497
4+
namespace test0 {
5+
class A {
6+
protected:
7+
A() {}
8+
A(const A &) {}
9+
~A() {}
10+
A &operator=(const A &a) { return *this; }
11+
};
12+
13+
class B : public A {};
14+
15+
void test() {
16+
B b1;
17+
B b2 = b1;
18+
b1 = b2;
19+
}
20+
}

0 commit comments

Comments
 (0)