26 using namespace clang;
42 if (!PrevMemberDecl) {
52 diag::err_class_redeclared_with_different_access)
53 << MemberDecl << LexicalAS;
54 Diag(PrevMemberDecl->
getLocation(), diag::note_previous_access_declaration)
55 << PrevMemberDecl << PrevMemberDecl->
getAccess();
70 if (isa<EnumDecl>(DC))
71 DC = cast<EnumDecl>(DC)->getDeclContext();
75 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->
getDeclContext());
76 return DeclaringClass;
80 struct EffectiveContext {
81 EffectiveContext() : Inner(nullptr), Dependent(
false) {}
85 Dependent(DC->isDependentContext()) {
106 if (isa<CXXRecordDecl>(DC)) {
110 }
else if (isa<FunctionDecl>(DC)) {
112 Functions.push_back(
Function->getCanonicalDecl());
113 if (
Function->getFriendObjectKind())
114 DC =
Function->getLexicalDeclContext();
125 bool isDependent()
const {
return Dependent; }
129 return llvm::find(Records, R) != Records.end();
160 FoundDecl, BaseObjectType) {
174 bool isInstanceMember()
const {
175 return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
178 bool hasInstanceContext()
const {
179 return HasInstanceContext;
182 class SavedInstanceContext {
184 SavedInstanceContext(SavedInstanceContext &&S)
188 ~SavedInstanceContext() {
190 Target->HasInstanceContext = Has;
194 friend struct AccessTarget;
195 explicit SavedInstanceContext(AccessTarget &Target)
201 SavedInstanceContext saveInstanceContext() {
202 return SavedInstanceContext(*
this);
205 void suppressInstanceContext() {
206 HasInstanceContext =
false;
210 assert(HasInstanceContext);
211 if (CalculatedInstanceContext)
212 return InstanceContext;
214 CalculatedInstanceContext =
true;
216 InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl()
218 return InstanceContext;
222 return DeclaringClass;
230 namingClass = cast<CXXRecordDecl>(namingClass->
getParent());
236 HasInstanceContext = (isMemberAccess() &&
237 !getBaseObjectType().isNull() &&
238 getTargetDecl()->isCXXInstanceMember());
239 CalculatedInstanceContext =
false;
240 InstanceContext =
nullptr;
242 if (isMemberAccess())
245 DeclaringClass = getBaseClass();
246 DeclaringClass = DeclaringClass->getCanonicalDecl();
249 bool HasInstanceContext : 1;
250 mutable bool CalculatedInstanceContext : 1;
266 if (FromDC == ToDC)
return true;
297 for (
const auto &I : Derived->
bases()) {
302 RD = cast<CXXRecordDecl>(RT->getDecl());
320 if (Queue.empty())
break;
322 Derived = Queue.pop_back_val();
331 if (Friend == Context)
335 "can't handle friends with dependent contexts here");
337 if (!Context->isDependentContext())
350 if (Friend == Context)
353 if (!Friend->isDependentType() && !Context->isDependentType())
363 if (Context->getDeclName() != Friend->
getDeclName())
367 Context->getDeclContext(),
376 ->getAs<FunctionProtoType>();
383 if (FriendTy->getNumParams() != ContextTy->getNumParams())
387 FriendTy->getReturnType()))
390 for (
unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I)
392 FriendTy->getParamType(I)))
402 Context->getTemplatedDecl(),
407 const EffectiveContext &EC,
409 if (EC.includesClass(Friend))
412 if (EC.isDependent()) {
423 const EffectiveContext &EC,
426 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
429 if (Friend->isDependentType())
438 const EffectiveContext &EC,
445 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
452 if (isa<ClassTemplateSpecializationDecl>(Record)) {
453 CTD = cast<ClassTemplateSpecializationDecl>(Record)
454 ->getSpecializedTemplate();
467 if (!EC.isDependent())
491 const EffectiveContext &EC,
496 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
510 const EffectiveContext &EC,
517 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
521 FTD = (*I)->getDescribedFunctionTemplate();
540 const EffectiveContext &EC,
548 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
555 if (isa<ClassTemplateDecl>(Friend))
556 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
558 if (isa<FunctionTemplateDecl>(Friend))
559 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
561 if (isa<CXXRecordDecl>(Friend))
564 assert(isa<FunctionDecl>(Friend) &&
"unknown friend decl kind");
569 const EffectiveContext &EC,
574 for (
auto *Friend : Class->friends()) {
596 struct ProtectedFriendContext {
598 const EffectiveContext &EC;
606 ProtectedFriendContext(
Sema &S,
const EffectiveContext &EC,
609 : S(S), EC(EC), NamingClass(NamingClass),
610 CheckDependent(InstanceContext->isDependentContext() ||
611 NamingClass->isDependentContext()),
612 EverDependent(
false) {}
616 bool checkFriendshipAlongPath(
unsigned I) {
617 assert(I < CurPath.size());
618 for (
unsigned E = CurPath.size(); I != E; ++I) {
633 bool findFriendship(
const CXXRecordDecl *Cur,
unsigned PrivateDepth) {
637 if (Cur == NamingClass)
638 return checkFriendshipAlongPath(PrivateDepth);
641 EverDependent =
true;
644 for (
const auto &I : Cur->
bases()) {
647 unsigned BasePrivateDepth = PrivateDepth;
649 BasePrivateDepth = CurPath.size() - 1;
655 RD = cast<CXXRecordDecl>(RT->getDecl());
661 EverDependent =
true;
666 CurPath.push_back(RD);
676 assert(CurPath.empty());
677 CurPath.push_back(Cur);
678 return findFriendship(Cur, 0);
712 assert(InstanceContext ==
nullptr ||
719 if (!InstanceContext)
return GetFriendKind(S, EC, NamingClass);
721 ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
722 if (PRC.findFriendship(InstanceContext))
return AR_accessible;
728 const EffectiveContext &EC,
731 const AccessTarget &Target) {
733 "declaration should be canonicalized before being passed here");
740 for (EffectiveContext::record_iterator
741 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
748 if (ECRecord == NamingClass)
780 if (!
Target.hasInstanceContext()) {
791 if (S.
getLangOpts().MSVCCompat && !EC.Functions.empty())
792 if (
CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
817 assert(
Target.isInstanceMember());
820 if (!InstanceContext) {
846 if (
Target.hasInstanceContext()) {
847 InstanceContext =
Target.resolveInstanceContext(S);
856 llvm_unreachable(
"impossible friendship kind");
866 llvm_unreachable(
"impossible friendship kind");
926 const EffectiveContext &EC,
927 AccessTarget &Target,
937 assert(isDerived &&
"derived class not actually derived from base");
942 assert(FinalAccess !=
AS_none &&
"forbidden access after declaring class");
944 bool AnyDependent =
false;
949 AccessTarget::SavedInstanceContext _ =
Target.saveInstanceContext();
953 CXXBasePath::iterator I = PI->end(), E = PI->begin();
970 PathAccess =
std::max(PathAccess, BaseAccess);
979 Target.suppressInstanceContext();
989 if (BestPath ==
nullptr || PathAccess < BestPath->Access) {
991 BestPath->
Access = PathAccess;
1002 "fell out of loop with public path");
1018 AccessTarget &Target) {
1020 if (!
Target.isInstanceMember())
1023 assert(
Target.isMemberAccess());
1027 for (EffectiveContext::record_iterator
1028 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
1048 if (!
Target.hasInstanceContext()) {
1050 if (NamingClass == ECRecord)
continue;
1054 S.
Diag(D->
getLocation(), diag::note_access_protected_restricted_noobject)
1060 assert(InstanceContext &&
"diagnosing dependent access");
1072 if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) ||
1073 (isa<FunctionTemplateDecl>(D) &&
1074 isa<CXXConstructorDecl>(
1075 cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
1077 diag::note_access_protected_restricted_ctordtor)
1083 diag::note_access_protected_restricted_object)
1093 const EffectiveContext &EC,
1094 AccessTarget &entity) {
1095 assert(entity.isMemberAccess());
1105 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
1111 else if (
TagDecl *TD = dyn_cast<TagDecl>(D)) {
1112 if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
1116 if (!PrevDecl)
break;
1121 Decl *ImmediateChild;
1126 while (DC->
getParent() != DeclaringClass)
1128 ImmediateChild = cast<Decl>(DC);
1133 bool isImplicit =
true;
1134 for (
const auto *I : DeclaringClass->
decls()) {
1135 if (I == ImmediateChild)
break;
1136 if (isa<AccessSpecDecl>(I)) {
1150 const EffectiveContext &EC,
1151 AccessTarget &entity) {
1153 AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();
1162 if (entity.isMemberAccess()) {
1165 const CXXRecordDecl *declaringClass = entity.getDeclaringClass();
1167 switch (
HasAccess(S, EC, declaringClass, accessSoFar, entity)) {
1172 entity.suppressInstanceContext();
1177 declaringClass == entity.getEffectiveNamingClass())
1182 llvm_unreachable(
"cannot diagnose dependent access");
1190 CXXBasePath::iterator i = path.end(), e = path.begin();
1191 CXXBasePath::iterator constrainingBase = i;
1205 if (baseAccess > accessSoFar) {
1206 constrainingBase = i;
1207 accessSoFar = baseAccess;
1210 switch (
HasAccess(S, EC, derivingClass, accessSoFar, entity)) {
1214 entity.suppressInstanceContext();
1215 constrainingBase =
nullptr;
1218 llvm_unreachable(
"cannot diagnose dependent access");
1225 assert(constrainingBase == i);
1232 if (constrainingBase == path.end())
1238 unsigned diagnostic;
1239 if (entity.isMemberAccess() ||
1240 constrainingBase + 1 != path.end()) {
1241 diagnostic = diag::note_access_constrained_by_path;
1243 diagnostic = diag::note_access_natural;
1253 if (entity.isMemberAccess())
1254 S.
Diag(entity.getTargetDecl()->getLocation(),
1255 diag::note_member_declared_at);
1259 const EffectiveContext &EC,
1260 AccessTarget &Entity) {
1262 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1263 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() :
nullptr);
1265 S.
Diag(Loc, Entity.getDiag())
1295 AccessTarget &Entity) {
1297 dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
1298 const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
1299 if (Entity.getTargetDecl()->getAccess() ==
AS_private &&
1302 S.
Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
1303 << Shadow->getUsingDecl()->getQualifiedNameAsString()
1314 const EffectiveContext &EC,
1315 AccessTarget &Entity) {
1317 const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();
1320 assert(UnprivilegedAccess !=
AS_public &&
"public access not weeded out");
1326 if (UnprivilegedAccess !=
AS_none) {
1327 switch (
HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
1343 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
1349 if (Entity.isMemberAccess()) {
1353 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1355 FinalAccess =
Target->getAccess();
1356 switch (
HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
1364 Entity.suppressInstanceContext();
1370 if (DeclaringClass == NamingClass)
1376 assert(Entity.getDeclaringClass() != NamingClass);
1384 assert(Path->
Access <= UnprivilegedAccess &&
1385 "access along best path worse than direct?");
1392 const EffectiveContext &EC,
1394 const AccessTarget &Entity) {
1395 assert(EC.isDependent() &&
"delaying non-dependent access");
1400 Entity.isMemberAccess(),
1402 Entity.getTargetDecl(),
1403 Entity.getNamingClass(),
1404 Entity.getBaseObjectType(),
1410 const EffectiveContext &EC,
1412 AccessTarget &Entity) {
1413 assert(Entity.getAccess() !=
AS_public &&
"called for public access!");
1424 if (!Entity.isQuiet())
1433 llvm_unreachable(
"invalid access result");
1437 AccessTarget &Entity) {
1464 llvm_unreachable(
"invalid access result");
1476 }
else if (
FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
1478 }
else if (
TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
1479 if (isa<DeclContext>(TD->getTemplatedDecl()))
1480 DC = cast<DeclContext>(TD->getTemplatedDecl());
1483 EffectiveContext EC(DC);
1498 if (!NamingD)
return;
1501 if (!TargetD)
return;
1505 NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1507 if (!BaseObjectType.
isNull()) {
1508 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1510 if (BaseObjectType.
isNull())
return;
1513 AccessTarget Entity(Context,
1514 AccessTarget::Member,
1521 AccessTarget Entity(Context,
1523 cast<CXXRecordDecl>(TargetD),
1524 cast<CXXRecordDecl>(NamingD),
1533 if (!getLangOpts().AccessControl ||
1538 AccessTarget Entity(Context, AccessTarget::Member, E->
getNamingClass(),
1549 if (!getLangOpts().AccessControl ||
1557 AccessTarget Entity(Context, AccessTarget::Member, E->
getNamingClass(),
1575 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1579 Entity.setDiag(
Diag);
1584 case AR_dependent: llvm_unreachable(
"dependent for =delete computation");
1585 case AR_delayed: llvm_unreachable(
"cannot delay =delete computation");
1587 llvm_unreachable(
"bad access result");
1594 if (!getLangOpts().AccessControl)
1605 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1608 Entity.setDiag(PDiag);
1618 bool IsCopyBindingRefToTemp) {
1625 PD = PDiag(IsCopyBindingRefToTemp
1626 ? diag::ext_rvalue_to_reference_access_ctor
1627 : diag::err_access_ctor);
1632 PD = PDiag(diag::err_access_base_ctor);
1639 PD = PDiag(diag::err_access_field_ctor);
1640 PD << Field->getType() << getSpecialMember(Constructor);
1646 PD = PDiag(diag::err_access_lambda_capture);
1647 PD << VarName << Entity.
getType() << getSpecialMember(Constructor);
1653 return CheckConstructorAccess(UseLoc, Constructor, Found, Entity, PD);
1662 if (!getLangOpts().AccessControl ||
1679 ObjectClass = cast<CXXConstructorDecl>(CurContext)->
getParent();
1680 }
else if (
auto *Shadow =
1681 dyn_cast<ConstructorUsingShadowDecl>(Found.
getDecl())) {
1686 ObjectClass = NamingClass;
1689 AccessTarget AccessEntity(
1690 Context, AccessTarget::Member, NamingClass,
1693 AccessEntity.setDiag(PD);
1704 if (!getLangOpts().AccessControl ||
1709 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1712 Entity.setDiag(diag::err_access)
1722 if (!getLangOpts().AccessControl ||
1727 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1738 if (!getLangOpts().AccessControl ||
1742 AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field,
1744 Entity.setDiag(diag::err_decomp_decl_inaccessible_field);
1755 if (!getLangOpts().AccessControl ||
1762 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1764 Entity.setDiag(diag::err_access)
1784 AccessTarget entity(Context, AccessTarget::Member,
1788 entity.setDiag(diag::err_access_friend_function)
1794 EffectiveContext EC(CurContext);
1800 llvm_unreachable(
"invalid access result");
1805 if (!getLangOpts().AccessControl ||
1813 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1815 Entity.setDiag(diag::err_access)
1833 bool ForceUnprivileged) {
1834 if (!ForceCheck && !getLangOpts().AccessControl)
1844 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1847 Entity.setDiag(DiagID) << Derived <<
Base;
1849 if (ForceUnprivileged) {
1851 AccessLoc, Entity)) {
1856 llvm_unreachable(
"unexpected result from CheckEffectiveAccess");
1863 assert(getLangOpts().AccessControl
1864 &&
"performing access check without access control");
1865 assert(R.
getNamingClass() &&
"performing access check without naming class");
1872 Entity.setDiag(diag::err_access);
1898 if (
Target->isCXXClassMember() && NamingClass) {
1907 EffectiveContext EC(CurContext);
1921 ClassOfMethodDecl = MD->getClassInterface();
1924 = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) {
1926 = dyn_cast<ObjCImplementationDecl>(Impl))
1927 ClassOfMethodDecl = IMPD->getClassInterface();
1929 = dyn_cast<ObjCCategoryImplDecl>(Impl))
1930 ClassOfMethodDecl = CatImplClass->getClassInterface();
1935 if (!ClassOfMethodDecl)
1946 return Ivar->getContainingInterface()->
isSuperClassOf(ClassOfMethodDecl);