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