1 //===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file provides Sema routines for C++ access control semantics. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Basic/Specifiers.h" 15 #include "clang/Sema/SemaInternal.h" 16 #include "clang/AST/ASTContext.h" 17 #include "clang/AST/CXXInheritance.h" 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/AST/DeclFriend.h" 20 #include "clang/AST/DeclObjC.h" 21 #include "clang/AST/DependentDiagnostic.h" 22 #include "clang/AST/ExprCXX.h" 23 #include "clang/Sema/DelayedDiagnostic.h" 24 #include "clang/Sema/Initialization.h" 25 #include "clang/Sema/Lookup.h" 26 27 using namespace clang; 28 using namespace sema; 29 30 /// A copy of Sema's enum without AR_delayed. 31 enum AccessResult { 32 AR_accessible, 33 AR_inaccessible, 34 AR_dependent 35 }; 36 37 /// SetMemberAccessSpecifier - Set the access specifier of a member. 38 /// Returns true on error (when the previous member decl access specifier 39 /// is different from the new member decl access specifier). 40 bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 41 NamedDecl *PrevMemberDecl, 42 AccessSpecifier LexicalAS) { 43 if (!PrevMemberDecl) { 44 // Use the lexical access specifier. 45 MemberDecl->setAccess(LexicalAS); 46 return false; 47 } 48 49 // C++ [class.access.spec]p3: When a member is redeclared its access 50 // specifier must be same as its initial declaration. 51 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 52 Diag(MemberDecl->getLocation(), 53 diag::err_class_redeclared_with_different_access) 54 << MemberDecl << LexicalAS; 55 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 56 << PrevMemberDecl << PrevMemberDecl->getAccess(); 57 58 MemberDecl->setAccess(LexicalAS); 59 return true; 60 } 61 62 MemberDecl->setAccess(PrevMemberDecl->getAccess()); 63 return false; 64 } 65 66 static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 67 DeclContext *DC = D->getDeclContext(); 68 69 // This can only happen at top: enum decls only "publish" their 70 // immediate members. 71 if (isa<EnumDecl>(DC)) 72 DC = cast<EnumDecl>(DC)->getDeclContext(); 73 74 CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 75 while (DeclaringClass->isAnonymousStructOrUnion()) 76 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 77 return DeclaringClass; 78 } 79 80 namespace { 81 struct EffectiveContext { 82 EffectiveContext() : Inner(nullptr), Dependent(false) {} 83 84 explicit EffectiveContext(DeclContext *DC) 85 : Inner(DC), 86 Dependent(DC->isDependentContext()) { 87 88 // C++11 [class.access.nest]p1: 89 // A nested class is a member and as such has the same access 90 // rights as any other member. 91 // C++11 [class.access]p2: 92 // A member of a class can also access all the names to which 93 // the class has access. A local class of a member function 94 // may access the same names that the member function itself 95 // may access. 96 // This almost implies that the privileges of nesting are transitive. 97 // Technically it says nothing about the local classes of non-member 98 // functions (which can gain privileges through friendship), but we 99 // take that as an oversight. 100 while (true) { 101 // We want to add canonical declarations to the EC lists for 102 // simplicity of checking, but we need to walk up through the 103 // actual current DC chain. Otherwise, something like a local 104 // extern or friend which happens to be the canonical 105 // declaration will really mess us up. 106 107 if (isa<CXXRecordDecl>(DC)) { 108 CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); 109 Records.push_back(Record->getCanonicalDecl()); 110 DC = Record->getDeclContext(); 111 } else if (isa<FunctionDecl>(DC)) { 112 FunctionDecl *Function = cast<FunctionDecl>(DC); 113 Functions.push_back(Function->getCanonicalDecl()); 114 if (Function->getFriendObjectKind()) 115 DC = Function->getLexicalDeclContext(); 116 else 117 DC = Function->getDeclContext(); 118 } else if (DC->isFileContext()) { 119 break; 120 } else { 121 DC = DC->getParent(); 122 } 123 } 124 } 125 126 bool isDependent() const { return Dependent; } 127 128 bool includesClass(const CXXRecordDecl *R) const { 129 R = R->getCanonicalDecl(); 130 return std::find(Records.begin(), Records.end(), R) 131 != Records.end(); 132 } 133 134 /// Retrieves the innermost "useful" context. Can be null if we're 135 /// doing access-control without privileges. 136 DeclContext *getInnerContext() const { 137 return Inner; 138 } 139 140 typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 141 142 DeclContext *Inner; 143 SmallVector<FunctionDecl*, 4> Functions; 144 SmallVector<CXXRecordDecl*, 4> Records; 145 bool Dependent; 146 }; 147 148 /// Like sema::AccessedEntity, but kindly lets us scribble all over 149 /// it. 150 struct AccessTarget : public AccessedEntity { 151 AccessTarget(const AccessedEntity &Entity) 152 : AccessedEntity(Entity) { 153 initialize(); 154 } 155 156 AccessTarget(ASTContext &Context, 157 MemberNonce _, 158 CXXRecordDecl *NamingClass, 159 DeclAccessPair FoundDecl, 160 QualType BaseObjectType) 161 : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass, 162 FoundDecl, BaseObjectType) { 163 initialize(); 164 } 165 166 AccessTarget(ASTContext &Context, 167 BaseNonce _, 168 CXXRecordDecl *BaseClass, 169 CXXRecordDecl *DerivedClass, 170 AccessSpecifier Access) 171 : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass, 172 Access) { 173 initialize(); 174 } 175 176 bool isInstanceMember() const { 177 return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember()); 178 } 179 180 bool hasInstanceContext() const { 181 return HasInstanceContext; 182 } 183 184 class SavedInstanceContext { 185 public: 186 SavedInstanceContext(SavedInstanceContext &&S) 187 : Target(S.Target), Has(S.Has) { 188 S.Target = nullptr; 189 } 190 ~SavedInstanceContext() { 191 if (Target) 192 Target->HasInstanceContext = Has; 193 } 194 195 private: 196 friend struct AccessTarget; 197 explicit SavedInstanceContext(AccessTarget &Target) 198 : Target(&Target), Has(Target.HasInstanceContext) {} 199 AccessTarget *Target; 200 bool Has; 201 }; 202 203 SavedInstanceContext saveInstanceContext() { 204 return SavedInstanceContext(*this); 205 } 206 207 void suppressInstanceContext() { 208 HasInstanceContext = false; 209 } 210 211 const CXXRecordDecl *resolveInstanceContext(Sema &S) const { 212 assert(HasInstanceContext); 213 if (CalculatedInstanceContext) 214 return InstanceContext; 215 216 CalculatedInstanceContext = true; 217 DeclContext *IC = S.computeDeclContext(getBaseObjectType()); 218 InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() 219 : nullptr); 220 return InstanceContext; 221 } 222 223 const CXXRecordDecl *getDeclaringClass() const { 224 return DeclaringClass; 225 } 226 227 /// The "effective" naming class is the canonical non-anonymous 228 /// class containing the actual naming class. 229 const CXXRecordDecl *getEffectiveNamingClass() const { 230 const CXXRecordDecl *namingClass = getNamingClass(); 231 while (namingClass->isAnonymousStructOrUnion()) 232 namingClass = cast<CXXRecordDecl>(namingClass->getParent()); 233 return namingClass->getCanonicalDecl(); 234 } 235 236 private: 237 void initialize() { 238 HasInstanceContext = (isMemberAccess() && 239 !getBaseObjectType().isNull() && 240 getTargetDecl()->isCXXInstanceMember()); 241 CalculatedInstanceContext = false; 242 InstanceContext = nullptr; 243 244 if (isMemberAccess()) 245 DeclaringClass = FindDeclaringClass(getTargetDecl()); 246 else 247 DeclaringClass = getBaseClass(); 248 DeclaringClass = DeclaringClass->getCanonicalDecl(); 249 } 250 251 bool HasInstanceContext : 1; 252 mutable bool CalculatedInstanceContext : 1; 253 mutable const CXXRecordDecl *InstanceContext; 254 const CXXRecordDecl *DeclaringClass; 255 }; 256 257 } 258 259 /// Checks whether one class might instantiate to the other. 260 static bool MightInstantiateTo(const CXXRecordDecl *From, 261 const CXXRecordDecl *To) { 262 // Declaration names are always preserved by instantiation. 263 if (From->getDeclName() != To->getDeclName()) 264 return false; 265 266 const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); 267 const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); 268 if (FromDC == ToDC) return true; 269 if (FromDC->isFileContext() || ToDC->isFileContext()) return false; 270 271 // Be conservative. 272 return true; 273 } 274 275 /// Checks whether one class is derived from another, inclusively. 276 /// Properly indicates when it couldn't be determined due to 277 /// dependence. 278 /// 279 /// This should probably be donated to AST or at least Sema. 280 static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, 281 const CXXRecordDecl *Target) { 282 assert(Derived->getCanonicalDecl() == Derived); 283 assert(Target->getCanonicalDecl() == Target); 284 285 if (Derived == Target) return AR_accessible; 286 287 bool CheckDependent = Derived->isDependentContext(); 288 if (CheckDependent && MightInstantiateTo(Derived, Target)) 289 return AR_dependent; 290 291 AccessResult OnFailure = AR_inaccessible; 292 SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack 293 294 while (true) { 295 if (Derived->isDependentContext() && !Derived->hasDefinition() && 296 !Derived->isLambda()) 297 return AR_dependent; 298 299 for (const auto &I : Derived->bases()) { 300 const CXXRecordDecl *RD; 301 302 QualType T = I.getType(); 303 if (const RecordType *RT = T->getAs<RecordType>()) { 304 RD = cast<CXXRecordDecl>(RT->getDecl()); 305 } else if (const InjectedClassNameType *IT 306 = T->getAs<InjectedClassNameType>()) { 307 RD = IT->getDecl(); 308 } else { 309 assert(T->isDependentType() && "non-dependent base wasn't a record?"); 310 OnFailure = AR_dependent; 311 continue; 312 } 313 314 RD = RD->getCanonicalDecl(); 315 if (RD == Target) return AR_accessible; 316 if (CheckDependent && MightInstantiateTo(RD, Target)) 317 OnFailure = AR_dependent; 318 319 Queue.push_back(RD); 320 } 321 322 if (Queue.empty()) break; 323 324 Derived = Queue.pop_back_val(); 325 } 326 327 return OnFailure; 328 } 329 330 331 static bool MightInstantiateTo(Sema &S, DeclContext *Context, 332 DeclContext *Friend) { 333 if (Friend == Context) 334 return true; 335 336 assert(!Friend->isDependentContext() && 337 "can't handle friends with dependent contexts here"); 338 339 if (!Context->isDependentContext()) 340 return false; 341 342 if (Friend->isFileContext()) 343 return false; 344 345 // TODO: this is very conservative 346 return true; 347 } 348 349 // Asks whether the type in 'context' can ever instantiate to the type 350 // in 'friend'. 351 static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 352 if (Friend == Context) 353 return true; 354 355 if (!Friend->isDependentType() && !Context->isDependentType()) 356 return false; 357 358 // TODO: this is very conservative. 359 return true; 360 } 361 362 static bool MightInstantiateTo(Sema &S, 363 FunctionDecl *Context, 364 FunctionDecl *Friend) { 365 if (Context->getDeclName() != Friend->getDeclName()) 366 return false; 367 368 if (!MightInstantiateTo(S, 369 Context->getDeclContext(), 370 Friend->getDeclContext())) 371 return false; 372 373 CanQual<FunctionProtoType> FriendTy 374 = S.Context.getCanonicalType(Friend->getType()) 375 ->getAs<FunctionProtoType>(); 376 CanQual<FunctionProtoType> ContextTy 377 = S.Context.getCanonicalType(Context->getType()) 378 ->getAs<FunctionProtoType>(); 379 380 // There isn't any way that I know of to add qualifiers 381 // during instantiation. 382 if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 383 return false; 384 385 if (FriendTy->getNumParams() != ContextTy->getNumParams()) 386 return false; 387 388 if (!MightInstantiateTo(S, ContextTy->getReturnType(), 389 FriendTy->getReturnType())) 390 return false; 391 392 for (unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I) 393 if (!MightInstantiateTo(S, ContextTy->getParamType(I), 394 FriendTy->getParamType(I))) 395 return false; 396 397 return true; 398 } 399 400 static bool MightInstantiateTo(Sema &S, 401 FunctionTemplateDecl *Context, 402 FunctionTemplateDecl *Friend) { 403 return MightInstantiateTo(S, 404 Context->getTemplatedDecl(), 405 Friend->getTemplatedDecl()); 406 } 407 408 static AccessResult MatchesFriend(Sema &S, 409 const EffectiveContext &EC, 410 const CXXRecordDecl *Friend) { 411 if (EC.includesClass(Friend)) 412 return AR_accessible; 413 414 if (EC.isDependent()) { 415 for (const CXXRecordDecl *Context : EC.Records) { 416 if (MightInstantiateTo(Context, Friend)) 417 return AR_dependent; 418 } 419 } 420 421 return AR_inaccessible; 422 } 423 424 static AccessResult MatchesFriend(Sema &S, 425 const EffectiveContext &EC, 426 CanQualType Friend) { 427 if (const RecordType *RT = Friend->getAs<RecordType>()) 428 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 429 430 // TODO: we can do better than this 431 if (Friend->isDependentType()) 432 return AR_dependent; 433 434 return AR_inaccessible; 435 } 436 437 /// Determines whether the given friend class template matches 438 /// anything in the effective context. 439 static AccessResult MatchesFriend(Sema &S, 440 const EffectiveContext &EC, 441 ClassTemplateDecl *Friend) { 442 AccessResult OnFailure = AR_inaccessible; 443 444 // Check whether the friend is the template of a class in the 445 // context chain. 446 for (SmallVectorImpl<CXXRecordDecl*>::const_iterator 447 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 448 CXXRecordDecl *Record = *I; 449 450 // Figure out whether the current class has a template: 451 ClassTemplateDecl *CTD; 452 453 // A specialization of the template... 454 if (isa<ClassTemplateSpecializationDecl>(Record)) { 455 CTD = cast<ClassTemplateSpecializationDecl>(Record) 456 ->getSpecializedTemplate(); 457 458 // ... or the template pattern itself. 459 } else { 460 CTD = Record->getDescribedClassTemplate(); 461 if (!CTD) continue; 462 } 463 464 // It's a match. 465 if (Friend == CTD->getCanonicalDecl()) 466 return AR_accessible; 467 468 // If the context isn't dependent, it can't be a dependent match. 469 if (!EC.isDependent()) 470 continue; 471 472 // If the template names don't match, it can't be a dependent 473 // match. 474 if (CTD->getDeclName() != Friend->getDeclName()) 475 continue; 476 477 // If the class's context can't instantiate to the friend's 478 // context, it can't be a dependent match. 479 if (!MightInstantiateTo(S, CTD->getDeclContext(), 480 Friend->getDeclContext())) 481 continue; 482 483 // Otherwise, it's a dependent match. 484 OnFailure = AR_dependent; 485 } 486 487 return OnFailure; 488 } 489 490 /// Determines whether the given friend function matches anything in 491 /// the effective context. 492 static AccessResult MatchesFriend(Sema &S, 493 const EffectiveContext &EC, 494 FunctionDecl *Friend) { 495 AccessResult OnFailure = AR_inaccessible; 496 497 for (SmallVectorImpl<FunctionDecl*>::const_iterator 498 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 499 if (Friend == *I) 500 return AR_accessible; 501 502 if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 503 OnFailure = AR_dependent; 504 } 505 506 return OnFailure; 507 } 508 509 /// Determines whether the given friend function template matches 510 /// anything in the effective context. 511 static AccessResult MatchesFriend(Sema &S, 512 const EffectiveContext &EC, 513 FunctionTemplateDecl *Friend) { 514 if (EC.Functions.empty()) return AR_inaccessible; 515 516 AccessResult OnFailure = AR_inaccessible; 517 518 for (SmallVectorImpl<FunctionDecl*>::const_iterator 519 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 520 521 FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 522 if (!FTD) 523 FTD = (*I)->getDescribedFunctionTemplate(); 524 if (!FTD) 525 continue; 526 527 FTD = FTD->getCanonicalDecl(); 528 529 if (Friend == FTD) 530 return AR_accessible; 531 532 if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 533 OnFailure = AR_dependent; 534 } 535 536 return OnFailure; 537 } 538 539 /// Determines whether the given friend declaration matches anything 540 /// in the effective context. 541 static AccessResult MatchesFriend(Sema &S, 542 const EffectiveContext &EC, 543 FriendDecl *FriendD) { 544 // Whitelist accesses if there's an invalid or unsupported friend 545 // declaration. 546 if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) 547 return AR_accessible; 548 549 if (TypeSourceInfo *T = FriendD->getFriendType()) 550 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 551 552 NamedDecl *Friend 553 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 554 555 // FIXME: declarations with dependent or templated scope. 556 557 if (isa<ClassTemplateDecl>(Friend)) 558 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 559 560 if (isa<FunctionTemplateDecl>(Friend)) 561 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 562 563 if (isa<CXXRecordDecl>(Friend)) 564 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 565 566 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 567 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 568 } 569 570 static AccessResult GetFriendKind(Sema &S, 571 const EffectiveContext &EC, 572 const CXXRecordDecl *Class) { 573 AccessResult OnFailure = AR_inaccessible; 574 575 // Okay, check friends. 576 for (auto *Friend : Class->friends()) { 577 switch (MatchesFriend(S, EC, Friend)) { 578 case AR_accessible: 579 return AR_accessible; 580 581 case AR_inaccessible: 582 continue; 583 584 case AR_dependent: 585 OnFailure = AR_dependent; 586 break; 587 } 588 } 589 590 // That's it, give up. 591 return OnFailure; 592 } 593 594 namespace { 595 596 /// A helper class for checking for a friend which will grant access 597 /// to a protected instance member. 598 struct ProtectedFriendContext { 599 Sema &S; 600 const EffectiveContext &EC; 601 const CXXRecordDecl *NamingClass; 602 bool CheckDependent; 603 bool EverDependent; 604 605 /// The path down to the current base class. 606 SmallVector<const CXXRecordDecl*, 20> CurPath; 607 608 ProtectedFriendContext(Sema &S, const EffectiveContext &EC, 609 const CXXRecordDecl *InstanceContext, 610 const CXXRecordDecl *NamingClass) 611 : S(S), EC(EC), NamingClass(NamingClass), 612 CheckDependent(InstanceContext->isDependentContext() || 613 NamingClass->isDependentContext()), 614 EverDependent(false) {} 615 616 /// Check classes in the current path for friendship, starting at 617 /// the given index. 618 bool checkFriendshipAlongPath(unsigned I) { 619 assert(I < CurPath.size()); 620 for (unsigned E = CurPath.size(); I != E; ++I) { 621 switch (GetFriendKind(S, EC, CurPath[I])) { 622 case AR_accessible: return true; 623 case AR_inaccessible: continue; 624 case AR_dependent: EverDependent = true; continue; 625 } 626 } 627 return false; 628 } 629 630 /// Perform a search starting at the given class. 631 /// 632 /// PrivateDepth is the index of the last (least derived) class 633 /// along the current path such that a notional public member of 634 /// the final class in the path would have access in that class. 635 bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { 636 // If we ever reach the naming class, check the current path for 637 // friendship. We can also stop recursing because we obviously 638 // won't find the naming class there again. 639 if (Cur == NamingClass) 640 return checkFriendshipAlongPath(PrivateDepth); 641 642 if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) 643 EverDependent = true; 644 645 // Recurse into the base classes. 646 for (const auto &I : Cur->bases()) { 647 // If this is private inheritance, then a public member of the 648 // base will not have any access in classes derived from Cur. 649 unsigned BasePrivateDepth = PrivateDepth; 650 if (I.getAccessSpecifier() == AS_private) 651 BasePrivateDepth = CurPath.size() - 1; 652 653 const CXXRecordDecl *RD; 654 655 QualType T = I.getType(); 656 if (const RecordType *RT = T->getAs<RecordType>()) { 657 RD = cast<CXXRecordDecl>(RT->getDecl()); 658 } else if (const InjectedClassNameType *IT 659 = T->getAs<InjectedClassNameType>()) { 660 RD = IT->getDecl(); 661 } else { 662 assert(T->isDependentType() && "non-dependent base wasn't a record?"); 663 EverDependent = true; 664 continue; 665 } 666 667 // Recurse. We don't need to clean up if this returns true. 668 CurPath.push_back(RD); 669 if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) 670 return true; 671 CurPath.pop_back(); 672 } 673 674 return false; 675 } 676 677 bool findFriendship(const CXXRecordDecl *Cur) { 678 assert(CurPath.empty()); 679 CurPath.push_back(Cur); 680 return findFriendship(Cur, 0); 681 } 682 }; 683 } 684 685 /// Search for a class P that EC is a friend of, under the constraint 686 /// InstanceContext <= P 687 /// if InstanceContext exists, or else 688 /// NamingClass <= P 689 /// and with the additional restriction that a protected member of 690 /// NamingClass would have some natural access in P, which implicitly 691 /// imposes the constraint that P <= NamingClass. 692 /// 693 /// This isn't quite the condition laid out in the standard. 694 /// Instead of saying that a notional protected member of NamingClass 695 /// would have to have some natural access in P, it says the actual 696 /// target has to have some natural access in P, which opens up the 697 /// possibility that the target (which is not necessarily a member 698 /// of NamingClass) might be more accessible along some path not 699 /// passing through it. That's really a bad idea, though, because it 700 /// introduces two problems: 701 /// - Most importantly, it breaks encapsulation because you can 702 /// access a forbidden base class's members by directly subclassing 703 /// it elsewhere. 704 /// - It also makes access substantially harder to compute because it 705 /// breaks the hill-climbing algorithm: knowing that the target is 706 /// accessible in some base class would no longer let you change 707 /// the question solely to whether the base class is accessible, 708 /// because the original target might have been more accessible 709 /// because of crazy subclassing. 710 /// So we don't implement that. 711 static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, 712 const CXXRecordDecl *InstanceContext, 713 const CXXRecordDecl *NamingClass) { 714 assert(InstanceContext == nullptr || 715 InstanceContext->getCanonicalDecl() == InstanceContext); 716 assert(NamingClass->getCanonicalDecl() == NamingClass); 717 718 // If we don't have an instance context, our constraints give us 719 // that NamingClass <= P <= NamingClass, i.e. P == NamingClass. 720 // This is just the usual friendship check. 721 if (!InstanceContext) return GetFriendKind(S, EC, NamingClass); 722 723 ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); 724 if (PRC.findFriendship(InstanceContext)) return AR_accessible; 725 if (PRC.EverDependent) return AR_dependent; 726 return AR_inaccessible; 727 } 728 729 static AccessResult HasAccess(Sema &S, 730 const EffectiveContext &EC, 731 const CXXRecordDecl *NamingClass, 732 AccessSpecifier Access, 733 const AccessTarget &Target) { 734 assert(NamingClass->getCanonicalDecl() == NamingClass && 735 "declaration should be canonicalized before being passed here"); 736 737 if (Access == AS_public) return AR_accessible; 738 assert(Access == AS_private || Access == AS_protected); 739 740 AccessResult OnFailure = AR_inaccessible; 741 742 for (EffectiveContext::record_iterator 743 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 744 // All the declarations in EC have been canonicalized, so pointer 745 // equality from this point on will work fine. 746 const CXXRecordDecl *ECRecord = *I; 747 748 // [B2] and [M2] 749 if (Access == AS_private) { 750 if (ECRecord == NamingClass) 751 return AR_accessible; 752 753 if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) 754 OnFailure = AR_dependent; 755 756 // [B3] and [M3] 757 } else { 758 assert(Access == AS_protected); 759 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 760 case AR_accessible: break; 761 case AR_inaccessible: continue; 762 case AR_dependent: OnFailure = AR_dependent; continue; 763 } 764 765 // C++ [class.protected]p1: 766 // An additional access check beyond those described earlier in 767 // [class.access] is applied when a non-static data member or 768 // non-static member function is a protected member of its naming 769 // class. As described earlier, access to a protected member is 770 // granted because the reference occurs in a friend or member of 771 // some class C. If the access is to form a pointer to member, 772 // the nested-name-specifier shall name C or a class derived from 773 // C. All other accesses involve a (possibly implicit) object 774 // expression. In this case, the class of the object expression 775 // shall be C or a class derived from C. 776 // 777 // We interpret this as a restriction on [M3]. 778 779 // In this part of the code, 'C' is just our context class ECRecord. 780 781 // These rules are different if we don't have an instance context. 782 if (!Target.hasInstanceContext()) { 783 // If it's not an instance member, these restrictions don't apply. 784 if (!Target.isInstanceMember()) return AR_accessible; 785 786 // If it's an instance member, use the pointer-to-member rule 787 // that the naming class has to be derived from the effective 788 // context. 789 790 // Emulate a MSVC bug where the creation of pointer-to-member 791 // to protected member of base class is allowed but only from 792 // static member functions. 793 if (S.getLangOpts().MSVCCompat && !EC.Functions.empty()) 794 if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front())) 795 if (MD->isStatic()) return AR_accessible; 796 797 // Despite the standard's confident wording, there is a case 798 // where you can have an instance member that's neither in a 799 // pointer-to-member expression nor in a member access: when 800 // it names a field in an unevaluated context that can't be an 801 // implicit member. Pending clarification, we just apply the 802 // same naming-class restriction here. 803 // FIXME: we're probably not correctly adding the 804 // protected-member restriction when we retroactively convert 805 // an expression to being evaluated. 806 807 // We know that ECRecord derives from NamingClass. The 808 // restriction says to check whether NamingClass derives from 809 // ECRecord, but that's not really necessary: two distinct 810 // classes can't be recursively derived from each other. So 811 // along this path, we just need to check whether the classes 812 // are equal. 813 if (NamingClass == ECRecord) return AR_accessible; 814 815 // Otherwise, this context class tells us nothing; on to the next. 816 continue; 817 } 818 819 assert(Target.isInstanceMember()); 820 821 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 822 if (!InstanceContext) { 823 OnFailure = AR_dependent; 824 continue; 825 } 826 827 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 828 case AR_accessible: return AR_accessible; 829 case AR_inaccessible: continue; 830 case AR_dependent: OnFailure = AR_dependent; continue; 831 } 832 } 833 } 834 835 // [M3] and [B3] say that, if the target is protected in N, we grant 836 // access if the access occurs in a friend or member of some class P 837 // that's a subclass of N and where the target has some natural 838 // access in P. The 'member' aspect is easy to handle because P 839 // would necessarily be one of the effective-context records, and we 840 // address that above. The 'friend' aspect is completely ridiculous 841 // to implement because there are no restrictions at all on P 842 // *unless* the [class.protected] restriction applies. If it does, 843 // however, we should ignore whether the naming class is a friend, 844 // and instead rely on whether any potential P is a friend. 845 if (Access == AS_protected && Target.isInstanceMember()) { 846 // Compute the instance context if possible. 847 const CXXRecordDecl *InstanceContext = nullptr; 848 if (Target.hasInstanceContext()) { 849 InstanceContext = Target.resolveInstanceContext(S); 850 if (!InstanceContext) return AR_dependent; 851 } 852 853 switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { 854 case AR_accessible: return AR_accessible; 855 case AR_inaccessible: return OnFailure; 856 case AR_dependent: return AR_dependent; 857 } 858 llvm_unreachable("impossible friendship kind"); 859 } 860 861 switch (GetFriendKind(S, EC, NamingClass)) { 862 case AR_accessible: return AR_accessible; 863 case AR_inaccessible: return OnFailure; 864 case AR_dependent: return AR_dependent; 865 } 866 867 // Silence bogus warnings 868 llvm_unreachable("impossible friendship kind"); 869 } 870 871 /// Finds the best path from the naming class to the declaring class, 872 /// taking friend declarations into account. 873 /// 874 /// C++0x [class.access.base]p5: 875 /// A member m is accessible at the point R when named in class N if 876 /// [M1] m as a member of N is public, or 877 /// [M2] m as a member of N is private, and R occurs in a member or 878 /// friend of class N, or 879 /// [M3] m as a member of N is protected, and R occurs in a member or 880 /// friend of class N, or in a member or friend of a class P 881 /// derived from N, where m as a member of P is public, private, 882 /// or protected, or 883 /// [M4] there exists a base class B of N that is accessible at R, and 884 /// m is accessible at R when named in class B. 885 /// 886 /// C++0x [class.access.base]p4: 887 /// A base class B of N is accessible at R, if 888 /// [B1] an invented public member of B would be a public member of N, or 889 /// [B2] R occurs in a member or friend of class N, and an invented public 890 /// member of B would be a private or protected member of N, or 891 /// [B3] R occurs in a member or friend of a class P derived from N, and an 892 /// invented public member of B would be a private or protected member 893 /// of P, or 894 /// [B4] there exists a class S such that B is a base class of S accessible 895 /// at R and S is a base class of N accessible at R. 896 /// 897 /// Along a single inheritance path we can restate both of these 898 /// iteratively: 899 /// 900 /// First, we note that M1-4 are equivalent to B1-4 if the member is 901 /// treated as a notional base of its declaring class with inheritance 902 /// access equivalent to the member's access. Therefore we need only 903 /// ask whether a class B is accessible from a class N in context R. 904 /// 905 /// Let B_1 .. B_n be the inheritance path in question (i.e. where 906 /// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 907 /// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 908 /// closest accessible base in the path: 909 /// Access(a, b) = (* access on the base specifier from a to b *) 910 /// Merge(a, forbidden) = forbidden 911 /// Merge(a, private) = forbidden 912 /// Merge(a, b) = min(a,b) 913 /// Accessible(c, forbidden) = false 914 /// Accessible(c, private) = (R is c) || IsFriend(c, R) 915 /// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 916 /// Accessible(c, public) = true 917 /// ACAB(n) = public 918 /// ACAB(i) = 919 /// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 920 /// if Accessible(B_i, AccessToBase) then public else AccessToBase 921 /// 922 /// B is an accessible base of N at R iff ACAB(1) = public. 923 /// 924 /// \param FinalAccess the access of the "final step", or AS_public if 925 /// there is no final step. 926 /// \return null if friendship is dependent 927 static CXXBasePath *FindBestPath(Sema &S, 928 const EffectiveContext &EC, 929 AccessTarget &Target, 930 AccessSpecifier FinalAccess, 931 CXXBasePaths &Paths) { 932 // Derive the paths to the desired base. 933 const CXXRecordDecl *Derived = Target.getNamingClass(); 934 const CXXRecordDecl *Base = Target.getDeclaringClass(); 935 936 // FIXME: fail correctly when there are dependent paths. 937 bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), 938 Paths); 939 assert(isDerived && "derived class not actually derived from base"); 940 (void) isDerived; 941 942 CXXBasePath *BestPath = nullptr; 943 944 assert(FinalAccess != AS_none && "forbidden access after declaring class"); 945 946 bool AnyDependent = false; 947 948 // Derive the friend-modified access along each path. 949 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 950 PI != PE; ++PI) { 951 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); 952 953 // Walk through the path backwards. 954 AccessSpecifier PathAccess = FinalAccess; 955 CXXBasePath::iterator I = PI->end(), E = PI->begin(); 956 while (I != E) { 957 --I; 958 959 assert(PathAccess != AS_none); 960 961 // If the declaration is a private member of a base class, there 962 // is no level of friendship in derived classes that can make it 963 // accessible. 964 if (PathAccess == AS_private) { 965 PathAccess = AS_none; 966 break; 967 } 968 969 const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); 970 971 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 972 PathAccess = std::max(PathAccess, BaseAccess); 973 974 switch (HasAccess(S, EC, NC, PathAccess, Target)) { 975 case AR_inaccessible: break; 976 case AR_accessible: 977 PathAccess = AS_public; 978 979 // Future tests are not against members and so do not have 980 // instance context. 981 Target.suppressInstanceContext(); 982 break; 983 case AR_dependent: 984 AnyDependent = true; 985 goto Next; 986 } 987 } 988 989 // Note that we modify the path's Access field to the 990 // friend-modified access. 991 if (BestPath == nullptr || PathAccess < BestPath->Access) { 992 BestPath = &*PI; 993 BestPath->Access = PathAccess; 994 995 // Short-circuit if we found a public path. 996 if (BestPath->Access == AS_public) 997 return BestPath; 998 } 999 1000 Next: ; 1001 } 1002 1003 assert((!BestPath || BestPath->Access != AS_public) && 1004 "fell out of loop with public path"); 1005 1006 // We didn't find a public path, but at least one path was subject 1007 // to dependent friendship, so delay the check. 1008 if (AnyDependent) 1009 return nullptr; 1010 1011 return BestPath; 1012 } 1013 1014 /// Given that an entity has protected natural access, check whether 1015 /// access might be denied because of the protected member access 1016 /// restriction. 1017 /// 1018 /// \return true if a note was emitted 1019 static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, 1020 AccessTarget &Target) { 1021 // Only applies to instance accesses. 1022 if (!Target.isInstanceMember()) 1023 return false; 1024 1025 assert(Target.isMemberAccess()); 1026 1027 const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass(); 1028 1029 for (EffectiveContext::record_iterator 1030 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 1031 const CXXRecordDecl *ECRecord = *I; 1032 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 1033 case AR_accessible: break; 1034 case AR_inaccessible: continue; 1035 case AR_dependent: continue; 1036 } 1037 1038 // The effective context is a subclass of the declaring class. 1039 // Check whether the [class.protected] restriction is limiting 1040 // access. 1041 1042 // To get this exactly right, this might need to be checked more 1043 // holistically; it's not necessarily the case that gaining 1044 // access here would grant us access overall. 1045 1046 NamedDecl *D = Target.getTargetDecl(); 1047 1048 // If we don't have an instance context, [class.protected] says the 1049 // naming class has to equal the context class. 1050 if (!Target.hasInstanceContext()) { 1051 // If it does, the restriction doesn't apply. 1052 if (NamingClass == ECRecord) continue; 1053 1054 // TODO: it would be great to have a fixit here, since this is 1055 // such an obvious error. 1056 S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject) 1057 << S.Context.getTypeDeclType(ECRecord); 1058 return true; 1059 } 1060 1061 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 1062 assert(InstanceContext && "diagnosing dependent access"); 1063 1064 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 1065 case AR_accessible: continue; 1066 case AR_dependent: continue; 1067 case AR_inaccessible: 1068 break; 1069 } 1070 1071 // Okay, the restriction seems to be what's limiting us. 1072 1073 // Use a special diagnostic for constructors and destructors. 1074 if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) || 1075 (isa<FunctionTemplateDecl>(D) && 1076 isa<CXXConstructorDecl>( 1077 cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) { 1078 return S.Diag(D->getLocation(), 1079 diag::note_access_protected_restricted_ctordtor) 1080 << isa<CXXDestructorDecl>(D->getAsFunction()); 1081 } 1082 1083 // Otherwise, use the generic diagnostic. 1084 return S.Diag(D->getLocation(), 1085 diag::note_access_protected_restricted_object) 1086 << S.Context.getTypeDeclType(ECRecord); 1087 } 1088 1089 return false; 1090 } 1091 1092 /// We are unable to access a given declaration due to its direct 1093 /// access control; diagnose that. 1094 static void diagnoseBadDirectAccess(Sema &S, 1095 const EffectiveContext &EC, 1096 AccessTarget &entity) { 1097 assert(entity.isMemberAccess()); 1098 NamedDecl *D = entity.getTargetDecl(); 1099 1100 if (D->getAccess() == AS_protected && 1101 TryDiagnoseProtectedAccess(S, EC, entity)) 1102 return; 1103 1104 // Find an original declaration. 1105 while (D->isOutOfLine()) { 1106 NamedDecl *PrevDecl = nullptr; 1107 if (VarDecl *VD = dyn_cast<VarDecl>(D)) 1108 PrevDecl = VD->getPreviousDecl(); 1109 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 1110 PrevDecl = FD->getPreviousDecl(); 1111 else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) 1112 PrevDecl = TND->getPreviousDecl(); 1113 else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 1114 if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) 1115 break; 1116 PrevDecl = TD->getPreviousDecl(); 1117 } 1118 if (!PrevDecl) break; 1119 D = PrevDecl; 1120 } 1121 1122 CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); 1123 Decl *ImmediateChild; 1124 if (D->getDeclContext() == DeclaringClass) 1125 ImmediateChild = D; 1126 else { 1127 DeclContext *DC = D->getDeclContext(); 1128 while (DC->getParent() != DeclaringClass) 1129 DC = DC->getParent(); 1130 ImmediateChild = cast<Decl>(DC); 1131 } 1132 1133 // Check whether there's an AccessSpecDecl preceding this in the 1134 // chain of the DeclContext. 1135 bool isImplicit = true; 1136 for (const auto *I : DeclaringClass->decls()) { 1137 if (I == ImmediateChild) break; 1138 if (isa<AccessSpecDecl>(I)) { 1139 isImplicit = false; 1140 break; 1141 } 1142 } 1143 1144 S.Diag(D->getLocation(), diag::note_access_natural) 1145 << (unsigned) (D->getAccess() == AS_protected) 1146 << isImplicit; 1147 } 1148 1149 /// Diagnose the path which caused the given declaration or base class 1150 /// to become inaccessible. 1151 static void DiagnoseAccessPath(Sema &S, 1152 const EffectiveContext &EC, 1153 AccessTarget &entity) { 1154 // Save the instance context to preserve invariants. 1155 AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext(); 1156 1157 // This basically repeats the main algorithm but keeps some more 1158 // information. 1159 1160 // The natural access so far. 1161 AccessSpecifier accessSoFar = AS_public; 1162 1163 // Check whether we have special rights to the declaring class. 1164 if (entity.isMemberAccess()) { 1165 NamedDecl *D = entity.getTargetDecl(); 1166 accessSoFar = D->getAccess(); 1167 const CXXRecordDecl *declaringClass = entity.getDeclaringClass(); 1168 1169 switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) { 1170 // If the declaration is accessible when named in its declaring 1171 // class, then we must be constrained by the path. 1172 case AR_accessible: 1173 accessSoFar = AS_public; 1174 entity.suppressInstanceContext(); 1175 break; 1176 1177 case AR_inaccessible: 1178 if (accessSoFar == AS_private || 1179 declaringClass == entity.getEffectiveNamingClass()) 1180 return diagnoseBadDirectAccess(S, EC, entity); 1181 break; 1182 1183 case AR_dependent: 1184 llvm_unreachable("cannot diagnose dependent access"); 1185 } 1186 } 1187 1188 CXXBasePaths paths; 1189 CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths); 1190 assert(path.Access != AS_public); 1191 1192 CXXBasePath::iterator i = path.end(), e = path.begin(); 1193 CXXBasePath::iterator constrainingBase = i; 1194 while (i != e) { 1195 --i; 1196 1197 assert(accessSoFar != AS_none && accessSoFar != AS_private); 1198 1199 // Is the entity accessible when named in the deriving class, as 1200 // modified by the base specifier? 1201 const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl(); 1202 const CXXBaseSpecifier *base = i->Base; 1203 1204 // If the access to this base is worse than the access we have to 1205 // the declaration, remember it. 1206 AccessSpecifier baseAccess = base->getAccessSpecifier(); 1207 if (baseAccess > accessSoFar) { 1208 constrainingBase = i; 1209 accessSoFar = baseAccess; 1210 } 1211 1212 switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) { 1213 case AR_inaccessible: break; 1214 case AR_accessible: 1215 accessSoFar = AS_public; 1216 entity.suppressInstanceContext(); 1217 constrainingBase = nullptr; 1218 break; 1219 case AR_dependent: 1220 llvm_unreachable("cannot diagnose dependent access"); 1221 } 1222 1223 // If this was private inheritance, but we don't have access to 1224 // the deriving class, we're done. 1225 if (accessSoFar == AS_private) { 1226 assert(baseAccess == AS_private); 1227 assert(constrainingBase == i); 1228 break; 1229 } 1230 } 1231 1232 // If we don't have a constraining base, the access failure must be 1233 // due to the original declaration. 1234 if (constrainingBase == path.end()) 1235 return diagnoseBadDirectAccess(S, EC, entity); 1236 1237 // We're constrained by inheritance, but we want to say 1238 // "declared private here" if we're diagnosing a hierarchy 1239 // conversion and this is the final step. 1240 unsigned diagnostic; 1241 if (entity.isMemberAccess() || 1242 constrainingBase + 1 != path.end()) { 1243 diagnostic = diag::note_access_constrained_by_path; 1244 } else { 1245 diagnostic = diag::note_access_natural; 1246 } 1247 1248 const CXXBaseSpecifier *base = constrainingBase->Base; 1249 1250 S.Diag(base->getSourceRange().getBegin(), diagnostic) 1251 << base->getSourceRange() 1252 << (base->getAccessSpecifier() == AS_protected) 1253 << (base->getAccessSpecifierAsWritten() == AS_none); 1254 1255 if (entity.isMemberAccess()) 1256 S.Diag(entity.getTargetDecl()->getLocation(), 1257 diag::note_member_declared_at); 1258 } 1259 1260 static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 1261 const EffectiveContext &EC, 1262 AccessTarget &Entity) { 1263 const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 1264 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1265 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr); 1266 1267 S.Diag(Loc, Entity.getDiag()) 1268 << (Entity.getAccess() == AS_protected) 1269 << (D ? D->getDeclName() : DeclarationName()) 1270 << S.Context.getTypeDeclType(NamingClass) 1271 << S.Context.getTypeDeclType(DeclaringClass); 1272 DiagnoseAccessPath(S, EC, Entity); 1273 } 1274 1275 /// MSVC has a bug where if during an using declaration name lookup, 1276 /// the declaration found is unaccessible (private) and that declaration 1277 /// was bring into scope via another using declaration whose target 1278 /// declaration is accessible (public) then no error is generated. 1279 /// Example: 1280 /// class A { 1281 /// public: 1282 /// int f(); 1283 /// }; 1284 /// class B : public A { 1285 /// private: 1286 /// using A::f; 1287 /// }; 1288 /// class C : public B { 1289 /// private: 1290 /// using B::f; 1291 /// }; 1292 /// 1293 /// Here, B::f is private so this should fail in Standard C++, but 1294 /// because B::f refers to A::f which is public MSVC accepts it. 1295 static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 1296 SourceLocation AccessLoc, 1297 AccessTarget &Entity) { 1298 if (UsingShadowDecl *Shadow = 1299 dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) { 1300 const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl(); 1301 if (Entity.getTargetDecl()->getAccess() == AS_private && 1302 (OrigDecl->getAccess() == AS_public || 1303 OrigDecl->getAccess() == AS_protected)) { 1304 S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible) 1305 << Shadow->getUsingDecl()->getQualifiedNameAsString() 1306 << OrigDecl->getQualifiedNameAsString(); 1307 return true; 1308 } 1309 } 1310 return false; 1311 } 1312 1313 /// Determines whether the accessed entity is accessible. Public members 1314 /// have been weeded out by this point. 1315 static AccessResult IsAccessible(Sema &S, 1316 const EffectiveContext &EC, 1317 AccessTarget &Entity) { 1318 // Determine the actual naming class. 1319 const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass(); 1320 1321 AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 1322 assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 1323 1324 // Before we try to recalculate access paths, try to white-list 1325 // accesses which just trade in on the final step, i.e. accesses 1326 // which don't require [M4] or [B4]. These are by far the most 1327 // common forms of privileged access. 1328 if (UnprivilegedAccess != AS_none) { 1329 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { 1330 case AR_dependent: 1331 // This is actually an interesting policy decision. We don't 1332 // *have* to delay immediately here: we can do the full access 1333 // calculation in the hope that friendship on some intermediate 1334 // class will make the declaration accessible non-dependently. 1335 // But that's not cheap, and odds are very good (note: assertion 1336 // made without data) that the friend declaration will determine 1337 // access. 1338 return AR_dependent; 1339 1340 case AR_accessible: return AR_accessible; 1341 case AR_inaccessible: break; 1342 } 1343 } 1344 1345 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); 1346 1347 // We lower member accesses to base accesses by pretending that the 1348 // member is a base class of its declaring class. 1349 AccessSpecifier FinalAccess; 1350 1351 if (Entity.isMemberAccess()) { 1352 // Determine if the declaration is accessible from EC when named 1353 // in its declaring class. 1354 NamedDecl *Target = Entity.getTargetDecl(); 1355 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1356 1357 FinalAccess = Target->getAccess(); 1358 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { 1359 case AR_accessible: 1360 // Target is accessible at EC when named in its declaring class. 1361 // We can now hill-climb and simply check whether the declaring 1362 // class is accessible as a base of the naming class. This is 1363 // equivalent to checking the access of a notional public 1364 // member with no instance context. 1365 FinalAccess = AS_public; 1366 Entity.suppressInstanceContext(); 1367 break; 1368 case AR_inaccessible: break; 1369 case AR_dependent: return AR_dependent; // see above 1370 } 1371 1372 if (DeclaringClass == NamingClass) 1373 return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); 1374 } else { 1375 FinalAccess = AS_public; 1376 } 1377 1378 assert(Entity.getDeclaringClass() != NamingClass); 1379 1380 // Append the declaration's access if applicable. 1381 CXXBasePaths Paths; 1382 CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); 1383 if (!Path) 1384 return AR_dependent; 1385 1386 assert(Path->Access <= UnprivilegedAccess && 1387 "access along best path worse than direct?"); 1388 if (Path->Access == AS_public) 1389 return AR_accessible; 1390 return AR_inaccessible; 1391 } 1392 1393 static void DelayDependentAccess(Sema &S, 1394 const EffectiveContext &EC, 1395 SourceLocation Loc, 1396 const AccessTarget &Entity) { 1397 assert(EC.isDependent() && "delaying non-dependent access"); 1398 DeclContext *DC = EC.getInnerContext(); 1399 assert(DC->isDependentContext() && "delaying non-dependent access"); 1400 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 1401 Loc, 1402 Entity.isMemberAccess(), 1403 Entity.getAccess(), 1404 Entity.getTargetDecl(), 1405 Entity.getNamingClass(), 1406 Entity.getBaseObjectType(), 1407 Entity.getDiag()); 1408 } 1409 1410 /// Checks access to an entity from the given effective context. 1411 static AccessResult CheckEffectiveAccess(Sema &S, 1412 const EffectiveContext &EC, 1413 SourceLocation Loc, 1414 AccessTarget &Entity) { 1415 assert(Entity.getAccess() != AS_public && "called for public access!"); 1416 1417 switch (IsAccessible(S, EC, Entity)) { 1418 case AR_dependent: 1419 DelayDependentAccess(S, EC, Loc, Entity); 1420 return AR_dependent; 1421 1422 case AR_inaccessible: 1423 if (S.getLangOpts().MSVCCompat && 1424 IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) 1425 return AR_accessible; 1426 if (!Entity.isQuiet()) 1427 DiagnoseBadAccess(S, Loc, EC, Entity); 1428 return AR_inaccessible; 1429 1430 case AR_accessible: 1431 return AR_accessible; 1432 } 1433 1434 // silence unnecessary warning 1435 llvm_unreachable("invalid access result"); 1436 } 1437 1438 static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 1439 AccessTarget &Entity) { 1440 // If the access path is public, it's accessible everywhere. 1441 if (Entity.getAccess() == AS_public) 1442 return Sema::AR_accessible; 1443 1444 // If we're currently parsing a declaration, we may need to delay 1445 // access control checking, because our effective context might be 1446 // different based on what the declaration comes out as. 1447 // 1448 // For example, we might be parsing a declaration with a scope 1449 // specifier, like this: 1450 // A::private_type A::foo() { ... } 1451 // 1452 // Or we might be parsing something that will turn out to be a friend: 1453 // void foo(A::private_type); 1454 // void B::foo(A::private_type); 1455 if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { 1456 S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); 1457 return Sema::AR_delayed; 1458 } 1459 1460 EffectiveContext EC(S.CurContext); 1461 switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { 1462 case AR_accessible: return Sema::AR_accessible; 1463 case AR_inaccessible: return Sema::AR_inaccessible; 1464 case AR_dependent: return Sema::AR_dependent; 1465 } 1466 llvm_unreachable("invalid access result"); 1467 } 1468 1469 void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { 1470 // Access control for names used in the declarations of functions 1471 // and function templates should normally be evaluated in the context 1472 // of the declaration, just in case it's a friend of something. 1473 // However, this does not apply to local extern declarations. 1474 1475 DeclContext *DC = D->getDeclContext(); 1476 if (D->isLocalExternDecl()) { 1477 DC = D->getLexicalDeclContext(); 1478 } else if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) { 1479 DC = FN; 1480 } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { 1481 DC = cast<DeclContext>(TD->getTemplatedDecl()); 1482 } 1483 1484 EffectiveContext EC(DC); 1485 1486 AccessTarget Target(DD.getAccessData()); 1487 1488 if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) 1489 DD.Triggered = true; 1490 } 1491 1492 void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 1493 const MultiLevelTemplateArgumentList &TemplateArgs) { 1494 SourceLocation Loc = DD.getAccessLoc(); 1495 AccessSpecifier Access = DD.getAccess(); 1496 1497 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 1498 TemplateArgs); 1499 if (!NamingD) return; 1500 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 1501 TemplateArgs); 1502 if (!TargetD) return; 1503 1504 if (DD.isAccessToMember()) { 1505 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); 1506 NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); 1507 QualType BaseObjectType = DD.getAccessBaseObjectType(); 1508 if (!BaseObjectType.isNull()) { 1509 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, 1510 DeclarationName()); 1511 if (BaseObjectType.isNull()) return; 1512 } 1513 1514 AccessTarget Entity(Context, 1515 AccessTarget::Member, 1516 NamingClass, 1517 DeclAccessPair::make(TargetDecl, Access), 1518 BaseObjectType); 1519 Entity.setDiag(DD.getDiagnostic()); 1520 CheckAccess(*this, Loc, Entity); 1521 } else { 1522 AccessTarget Entity(Context, 1523 AccessTarget::Base, 1524 cast<CXXRecordDecl>(TargetD), 1525 cast<CXXRecordDecl>(NamingD), 1526 Access); 1527 Entity.setDiag(DD.getDiagnostic()); 1528 CheckAccess(*this, Loc, Entity); 1529 } 1530 } 1531 1532 Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 1533 DeclAccessPair Found) { 1534 if (!getLangOpts().AccessControl || 1535 !E->getNamingClass() || 1536 Found.getAccess() == AS_public) 1537 return AR_accessible; 1538 1539 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1540 Found, QualType()); 1541 Entity.setDiag(diag::err_access) << E->getSourceRange(); 1542 1543 return CheckAccess(*this, E->getNameLoc(), Entity); 1544 } 1545 1546 /// Perform access-control checking on a previously-unresolved member 1547 /// access which has now been resolved to a member. 1548 Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 1549 DeclAccessPair Found) { 1550 if (!getLangOpts().AccessControl || 1551 Found.getAccess() == AS_public) 1552 return AR_accessible; 1553 1554 QualType BaseType = E->getBaseType(); 1555 if (E->isArrow()) 1556 BaseType = BaseType->getAs<PointerType>()->getPointeeType(); 1557 1558 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1559 Found, BaseType); 1560 Entity.setDiag(diag::err_access) << E->getSourceRange(); 1561 1562 return CheckAccess(*this, E->getMemberLoc(), Entity); 1563 } 1564 1565 /// Is the given special member function accessible for the purposes of 1566 /// deciding whether to define a special member function as deleted? 1567 bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl, 1568 AccessSpecifier access, 1569 QualType objectType) { 1570 // Fast path. 1571 if (access == AS_public || !getLangOpts().AccessControl) return true; 1572 1573 AccessTarget entity(Context, AccessTarget::Member, decl->getParent(), 1574 DeclAccessPair::make(decl, access), objectType); 1575 1576 // Suppress diagnostics. 1577 entity.setDiag(PDiag()); 1578 1579 switch (CheckAccess(*this, SourceLocation(), entity)) { 1580 case AR_accessible: return true; 1581 case AR_inaccessible: return false; 1582 case AR_dependent: llvm_unreachable("dependent for =delete computation"); 1583 case AR_delayed: llvm_unreachable("cannot delay =delete computation"); 1584 } 1585 llvm_unreachable("bad access result"); 1586 } 1587 1588 Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 1589 CXXDestructorDecl *Dtor, 1590 const PartialDiagnostic &PDiag, 1591 QualType ObjectTy) { 1592 if (!getLangOpts().AccessControl) 1593 return AR_accessible; 1594 1595 // There's never a path involved when checking implicit destructor access. 1596 AccessSpecifier Access = Dtor->getAccess(); 1597 if (Access == AS_public) 1598 return AR_accessible; 1599 1600 CXXRecordDecl *NamingClass = Dtor->getParent(); 1601 if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass); 1602 1603 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1604 DeclAccessPair::make(Dtor, Access), 1605 ObjectTy); 1606 Entity.setDiag(PDiag); // TODO: avoid copy 1607 1608 return CheckAccess(*this, Loc, Entity); 1609 } 1610 1611 /// Checks access to a constructor. 1612 Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 1613 CXXConstructorDecl *Constructor, 1614 DeclAccessPair Found, 1615 const InitializedEntity &Entity, 1616 bool IsCopyBindingRefToTemp) { 1617 if (!getLangOpts().AccessControl || Found.getAccess() == AS_public) 1618 return AR_accessible; 1619 1620 PartialDiagnostic PD(PDiag()); 1621 switch (Entity.getKind()) { 1622 default: 1623 PD = PDiag(IsCopyBindingRefToTemp 1624 ? diag::ext_rvalue_to_reference_access_ctor 1625 : diag::err_access_ctor); 1626 1627 break; 1628 1629 case InitializedEntity::EK_Base: 1630 PD = PDiag(diag::err_access_base_ctor); 1631 PD << Entity.isInheritedVirtualBase() 1632 << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); 1633 break; 1634 1635 case InitializedEntity::EK_Member: { 1636 const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); 1637 PD = PDiag(diag::err_access_field_ctor); 1638 PD << Field->getType() << getSpecialMember(Constructor); 1639 break; 1640 } 1641 1642 case InitializedEntity::EK_LambdaCapture: { 1643 StringRef VarName = Entity.getCapturedVarName(); 1644 PD = PDiag(diag::err_access_lambda_capture); 1645 PD << VarName << Entity.getType() << getSpecialMember(Constructor); 1646 break; 1647 } 1648 1649 } 1650 1651 return CheckConstructorAccess(UseLoc, Constructor, Found, Entity, PD); 1652 } 1653 1654 /// Checks access to a constructor. 1655 Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 1656 CXXConstructorDecl *Constructor, 1657 DeclAccessPair Found, 1658 const InitializedEntity &Entity, 1659 const PartialDiagnostic &PD) { 1660 if (!getLangOpts().AccessControl || 1661 Found.getAccess() == AS_public) 1662 return AR_accessible; 1663 1664 CXXRecordDecl *NamingClass = Constructor->getParent(); 1665 1666 // Initializing a base sub-object is an instance method call on an 1667 // object of the derived class. Otherwise, we have an instance method 1668 // call on an object of the constructed type. 1669 // 1670 // FIXME: If we have a parent, we're initializing the base class subobject 1671 // in aggregate initialization. It's not clear whether the object class 1672 // should be the base class or the derived class in that case. 1673 CXXRecordDecl *ObjectClass; 1674 if ((Entity.getKind() == InitializedEntity::EK_Base || 1675 Entity.getKind() == InitializedEntity::EK_Delegating) && 1676 !Entity.getParent()) { 1677 ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent(); 1678 } else if (auto *Shadow = 1679 dyn_cast<ConstructorUsingShadowDecl>(Found.getDecl())) { 1680 // If we're using an inheriting constructor to construct an object, 1681 // the object class is the derived class, not the base class. 1682 ObjectClass = Shadow->getParent(); 1683 } else { 1684 ObjectClass = NamingClass; 1685 } 1686 1687 AccessTarget AccessEntity( 1688 Context, AccessTarget::Member, NamingClass, 1689 DeclAccessPair::make(Constructor, Found.getAccess()), 1690 Context.getTypeDeclType(ObjectClass)); 1691 AccessEntity.setDiag(PD); 1692 1693 return CheckAccess(*this, UseLoc, AccessEntity); 1694 } 1695 1696 /// Checks access to an overloaded operator new or delete. 1697 Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 1698 SourceRange PlacementRange, 1699 CXXRecordDecl *NamingClass, 1700 DeclAccessPair Found, 1701 bool Diagnose) { 1702 if (!getLangOpts().AccessControl || 1703 !NamingClass || 1704 Found.getAccess() == AS_public) 1705 return AR_accessible; 1706 1707 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1708 QualType()); 1709 if (Diagnose) 1710 Entity.setDiag(diag::err_access) 1711 << PlacementRange; 1712 1713 return CheckAccess(*this, OpLoc, Entity); 1714 } 1715 1716 /// Checks access to a member. 1717 Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, 1718 CXXRecordDecl *NamingClass, 1719 DeclAccessPair Found) { 1720 if (!getLangOpts().AccessControl || 1721 !NamingClass || 1722 Found.getAccess() == AS_public) 1723 return AR_accessible; 1724 1725 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1726 Found, QualType()); 1727 1728 return CheckAccess(*this, UseLoc, Entity); 1729 } 1730 1731 /// Checks implicit access to a member in a structured binding. 1732 Sema::AccessResult 1733 Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc, 1734 CXXRecordDecl *DecomposedClass, 1735 DeclAccessPair Field) { 1736 if (!getLangOpts().AccessControl || 1737 Field.getAccess() == AS_public) 1738 return AR_accessible; 1739 1740 AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field, 1741 Context.getRecordType(DecomposedClass)); 1742 Entity.setDiag(diag::err_decomp_decl_inaccessible_field); 1743 1744 return CheckAccess(*this, UseLoc, Entity); 1745 } 1746 1747 /// Checks access to an overloaded member operator, including 1748 /// conversion operators. 1749 Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 1750 Expr *ObjectExpr, 1751 Expr *ArgExpr, 1752 DeclAccessPair Found) { 1753 if (!getLangOpts().AccessControl || 1754 Found.getAccess() == AS_public) 1755 return AR_accessible; 1756 1757 const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>(); 1758 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 1759 1760 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1761 ObjectExpr->getType()); 1762 Entity.setDiag(diag::err_access) 1763 << ObjectExpr->getSourceRange() 1764 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 1765 1766 return CheckAccess(*this, OpLoc, Entity); 1767 } 1768 1769 /// Checks access to the target of a friend declaration. 1770 Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) { 1771 assert(isa<CXXMethodDecl>(target->getAsFunction())); 1772 1773 // Friendship lookup is a redeclaration lookup, so there's never an 1774 // inheritance path modifying access. 1775 AccessSpecifier access = target->getAccess(); 1776 1777 if (!getLangOpts().AccessControl || access == AS_public) 1778 return AR_accessible; 1779 1780 CXXMethodDecl *method = cast<CXXMethodDecl>(target->getAsFunction()); 1781 1782 AccessTarget entity(Context, AccessTarget::Member, 1783 cast<CXXRecordDecl>(target->getDeclContext()), 1784 DeclAccessPair::make(target, access), 1785 /*no instance context*/ QualType()); 1786 entity.setDiag(diag::err_access_friend_function) 1787 << (method->getQualifier() ? method->getQualifierLoc().getSourceRange() 1788 : method->getNameInfo().getSourceRange()); 1789 1790 // We need to bypass delayed-diagnostics because we might be called 1791 // while the ParsingDeclarator is active. 1792 EffectiveContext EC(CurContext); 1793 switch (CheckEffectiveAccess(*this, EC, target->getLocation(), entity)) { 1794 case ::AR_accessible: return Sema::AR_accessible; 1795 case ::AR_inaccessible: return Sema::AR_inaccessible; 1796 case ::AR_dependent: return Sema::AR_dependent; 1797 } 1798 llvm_unreachable("invalid access result"); 1799 } 1800 1801 Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 1802 DeclAccessPair Found) { 1803 if (!getLangOpts().AccessControl || 1804 Found.getAccess() == AS_none || 1805 Found.getAccess() == AS_public) 1806 return AR_accessible; 1807 1808 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; 1809 CXXRecordDecl *NamingClass = Ovl->getNamingClass(); 1810 1811 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1812 /*no instance context*/ QualType()); 1813 Entity.setDiag(diag::err_access) 1814 << Ovl->getSourceRange(); 1815 1816 return CheckAccess(*this, Ovl->getNameLoc(), Entity); 1817 } 1818 1819 /// Checks access for a hierarchy conversion. 1820 /// 1821 /// \param ForceCheck true if this check should be performed even if access 1822 /// control is disabled; some things rely on this for semantics 1823 /// \param ForceUnprivileged true if this check should proceed as if the 1824 /// context had no special privileges 1825 Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 1826 QualType Base, 1827 QualType Derived, 1828 const CXXBasePath &Path, 1829 unsigned DiagID, 1830 bool ForceCheck, 1831 bool ForceUnprivileged) { 1832 if (!ForceCheck && !getLangOpts().AccessControl) 1833 return AR_accessible; 1834 1835 if (Path.Access == AS_public) 1836 return AR_accessible; 1837 1838 CXXRecordDecl *BaseD, *DerivedD; 1839 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 1840 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 1841 1842 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 1843 Path.Access); 1844 if (DiagID) 1845 Entity.setDiag(DiagID) << Derived << Base; 1846 1847 if (ForceUnprivileged) { 1848 switch (CheckEffectiveAccess(*this, EffectiveContext(), 1849 AccessLoc, Entity)) { 1850 case ::AR_accessible: return Sema::AR_accessible; 1851 case ::AR_inaccessible: return Sema::AR_inaccessible; 1852 case ::AR_dependent: return Sema::AR_dependent; 1853 } 1854 llvm_unreachable("unexpected result from CheckEffectiveAccess"); 1855 } 1856 return CheckAccess(*this, AccessLoc, Entity); 1857 } 1858 1859 /// Checks access to all the declarations in the given result set. 1860 void Sema::CheckLookupAccess(const LookupResult &R) { 1861 assert(getLangOpts().AccessControl 1862 && "performing access check without access control"); 1863 assert(R.getNamingClass() && "performing access check without naming class"); 1864 1865 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 1866 if (I.getAccess() != AS_public) { 1867 AccessTarget Entity(Context, AccessedEntity::Member, 1868 R.getNamingClass(), I.getPair(), 1869 R.getBaseObjectType()); 1870 Entity.setDiag(diag::err_access); 1871 CheckAccess(*this, R.getNameLoc(), Entity); 1872 } 1873 } 1874 } 1875 1876 /// Checks access to Target from the given class. The check will take access 1877 /// specifiers into account, but no member access expressions and such. 1878 /// 1879 /// \param Target the declaration to check if it can be accessed 1880 /// \param Ctx the class/context from which to start the search 1881 /// \return true if the Target is accessible from the Class, false otherwise. 1882 bool Sema::IsSimplyAccessible(NamedDecl *Target, DeclContext *Ctx) { 1883 if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) { 1884 if (!Target->isCXXClassMember()) 1885 return true; 1886 1887 if (Target->getAccess() == AS_public) 1888 return true; 1889 QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); 1890 // The unprivileged access is AS_none as we don't know how the member was 1891 // accessed, which is described by the access in DeclAccessPair. 1892 // `IsAccessible` will examine the actual access of Target (i.e. 1893 // Decl->getAccess()) when calculating the access. 1894 AccessTarget Entity(Context, AccessedEntity::Member, Class, 1895 DeclAccessPair::make(Target, AS_none), qType); 1896 EffectiveContext EC(CurContext); 1897 return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; 1898 } 1899 1900 if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Target)) { 1901 // @public and @package ivars are always accessible. 1902 if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public || 1903 Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package) 1904 return true; 1905 1906 // If we are inside a class or category implementation, determine the 1907 // interface we're in. 1908 ObjCInterfaceDecl *ClassOfMethodDecl = nullptr; 1909 if (ObjCMethodDecl *MD = getCurMethodDecl()) 1910 ClassOfMethodDecl = MD->getClassInterface(); 1911 else if (FunctionDecl *FD = getCurFunctionDecl()) { 1912 if (ObjCImplDecl *Impl 1913 = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) { 1914 if (ObjCImplementationDecl *IMPD 1915 = dyn_cast<ObjCImplementationDecl>(Impl)) 1916 ClassOfMethodDecl = IMPD->getClassInterface(); 1917 else if (ObjCCategoryImplDecl* CatImplClass 1918 = dyn_cast<ObjCCategoryImplDecl>(Impl)) 1919 ClassOfMethodDecl = CatImplClass->getClassInterface(); 1920 } 1921 } 1922 1923 // If we're not in an interface, this ivar is inaccessible. 1924 if (!ClassOfMethodDecl) 1925 return false; 1926 1927 // If we're inside the same interface that owns the ivar, we're fine. 1928 if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface())) 1929 return true; 1930 1931 // If the ivar is private, it's inaccessible. 1932 if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private) 1933 return false; 1934 1935 return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl); 1936 } 1937 1938 return true; 1939 } 1940