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