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