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