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