SemaAccess.cpp revision 337ec3d0e8cb24a591ecbecdc0a995a167f6af01
1//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file provides Sema routines for C++ access control semantics. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Sema/SemaInternal.h" 15#include "clang/Sema/DelayedDiagnostic.h" 16#include "clang/Sema/Initialization.h" 17#include "clang/Sema/Lookup.h" 18#include "clang/AST/ASTContext.h" 19#include "clang/AST/CXXInheritance.h" 20#include "clang/AST/DeclCXX.h" 21#include "clang/AST/DeclFriend.h" 22#include "clang/AST/DependentDiagnostic.h" 23#include "clang/AST/ExprCXX.h" 24 25using namespace clang; 26using namespace sema; 27 28/// A copy of Sema's enum without AR_delayed. 29enum AccessResult { 30 AR_accessible, 31 AR_inaccessible, 32 AR_dependent 33}; 34 35/// SetMemberAccessSpecifier - Set the access specifier of a member. 36/// Returns true on error (when the previous member decl access specifier 37/// is different from the new member decl access specifier). 38bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 39 NamedDecl *PrevMemberDecl, 40 AccessSpecifier LexicalAS) { 41 if (!PrevMemberDecl) { 42 // Use the lexical access specifier. 43 MemberDecl->setAccess(LexicalAS); 44 return false; 45 } 46 47 // C++ [class.access.spec]p3: When a member is redeclared its access 48 // specifier must be same as its initial declaration. 49 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 50 Diag(MemberDecl->getLocation(), 51 diag::err_class_redeclared_with_different_access) 52 << MemberDecl << LexicalAS; 53 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 54 << PrevMemberDecl << PrevMemberDecl->getAccess(); 55 56 MemberDecl->setAccess(LexicalAS); 57 return true; 58 } 59 60 MemberDecl->setAccess(PrevMemberDecl->getAccess()); 61 return false; 62} 63 64static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 65 DeclContext *DC = D->getDeclContext(); 66 67 // This can only happen at top: enum decls only "publish" their 68 // immediate members. 69 if (isa<EnumDecl>(DC)) 70 DC = cast<EnumDecl>(DC)->getDeclContext(); 71 72 CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 73 while (DeclaringClass->isAnonymousStructOrUnion()) 74 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 75 return DeclaringClass; 76} 77 78namespace { 79struct EffectiveContext { 80 EffectiveContext() : Inner(0), Dependent(false) {} 81 82 explicit EffectiveContext(DeclContext *DC) 83 : Inner(DC), 84 Dependent(DC->isDependentContext()) { 85 86 // C++ [class.access.nest]p1: 87 // A nested class is a member and as such has the same access 88 // rights as any other member. 89 // C++ [class.access]p2: 90 // A member of a class can also access all the names to which 91 // the class has access. A local class of a member function 92 // may access the same names that the member function itself 93 // may access. 94 // This almost implies that the privileges of nesting are transitive. 95 // Technically it says nothing about the local classes of non-member 96 // functions (which can gain privileges through friendship), but we 97 // take that as an oversight. 98 while (true) { 99 if (isa<CXXRecordDecl>(DC)) { 100 CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); 101 Records.push_back(Record); 102 DC = Record->getDeclContext(); 103 } else if (isa<FunctionDecl>(DC)) { 104 FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); 105 Functions.push_back(Function); 106 DC = Function->getDeclContext(); 107 } else if (DC->isFileContext()) { 108 break; 109 } else { 110 DC = DC->getParent(); 111 } 112 } 113 } 114 115 bool isDependent() const { return Dependent; } 116 117 bool includesClass(const CXXRecordDecl *R) const { 118 R = R->getCanonicalDecl(); 119 return std::find(Records.begin(), Records.end(), R) 120 != Records.end(); 121 } 122 123 /// Retrieves the innermost "useful" context. Can be null if we're 124 /// doing access-control without privileges. 125 DeclContext *getInnerContext() const { 126 return Inner; 127 } 128 129 typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 130 131 DeclContext *Inner; 132 llvm::SmallVector<FunctionDecl*, 4> Functions; 133 llvm::SmallVector<CXXRecordDecl*, 4> Records; 134 bool Dependent; 135}; 136 137/// Like sema:;AccessedEntity, but kindly lets us scribble all over 138/// it. 139struct AccessTarget : public AccessedEntity { 140 AccessTarget(const AccessedEntity &Entity) 141 : AccessedEntity(Entity) { 142 initialize(); 143 } 144 145 AccessTarget(ASTContext &Context, 146 MemberNonce _, 147 CXXRecordDecl *NamingClass, 148 DeclAccessPair FoundDecl, 149 QualType BaseObjectType) 150 : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) { 151 initialize(); 152 } 153 154 AccessTarget(ASTContext &Context, 155 BaseNonce _, 156 CXXRecordDecl *BaseClass, 157 CXXRecordDecl *DerivedClass, 158 AccessSpecifier Access) 159 : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) { 160 initialize(); 161 } 162 163 bool hasInstanceContext() const { 164 return HasInstanceContext; 165 } 166 167 class SavedInstanceContext { 168 public: 169 ~SavedInstanceContext() { 170 Target.HasInstanceContext = Has; 171 } 172 173 private: 174 friend struct AccessTarget; 175 explicit SavedInstanceContext(AccessTarget &Target) 176 : Target(Target), Has(Target.HasInstanceContext) {} 177 AccessTarget &Target; 178 bool Has; 179 }; 180 181 SavedInstanceContext saveInstanceContext() { 182 return SavedInstanceContext(*this); 183 } 184 185 void suppressInstanceContext() { 186 HasInstanceContext = false; 187 } 188 189 const CXXRecordDecl *resolveInstanceContext(Sema &S) const { 190 assert(HasInstanceContext); 191 if (CalculatedInstanceContext) 192 return InstanceContext; 193 194 CalculatedInstanceContext = true; 195 DeclContext *IC = S.computeDeclContext(getBaseObjectType()); 196 InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0); 197 return InstanceContext; 198 } 199 200 const CXXRecordDecl *getDeclaringClass() const { 201 return DeclaringClass; 202 } 203 204private: 205 void initialize() { 206 HasInstanceContext = (isMemberAccess() && 207 !getBaseObjectType().isNull() && 208 getTargetDecl()->isCXXInstanceMember()); 209 CalculatedInstanceContext = false; 210 InstanceContext = 0; 211 212 if (isMemberAccess()) 213 DeclaringClass = FindDeclaringClass(getTargetDecl()); 214 else 215 DeclaringClass = getBaseClass(); 216 DeclaringClass = DeclaringClass->getCanonicalDecl(); 217 } 218 219 bool HasInstanceContext : 1; 220 mutable bool CalculatedInstanceContext : 1; 221 mutable const CXXRecordDecl *InstanceContext; 222 const CXXRecordDecl *DeclaringClass; 223}; 224 225} 226 227/// Checks whether one class might instantiate to the other. 228static bool MightInstantiateTo(const CXXRecordDecl *From, 229 const CXXRecordDecl *To) { 230 // Declaration names are always preserved by instantiation. 231 if (From->getDeclName() != To->getDeclName()) 232 return false; 233 234 const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); 235 const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); 236 if (FromDC == ToDC) return true; 237 if (FromDC->isFileContext() || ToDC->isFileContext()) return false; 238 239 // Be conservative. 240 return true; 241} 242 243/// Checks whether one class is derived from another, inclusively. 244/// Properly indicates when it couldn't be determined due to 245/// dependence. 246/// 247/// This should probably be donated to AST or at least Sema. 248static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, 249 const CXXRecordDecl *Target) { 250 assert(Derived->getCanonicalDecl() == Derived); 251 assert(Target->getCanonicalDecl() == Target); 252 253 if (Derived == Target) return AR_accessible; 254 255 bool CheckDependent = Derived->isDependentContext(); 256 if (CheckDependent && MightInstantiateTo(Derived, Target)) 257 return AR_dependent; 258 259 AccessResult OnFailure = AR_inaccessible; 260 llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack 261 262 while (true) { 263 for (CXXRecordDecl::base_class_const_iterator 264 I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { 265 266 const CXXRecordDecl *RD; 267 268 QualType T = I->getType(); 269 if (const RecordType *RT = T->getAs<RecordType>()) { 270 RD = cast<CXXRecordDecl>(RT->getDecl()); 271 } else if (const InjectedClassNameType *IT 272 = T->getAs<InjectedClassNameType>()) { 273 RD = IT->getDecl(); 274 } else { 275 assert(T->isDependentType() && "non-dependent base wasn't a record?"); 276 OnFailure = AR_dependent; 277 continue; 278 } 279 280 RD = RD->getCanonicalDecl(); 281 if (RD == Target) return AR_accessible; 282 if (CheckDependent && MightInstantiateTo(RD, Target)) 283 OnFailure = AR_dependent; 284 285 Queue.push_back(RD); 286 } 287 288 if (Queue.empty()) break; 289 290 Derived = Queue.back(); 291 Queue.pop_back(); 292 } 293 294 return OnFailure; 295} 296 297 298static bool MightInstantiateTo(Sema &S, DeclContext *Context, 299 DeclContext *Friend) { 300 if (Friend == Context) 301 return true; 302 303 assert(!Friend->isDependentContext() && 304 "can't handle friends with dependent contexts here"); 305 306 if (!Context->isDependentContext()) 307 return false; 308 309 if (Friend->isFileContext()) 310 return false; 311 312 // TODO: this is very conservative 313 return true; 314} 315 316// Asks whether the type in 'context' can ever instantiate to the type 317// in 'friend'. 318static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 319 if (Friend == Context) 320 return true; 321 322 if (!Friend->isDependentType() && !Context->isDependentType()) 323 return false; 324 325 // TODO: this is very conservative. 326 return true; 327} 328 329static bool MightInstantiateTo(Sema &S, 330 FunctionDecl *Context, 331 FunctionDecl *Friend) { 332 if (Context->getDeclName() != Friend->getDeclName()) 333 return false; 334 335 if (!MightInstantiateTo(S, 336 Context->getDeclContext(), 337 Friend->getDeclContext())) 338 return false; 339 340 CanQual<FunctionProtoType> FriendTy 341 = S.Context.getCanonicalType(Friend->getType()) 342 ->getAs<FunctionProtoType>(); 343 CanQual<FunctionProtoType> ContextTy 344 = S.Context.getCanonicalType(Context->getType()) 345 ->getAs<FunctionProtoType>(); 346 347 // There isn't any way that I know of to add qualifiers 348 // during instantiation. 349 if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 350 return false; 351 352 if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) 353 return false; 354 355 if (!MightInstantiateTo(S, 356 ContextTy->getResultType(), 357 FriendTy->getResultType())) 358 return false; 359 360 for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) 361 if (!MightInstantiateTo(S, 362 ContextTy->getArgType(I), 363 FriendTy->getArgType(I))) 364 return false; 365 366 return true; 367} 368 369static bool MightInstantiateTo(Sema &S, 370 FunctionTemplateDecl *Context, 371 FunctionTemplateDecl *Friend) { 372 return MightInstantiateTo(S, 373 Context->getTemplatedDecl(), 374 Friend->getTemplatedDecl()); 375} 376 377static AccessResult MatchesFriend(Sema &S, 378 const EffectiveContext &EC, 379 const CXXRecordDecl *Friend) { 380 if (EC.includesClass(Friend)) 381 return AR_accessible; 382 383 if (EC.isDependent()) { 384 CanQualType FriendTy 385 = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); 386 387 for (EffectiveContext::record_iterator 388 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 389 CanQualType ContextTy 390 = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); 391 if (MightInstantiateTo(S, ContextTy, FriendTy)) 392 return AR_dependent; 393 } 394 } 395 396 return AR_inaccessible; 397} 398 399static AccessResult MatchesFriend(Sema &S, 400 const EffectiveContext &EC, 401 CanQualType Friend) { 402 if (const RecordType *RT = Friend->getAs<RecordType>()) 403 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 404 405 // TODO: we can do better than this 406 if (Friend->isDependentType()) 407 return AR_dependent; 408 409 return AR_inaccessible; 410} 411 412/// Determines whether the given friend class template matches 413/// anything in the effective context. 414static AccessResult MatchesFriend(Sema &S, 415 const EffectiveContext &EC, 416 ClassTemplateDecl *Friend) { 417 AccessResult OnFailure = AR_inaccessible; 418 419 // Check whether the friend is the template of a class in the 420 // context chain. 421 for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator 422 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 423 CXXRecordDecl *Record = *I; 424 425 // Figure out whether the current class has a template: 426 ClassTemplateDecl *CTD; 427 428 // A specialization of the template... 429 if (isa<ClassTemplateSpecializationDecl>(Record)) { 430 CTD = cast<ClassTemplateSpecializationDecl>(Record) 431 ->getSpecializedTemplate(); 432 433 // ... or the template pattern itself. 434 } else { 435 CTD = Record->getDescribedClassTemplate(); 436 if (!CTD) continue; 437 } 438 439 // It's a match. 440 if (Friend == CTD->getCanonicalDecl()) 441 return AR_accessible; 442 443 // If the context isn't dependent, it can't be a dependent match. 444 if (!EC.isDependent()) 445 continue; 446 447 // If the template names don't match, it can't be a dependent 448 // match. This isn't true in C++0x because of template aliases. 449 if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName()) 450 continue; 451 452 // If the class's context can't instantiate to the friend's 453 // context, it can't be a dependent match. 454 if (!MightInstantiateTo(S, CTD->getDeclContext(), 455 Friend->getDeclContext())) 456 continue; 457 458 // Otherwise, it's a dependent match. 459 OnFailure = AR_dependent; 460 } 461 462 return OnFailure; 463} 464 465/// Determines whether the given friend function matches anything in 466/// the effective context. 467static AccessResult MatchesFriend(Sema &S, 468 const EffectiveContext &EC, 469 FunctionDecl *Friend) { 470 AccessResult OnFailure = AR_inaccessible; 471 472 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 473 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 474 if (Friend == *I) 475 return AR_accessible; 476 477 if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 478 OnFailure = AR_dependent; 479 } 480 481 return OnFailure; 482} 483 484/// Determines whether the given friend function template matches 485/// anything in the effective context. 486static AccessResult MatchesFriend(Sema &S, 487 const EffectiveContext &EC, 488 FunctionTemplateDecl *Friend) { 489 if (EC.Functions.empty()) return AR_inaccessible; 490 491 AccessResult OnFailure = AR_inaccessible; 492 493 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 494 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 495 496 FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 497 if (!FTD) 498 FTD = (*I)->getDescribedFunctionTemplate(); 499 if (!FTD) 500 continue; 501 502 FTD = FTD->getCanonicalDecl(); 503 504 if (Friend == FTD) 505 return AR_accessible; 506 507 if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 508 OnFailure = AR_dependent; 509 } 510 511 return OnFailure; 512} 513 514/// Determines whether the given friend declaration matches anything 515/// in the effective context. 516static AccessResult MatchesFriend(Sema &S, 517 const EffectiveContext &EC, 518 FriendDecl *FriendD) { 519 // Whitelist accesses if there's an invalid friend declaration. 520 if (FriendD->isInvalidDecl()) 521 return AR_accessible; 522 523 if (TypeSourceInfo *T = FriendD->getFriendType()) 524 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 525 526 NamedDecl *Friend 527 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 528 529 // FIXME: declarations with dependent or templated scope. 530 531 if (isa<ClassTemplateDecl>(Friend)) 532 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 533 534 if (isa<FunctionTemplateDecl>(Friend)) 535 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 536 537 if (isa<CXXRecordDecl>(Friend)) 538 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 539 540 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 541 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 542} 543 544static AccessResult GetFriendKind(Sema &S, 545 const EffectiveContext &EC, 546 const CXXRecordDecl *Class) { 547 AccessResult OnFailure = AR_inaccessible; 548 549 // Okay, check friends. 550 for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 551 E = Class->friend_end(); I != E; ++I) { 552 FriendDecl *Friend = *I; 553 554 switch (MatchesFriend(S, EC, Friend)) { 555 case AR_accessible: 556 return AR_accessible; 557 558 case AR_inaccessible: 559 continue; 560 561 case AR_dependent: 562 OnFailure = AR_dependent; 563 break; 564 } 565 } 566 567 // That's it, give up. 568 return OnFailure; 569} 570 571namespace { 572 573/// A helper class for checking for a friend which will grant access 574/// to a protected instance member. 575struct ProtectedFriendContext { 576 Sema &S; 577 const EffectiveContext &EC; 578 const CXXRecordDecl *NamingClass; 579 bool CheckDependent; 580 bool EverDependent; 581 582 /// The path down to the current base class. 583 llvm::SmallVector<const CXXRecordDecl*, 20> CurPath; 584 585 ProtectedFriendContext(Sema &S, const EffectiveContext &EC, 586 const CXXRecordDecl *InstanceContext, 587 const CXXRecordDecl *NamingClass) 588 : S(S), EC(EC), NamingClass(NamingClass), 589 CheckDependent(InstanceContext->isDependentContext() || 590 NamingClass->isDependentContext()), 591 EverDependent(false) {} 592 593 /// Check classes in the current path for friendship, starting at 594 /// the given index. 595 bool checkFriendshipAlongPath(unsigned I) { 596 assert(I < CurPath.size()); 597 for (unsigned E = CurPath.size(); I != E; ++I) { 598 switch (GetFriendKind(S, EC, CurPath[I])) { 599 case AR_accessible: return true; 600 case AR_inaccessible: continue; 601 case AR_dependent: EverDependent = true; continue; 602 } 603 } 604 return false; 605 } 606 607 /// Perform a search starting at the given class. 608 /// 609 /// PrivateDepth is the index of the last (least derived) class 610 /// along the current path such that a notional public member of 611 /// the final class in the path would have access in that class. 612 bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { 613 // If we ever reach the naming class, check the current path for 614 // friendship. We can also stop recursing because we obviously 615 // won't find the naming class there again. 616 if (Cur == NamingClass) 617 return checkFriendshipAlongPath(PrivateDepth); 618 619 if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) 620 EverDependent = true; 621 622 // Recurse into the base classes. 623 for (CXXRecordDecl::base_class_const_iterator 624 I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) { 625 626 // If this is private inheritance, then a public member of the 627 // base will not have any access in classes derived from Cur. 628 unsigned BasePrivateDepth = PrivateDepth; 629 if (I->getAccessSpecifier() == AS_private) 630 BasePrivateDepth = CurPath.size() - 1; 631 632 const CXXRecordDecl *RD; 633 634 QualType T = I->getType(); 635 if (const RecordType *RT = T->getAs<RecordType>()) { 636 RD = cast<CXXRecordDecl>(RT->getDecl()); 637 } else if (const InjectedClassNameType *IT 638 = T->getAs<InjectedClassNameType>()) { 639 RD = IT->getDecl(); 640 } else { 641 assert(T->isDependentType() && "non-dependent base wasn't a record?"); 642 EverDependent = true; 643 continue; 644 } 645 646 // Recurse. We don't need to clean up if this returns true. 647 CurPath.push_back(RD); 648 if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) 649 return true; 650 CurPath.pop_back(); 651 } 652 653 return false; 654 } 655 656 bool findFriendship(const CXXRecordDecl *Cur) { 657 assert(CurPath.empty()); 658 CurPath.push_back(Cur); 659 return findFriendship(Cur, 0); 660 } 661}; 662} 663 664/// Search for a class P that EC is a friend of, under the constraint 665/// InstanceContext <= P <= NamingClass 666/// and with the additional restriction that a protected member of 667/// NamingClass would have some natural access in P. 668/// 669/// That second condition isn't actually quite right: the condition in 670/// the standard is whether the target would have some natural access 671/// in P. The difference is that the target might be more accessible 672/// along some path not passing through NamingClass. Allowing that 673/// introduces two problems: 674/// - It breaks encapsulation because you can suddenly access a 675/// forbidden base class's members by subclassing it elsewhere. 676/// - It makes access substantially harder to compute because it 677/// breaks the hill-climbing algorithm: knowing that the target is 678/// accessible in some base class would no longer let you change 679/// the question solely to whether the base class is accessible, 680/// because the original target might have been more accessible 681/// because of crazy subclassing. 682/// So we don't implement that. 683static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, 684 const CXXRecordDecl *InstanceContext, 685 const CXXRecordDecl *NamingClass) { 686 assert(InstanceContext->getCanonicalDecl() == InstanceContext); 687 assert(NamingClass->getCanonicalDecl() == NamingClass); 688 689 ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); 690 if (PRC.findFriendship(InstanceContext)) return AR_accessible; 691 if (PRC.EverDependent) return AR_dependent; 692 return AR_inaccessible; 693} 694 695static AccessResult HasAccess(Sema &S, 696 const EffectiveContext &EC, 697 const CXXRecordDecl *NamingClass, 698 AccessSpecifier Access, 699 const AccessTarget &Target) { 700 assert(NamingClass->getCanonicalDecl() == NamingClass && 701 "declaration should be canonicalized before being passed here"); 702 703 if (Access == AS_public) return AR_accessible; 704 assert(Access == AS_private || Access == AS_protected); 705 706 AccessResult OnFailure = AR_inaccessible; 707 708 for (EffectiveContext::record_iterator 709 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 710 // All the declarations in EC have been canonicalized, so pointer 711 // equality from this point on will work fine. 712 const CXXRecordDecl *ECRecord = *I; 713 714 // [B2] and [M2] 715 if (Access == AS_private) { 716 if (ECRecord == NamingClass) 717 return AR_accessible; 718 719 if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) 720 OnFailure = AR_dependent; 721 722 // [B3] and [M3] 723 } else { 724 assert(Access == AS_protected); 725 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 726 case AR_accessible: break; 727 case AR_inaccessible: continue; 728 case AR_dependent: OnFailure = AR_dependent; continue; 729 } 730 731 if (!Target.hasInstanceContext()) 732 return AR_accessible; 733 734 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 735 if (!InstanceContext) { 736 OnFailure = AR_dependent; 737 continue; 738 } 739 740 // C++ [class.protected]p1: 741 // An additional access check beyond those described earlier in 742 // [class.access] is applied when a non-static data member or 743 // non-static member function is a protected member of its naming 744 // class. As described earlier, access to a protected member is 745 // granted because the reference occurs in a friend or member of 746 // some class C. If the access is to form a pointer to member, 747 // the nested-name-specifier shall name C or a class derived from 748 // C. All other accesses involve a (possibly implicit) object 749 // expression. In this case, the class of the object expression 750 // shall be C or a class derived from C. 751 // 752 // We interpret this as a restriction on [M3]. Most of the 753 // conditions are encoded by not having any instance context. 754 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 755 case AR_accessible: return AR_accessible; 756 case AR_inaccessible: continue; 757 case AR_dependent: OnFailure = AR_dependent; continue; 758 } 759 } 760 } 761 762 // [M3] and [B3] say that, if the target is protected in N, we grant 763 // access if the access occurs in a friend or member of some class P 764 // that's a subclass of N and where the target has some natural 765 // access in P. The 'member' aspect is easy to handle because P 766 // would necessarily be one of the effective-context records, and we 767 // address that above. The 'friend' aspect is completely ridiculous 768 // to implement because there are no restrictions at all on P 769 // *unless* the [class.protected] restriction applies. If it does, 770 // however, we should ignore whether the naming class is a friend, 771 // and instead rely on whether any potential P is a friend. 772 if (Access == AS_protected && Target.hasInstanceContext()) { 773 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 774 if (!InstanceContext) return AR_dependent; 775 switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { 776 case AR_accessible: return AR_accessible; 777 case AR_inaccessible: return OnFailure; 778 case AR_dependent: return AR_dependent; 779 } 780 llvm_unreachable("impossible friendship kind"); 781 } 782 783 switch (GetFriendKind(S, EC, NamingClass)) { 784 case AR_accessible: return AR_accessible; 785 case AR_inaccessible: return OnFailure; 786 case AR_dependent: return AR_dependent; 787 } 788 789 // Silence bogus warnings 790 llvm_unreachable("impossible friendship kind"); 791 return OnFailure; 792} 793 794/// Finds the best path from the naming class to the declaring class, 795/// taking friend declarations into account. 796/// 797/// C++0x [class.access.base]p5: 798/// A member m is accessible at the point R when named in class N if 799/// [M1] m as a member of N is public, or 800/// [M2] m as a member of N is private, and R occurs in a member or 801/// friend of class N, or 802/// [M3] m as a member of N is protected, and R occurs in a member or 803/// friend of class N, or in a member or friend of a class P 804/// derived from N, where m as a member of P is public, private, 805/// or protected, or 806/// [M4] there exists a base class B of N that is accessible at R, and 807/// m is accessible at R when named in class B. 808/// 809/// C++0x [class.access.base]p4: 810/// A base class B of N is accessible at R, if 811/// [B1] an invented public member of B would be a public member of N, or 812/// [B2] R occurs in a member or friend of class N, and an invented public 813/// member of B would be a private or protected member of N, or 814/// [B3] R occurs in a member or friend of a class P derived from N, and an 815/// invented public member of B would be a private or protected member 816/// of P, or 817/// [B4] there exists a class S such that B is a base class of S accessible 818/// at R and S is a base class of N accessible at R. 819/// 820/// Along a single inheritance path we can restate both of these 821/// iteratively: 822/// 823/// First, we note that M1-4 are equivalent to B1-4 if the member is 824/// treated as a notional base of its declaring class with inheritance 825/// access equivalent to the member's access. Therefore we need only 826/// ask whether a class B is accessible from a class N in context R. 827/// 828/// Let B_1 .. B_n be the inheritance path in question (i.e. where 829/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 830/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 831/// closest accessible base in the path: 832/// Access(a, b) = (* access on the base specifier from a to b *) 833/// Merge(a, forbidden) = forbidden 834/// Merge(a, private) = forbidden 835/// Merge(a, b) = min(a,b) 836/// Accessible(c, forbidden) = false 837/// Accessible(c, private) = (R is c) || IsFriend(c, R) 838/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 839/// Accessible(c, public) = true 840/// ACAB(n) = public 841/// ACAB(i) = 842/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 843/// if Accessible(B_i, AccessToBase) then public else AccessToBase 844/// 845/// B is an accessible base of N at R iff ACAB(1) = public. 846/// 847/// \param FinalAccess the access of the "final step", or AS_public if 848/// there is no final step. 849/// \return null if friendship is dependent 850static CXXBasePath *FindBestPath(Sema &S, 851 const EffectiveContext &EC, 852 AccessTarget &Target, 853 AccessSpecifier FinalAccess, 854 CXXBasePaths &Paths) { 855 // Derive the paths to the desired base. 856 const CXXRecordDecl *Derived = Target.getNamingClass(); 857 const CXXRecordDecl *Base = Target.getDeclaringClass(); 858 859 // FIXME: fail correctly when there are dependent paths. 860 bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), 861 Paths); 862 assert(isDerived && "derived class not actually derived from base"); 863 (void) isDerived; 864 865 CXXBasePath *BestPath = 0; 866 867 assert(FinalAccess != AS_none && "forbidden access after declaring class"); 868 869 bool AnyDependent = false; 870 871 // Derive the friend-modified access along each path. 872 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 873 PI != PE; ++PI) { 874 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); 875 876 // Walk through the path backwards. 877 AccessSpecifier PathAccess = FinalAccess; 878 CXXBasePath::iterator I = PI->end(), E = PI->begin(); 879 while (I != E) { 880 --I; 881 882 assert(PathAccess != AS_none); 883 884 // If the declaration is a private member of a base class, there 885 // is no level of friendship in derived classes that can make it 886 // accessible. 887 if (PathAccess == AS_private) { 888 PathAccess = AS_none; 889 break; 890 } 891 892 const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); 893 894 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 895 PathAccess = std::max(PathAccess, BaseAccess); 896 897 switch (HasAccess(S, EC, NC, PathAccess, Target)) { 898 case AR_inaccessible: break; 899 case AR_accessible: 900 PathAccess = AS_public; 901 902 // Future tests are not against members and so do not have 903 // instance context. 904 Target.suppressInstanceContext(); 905 break; 906 case AR_dependent: 907 AnyDependent = true; 908 goto Next; 909 } 910 } 911 912 // Note that we modify the path's Access field to the 913 // friend-modified access. 914 if (BestPath == 0 || PathAccess < BestPath->Access) { 915 BestPath = &*PI; 916 BestPath->Access = PathAccess; 917 918 // Short-circuit if we found a public path. 919 if (BestPath->Access == AS_public) 920 return BestPath; 921 } 922 923 Next: ; 924 } 925 926 assert((!BestPath || BestPath->Access != AS_public) && 927 "fell out of loop with public path"); 928 929 // We didn't find a public path, but at least one path was subject 930 // to dependent friendship, so delay the check. 931 if (AnyDependent) 932 return 0; 933 934 return BestPath; 935} 936 937/// Given that an entity has protected natural access, check whether 938/// access might be denied because of the protected member access 939/// restriction. 940/// 941/// \return true if a note was emitted 942static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, 943 AccessTarget &Target) { 944 // Only applies to instance accesses. 945 if (!Target.hasInstanceContext()) 946 return false; 947 assert(Target.isMemberAccess()); 948 NamedDecl *D = Target.getTargetDecl(); 949 950 const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass(); 951 DeclaringClass = DeclaringClass->getCanonicalDecl(); 952 953 for (EffectiveContext::record_iterator 954 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 955 const CXXRecordDecl *ECRecord = *I; 956 switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) { 957 case AR_accessible: break; 958 case AR_inaccessible: continue; 959 case AR_dependent: continue; 960 } 961 962 // The effective context is a subclass of the declaring class. 963 // If that class isn't a superclass of the instance context, 964 // then the [class.protected] restriction applies. 965 966 // To get this exactly right, this might need to be checked more 967 // holistically; it's not necessarily the case that gaining 968 // access here would grant us access overall. 969 970 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 971 assert(InstanceContext && "diagnosing dependent access"); 972 973 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 974 case AR_accessible: continue; 975 case AR_dependent: continue; 976 case AR_inaccessible: 977 S.Diag(D->getLocation(), diag::note_access_protected_restricted) 978 << (InstanceContext != Target.getNamingClass()->getCanonicalDecl()) 979 << S.Context.getTypeDeclType(InstanceContext) 980 << S.Context.getTypeDeclType(ECRecord); 981 return true; 982 } 983 } 984 985 return false; 986} 987 988/// Diagnose the path which caused the given declaration or base class 989/// to become inaccessible. 990static void DiagnoseAccessPath(Sema &S, 991 const EffectiveContext &EC, 992 AccessTarget &Entity) { 993 AccessSpecifier Access = Entity.getAccess(); 994 const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 995 NamingClass = NamingClass->getCanonicalDecl(); 996 997 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 998 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 999 1000 // Easy case: the decl's natural access determined its path access. 1001 // We have to check against AS_private here in case Access is AS_none, 1002 // indicating a non-public member of a private base class. 1003 if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { 1004 switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) { 1005 case AR_inaccessible: { 1006 if (Access == AS_protected && 1007 TryDiagnoseProtectedAccess(S, EC, Entity)) 1008 return; 1009 1010 S.Diag(D->getLocation(), diag::note_access_natural) 1011 << (unsigned) (Access == AS_protected) 1012 << /*FIXME: not implicitly*/ 0; 1013 return; 1014 } 1015 1016 case AR_accessible: break; 1017 1018 case AR_dependent: 1019 llvm_unreachable("can't diagnose dependent access failures"); 1020 return; 1021 } 1022 } 1023 1024 CXXBasePaths Paths; 1025 CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths); 1026 1027 CXXBasePath::iterator I = Path.end(), E = Path.begin(); 1028 while (I != E) { 1029 --I; 1030 1031 const CXXBaseSpecifier *BS = I->Base; 1032 AccessSpecifier BaseAccess = BS->getAccessSpecifier(); 1033 1034 // If this is public inheritance, or the derived class is a friend, 1035 // skip this step. 1036 if (BaseAccess == AS_public) 1037 continue; 1038 1039 switch (GetFriendKind(S, EC, I->Class)) { 1040 case AR_accessible: continue; 1041 case AR_inaccessible: break; 1042 case AR_dependent: 1043 llvm_unreachable("can't diagnose dependent access failures"); 1044 } 1045 1046 // Check whether this base specifier is the tighest point 1047 // constraining access. We have to check against AS_private for 1048 // the same reasons as above. 1049 if (BaseAccess == AS_private || BaseAccess >= Access) { 1050 1051 // We're constrained by inheritance, but we want to say 1052 // "declared private here" if we're diagnosing a hierarchy 1053 // conversion and this is the final step. 1054 unsigned diagnostic; 1055 if (D) diagnostic = diag::note_access_constrained_by_path; 1056 else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; 1057 else diagnostic = diag::note_access_constrained_by_path; 1058 1059 S.Diag(BS->getSourceRange().getBegin(), diagnostic) 1060 << BS->getSourceRange() 1061 << (BaseAccess == AS_protected) 1062 << (BS->getAccessSpecifierAsWritten() == AS_none); 1063 1064 if (D) 1065 S.Diag(D->getLocation(), diag::note_field_decl); 1066 1067 return; 1068 } 1069 } 1070 1071 llvm_unreachable("access not apparently constrained by path"); 1072} 1073 1074static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 1075 const EffectiveContext &EC, 1076 AccessTarget &Entity) { 1077 const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 1078 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1079 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 1080 1081 S.Diag(Loc, Entity.getDiag()) 1082 << (Entity.getAccess() == AS_protected) 1083 << (D ? D->getDeclName() : DeclarationName()) 1084 << S.Context.getTypeDeclType(NamingClass) 1085 << S.Context.getTypeDeclType(DeclaringClass); 1086 DiagnoseAccessPath(S, EC, Entity); 1087} 1088 1089/// Determines whether the accessed entity is accessible. Public members 1090/// have been weeded out by this point. 1091static AccessResult IsAccessible(Sema &S, 1092 const EffectiveContext &EC, 1093 AccessTarget &Entity) { 1094 // Determine the actual naming class. 1095 CXXRecordDecl *NamingClass = Entity.getNamingClass(); 1096 while (NamingClass->isAnonymousStructOrUnion()) 1097 NamingClass = cast<CXXRecordDecl>(NamingClass->getParent()); 1098 NamingClass = NamingClass->getCanonicalDecl(); 1099 1100 AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 1101 assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 1102 1103 // Before we try to recalculate access paths, try to white-list 1104 // accesses which just trade in on the final step, i.e. accesses 1105 // which don't require [M4] or [B4]. These are by far the most 1106 // common forms of privileged access. 1107 if (UnprivilegedAccess != AS_none) { 1108 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { 1109 case AR_dependent: 1110 // This is actually an interesting policy decision. We don't 1111 // *have* to delay immediately here: we can do the full access 1112 // calculation in the hope that friendship on some intermediate 1113 // class will make the declaration accessible non-dependently. 1114 // But that's not cheap, and odds are very good (note: assertion 1115 // made without data) that the friend declaration will determine 1116 // access. 1117 return AR_dependent; 1118 1119 case AR_accessible: return AR_accessible; 1120 case AR_inaccessible: break; 1121 } 1122 } 1123 1124 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); 1125 1126 // We lower member accesses to base accesses by pretending that the 1127 // member is a base class of its declaring class. 1128 AccessSpecifier FinalAccess; 1129 1130 if (Entity.isMemberAccess()) { 1131 // Determine if the declaration is accessible from EC when named 1132 // in its declaring class. 1133 NamedDecl *Target = Entity.getTargetDecl(); 1134 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1135 1136 FinalAccess = Target->getAccess(); 1137 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { 1138 case AR_accessible: 1139 FinalAccess = AS_public; 1140 break; 1141 case AR_inaccessible: break; 1142 case AR_dependent: return AR_dependent; // see above 1143 } 1144 1145 if (DeclaringClass == NamingClass) 1146 return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); 1147 1148 Entity.suppressInstanceContext(); 1149 } else { 1150 FinalAccess = AS_public; 1151 } 1152 1153 assert(Entity.getDeclaringClass() != NamingClass); 1154 1155 // Append the declaration's access if applicable. 1156 CXXBasePaths Paths; 1157 CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); 1158 if (!Path) 1159 return AR_dependent; 1160 1161 assert(Path->Access <= UnprivilegedAccess && 1162 "access along best path worse than direct?"); 1163 if (Path->Access == AS_public) 1164 return AR_accessible; 1165 return AR_inaccessible; 1166} 1167 1168static void DelayDependentAccess(Sema &S, 1169 const EffectiveContext &EC, 1170 SourceLocation Loc, 1171 const AccessTarget &Entity) { 1172 assert(EC.isDependent() && "delaying non-dependent access"); 1173 DeclContext *DC = EC.getInnerContext(); 1174 assert(DC->isDependentContext() && "delaying non-dependent access"); 1175 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 1176 Loc, 1177 Entity.isMemberAccess(), 1178 Entity.getAccess(), 1179 Entity.getTargetDecl(), 1180 Entity.getNamingClass(), 1181 Entity.getBaseObjectType(), 1182 Entity.getDiag()); 1183} 1184 1185/// Checks access to an entity from the given effective context. 1186static AccessResult CheckEffectiveAccess(Sema &S, 1187 const EffectiveContext &EC, 1188 SourceLocation Loc, 1189 AccessTarget &Entity) { 1190 assert(Entity.getAccess() != AS_public && "called for public access!"); 1191 1192 switch (IsAccessible(S, EC, Entity)) { 1193 case AR_dependent: 1194 DelayDependentAccess(S, EC, Loc, Entity); 1195 return AR_dependent; 1196 1197 case AR_inaccessible: 1198 if (!Entity.isQuiet()) 1199 DiagnoseBadAccess(S, Loc, EC, Entity); 1200 return AR_inaccessible; 1201 1202 case AR_accessible: 1203 return AR_accessible; 1204 } 1205 1206 // silence unnecessary warning 1207 llvm_unreachable("invalid access result"); 1208 return AR_accessible; 1209} 1210 1211static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 1212 AccessTarget &Entity) { 1213 // If the access path is public, it's accessible everywhere. 1214 if (Entity.getAccess() == AS_public) 1215 return Sema::AR_accessible; 1216 1217 if (S.SuppressAccessChecking) 1218 return Sema::AR_accessible; 1219 1220 // If we're currently parsing a top-level declaration, delay 1221 // diagnostics. This is the only case where parsing a declaration 1222 // can actually change our effective context for the purposes of 1223 // access control. 1224 if (S.CurContext->isFileContext() && S.ParsingDeclDepth) { 1225 S.DelayedDiagnostics.push_back( 1226 DelayedDiagnostic::makeAccess(Loc, Entity)); 1227 return Sema::AR_delayed; 1228 } 1229 1230 EffectiveContext EC(S.CurContext); 1231 switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { 1232 case AR_accessible: return Sema::AR_accessible; 1233 case AR_inaccessible: return Sema::AR_inaccessible; 1234 case AR_dependent: return Sema::AR_dependent; 1235 } 1236 llvm_unreachable("falling off end"); 1237 return Sema::AR_accessible; 1238} 1239 1240void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) { 1241 // Pretend we did this from the context of the newly-parsed 1242 // declaration. If that declaration itself forms a declaration context, 1243 // include it in the effective context so that parameters and return types of 1244 // befriended functions have that function's access priveledges. 1245 DeclContext *DC = Ctx->getDeclContext(); 1246 if (isa<FunctionDecl>(Ctx)) 1247 DC = cast<DeclContext>(Ctx); 1248 else if (FunctionTemplateDecl *FnTpl = dyn_cast<FunctionTemplateDecl>(Ctx)) 1249 DC = cast<DeclContext>(FnTpl->getTemplatedDecl()); 1250 EffectiveContext EC(DC); 1251 1252 AccessTarget Target(DD.getAccessData()); 1253 1254 if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) 1255 DD.Triggered = true; 1256} 1257 1258void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 1259 const MultiLevelTemplateArgumentList &TemplateArgs) { 1260 SourceLocation Loc = DD.getAccessLoc(); 1261 AccessSpecifier Access = DD.getAccess(); 1262 1263 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 1264 TemplateArgs); 1265 if (!NamingD) return; 1266 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 1267 TemplateArgs); 1268 if (!TargetD) return; 1269 1270 if (DD.isAccessToMember()) { 1271 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); 1272 NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); 1273 QualType BaseObjectType = DD.getAccessBaseObjectType(); 1274 if (!BaseObjectType.isNull()) { 1275 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, 1276 DeclarationName()); 1277 if (BaseObjectType.isNull()) return; 1278 } 1279 1280 AccessTarget Entity(Context, 1281 AccessTarget::Member, 1282 NamingClass, 1283 DeclAccessPair::make(TargetDecl, Access), 1284 BaseObjectType); 1285 Entity.setDiag(DD.getDiagnostic()); 1286 CheckAccess(*this, Loc, Entity); 1287 } else { 1288 AccessTarget Entity(Context, 1289 AccessTarget::Base, 1290 cast<CXXRecordDecl>(TargetD), 1291 cast<CXXRecordDecl>(NamingD), 1292 Access); 1293 Entity.setDiag(DD.getDiagnostic()); 1294 CheckAccess(*this, Loc, Entity); 1295 } 1296} 1297 1298Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 1299 DeclAccessPair Found) { 1300 if (!getLangOptions().AccessControl || 1301 !E->getNamingClass() || 1302 Found.getAccess() == AS_public) 1303 return AR_accessible; 1304 1305 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1306 Found, QualType()); 1307 Entity.setDiag(diag::err_access) << E->getSourceRange(); 1308 1309 return CheckAccess(*this, E->getNameLoc(), Entity); 1310} 1311 1312/// Perform access-control checking on a previously-unresolved member 1313/// access which has now been resolved to a member. 1314Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 1315 DeclAccessPair Found) { 1316 if (!getLangOptions().AccessControl || 1317 Found.getAccess() == AS_public) 1318 return AR_accessible; 1319 1320 QualType BaseType = E->getBaseType(); 1321 if (E->isArrow()) 1322 BaseType = BaseType->getAs<PointerType>()->getPointeeType(); 1323 1324 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1325 Found, BaseType); 1326 Entity.setDiag(diag::err_access) << E->getSourceRange(); 1327 1328 return CheckAccess(*this, E->getMemberLoc(), Entity); 1329} 1330 1331Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 1332 CXXDestructorDecl *Dtor, 1333 const PartialDiagnostic &PDiag) { 1334 if (!getLangOptions().AccessControl) 1335 return AR_accessible; 1336 1337 // There's never a path involved when checking implicit destructor access. 1338 AccessSpecifier Access = Dtor->getAccess(); 1339 if (Access == AS_public) 1340 return AR_accessible; 1341 1342 CXXRecordDecl *NamingClass = Dtor->getParent(); 1343 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1344 DeclAccessPair::make(Dtor, Access), 1345 QualType()); 1346 Entity.setDiag(PDiag); // TODO: avoid copy 1347 1348 return CheckAccess(*this, Loc, Entity); 1349} 1350 1351/// Checks access to a constructor. 1352Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 1353 CXXConstructorDecl *Constructor, 1354 const InitializedEntity &Entity, 1355 AccessSpecifier Access, 1356 bool IsCopyBindingRefToTemp) { 1357 if (!getLangOptions().AccessControl || 1358 Access == AS_public) 1359 return AR_accessible; 1360 1361 CXXRecordDecl *NamingClass = Constructor->getParent(); 1362 AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, 1363 DeclAccessPair::make(Constructor, Access), 1364 QualType()); 1365 switch (Entity.getKind()) { 1366 default: 1367 AccessEntity.setDiag(IsCopyBindingRefToTemp 1368 ? diag::ext_rvalue_to_reference_access_ctor 1369 : diag::err_access_ctor); 1370 break; 1371 1372 case InitializedEntity::EK_Base: 1373 AccessEntity.setDiag(PDiag(diag::err_access_base) 1374 << Entity.isInheritedVirtualBase() 1375 << Entity.getBaseSpecifier()->getType() 1376 << getSpecialMember(Constructor)); 1377 break; 1378 1379 case InitializedEntity::EK_Member: { 1380 const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); 1381 AccessEntity.setDiag(PDiag(diag::err_access_field) 1382 << Field->getType() 1383 << getSpecialMember(Constructor)); 1384 break; 1385 } 1386 1387 } 1388 1389 return CheckAccess(*this, UseLoc, AccessEntity); 1390} 1391 1392/// Checks direct (i.e. non-inherited) access to an arbitrary class 1393/// member. 1394Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, 1395 NamedDecl *Target, 1396 const PartialDiagnostic &Diag) { 1397 AccessSpecifier Access = Target->getAccess(); 1398 if (!getLangOptions().AccessControl || 1399 Access == AS_public) 1400 return AR_accessible; 1401 1402 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); 1403 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1404 DeclAccessPair::make(Target, Access), 1405 QualType()); 1406 Entity.setDiag(Diag); 1407 return CheckAccess(*this, UseLoc, Entity); 1408} 1409 1410 1411/// Checks access to an overloaded operator new or delete. 1412Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 1413 SourceRange PlacementRange, 1414 CXXRecordDecl *NamingClass, 1415 DeclAccessPair Found) { 1416 if (!getLangOptions().AccessControl || 1417 !NamingClass || 1418 Found.getAccess() == AS_public) 1419 return AR_accessible; 1420 1421 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1422 QualType()); 1423 Entity.setDiag(diag::err_access) 1424 << PlacementRange; 1425 1426 return CheckAccess(*this, OpLoc, Entity); 1427} 1428 1429/// Checks access to an overloaded member operator, including 1430/// conversion operators. 1431Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 1432 Expr *ObjectExpr, 1433 Expr *ArgExpr, 1434 DeclAccessPair Found) { 1435 if (!getLangOptions().AccessControl || 1436 Found.getAccess() == AS_public) 1437 return AR_accessible; 1438 1439 const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); 1440 assert(RT && "found member operator but object expr not of record type"); 1441 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 1442 1443 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1444 ObjectExpr->getType()); 1445 Entity.setDiag(diag::err_access) 1446 << ObjectExpr->getSourceRange() 1447 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 1448 1449 return CheckAccess(*this, OpLoc, Entity); 1450} 1451 1452Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 1453 DeclAccessPair Found) { 1454 if (!getLangOptions().AccessControl || 1455 Found.getAccess() == AS_none || 1456 Found.getAccess() == AS_public) 1457 return AR_accessible; 1458 1459 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; 1460 CXXRecordDecl *NamingClass = Ovl->getNamingClass(); 1461 1462 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1463 Context.getTypeDeclType(NamingClass)); 1464 Entity.setDiag(diag::err_access) 1465 << Ovl->getSourceRange(); 1466 1467 return CheckAccess(*this, Ovl->getNameLoc(), Entity); 1468} 1469 1470/// Checks access for a hierarchy conversion. 1471/// 1472/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) 1473/// or a derived-to-base conversion (false) 1474/// \param ForceCheck true if this check should be performed even if access 1475/// control is disabled; some things rely on this for semantics 1476/// \param ForceUnprivileged true if this check should proceed as if the 1477/// context had no special privileges 1478/// \param ADK controls the kind of diagnostics that are used 1479Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 1480 QualType Base, 1481 QualType Derived, 1482 const CXXBasePath &Path, 1483 unsigned DiagID, 1484 bool ForceCheck, 1485 bool ForceUnprivileged) { 1486 if (!ForceCheck && !getLangOptions().AccessControl) 1487 return AR_accessible; 1488 1489 if (Path.Access == AS_public) 1490 return AR_accessible; 1491 1492 CXXRecordDecl *BaseD, *DerivedD; 1493 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 1494 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 1495 1496 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 1497 Path.Access); 1498 if (DiagID) 1499 Entity.setDiag(DiagID) << Derived << Base; 1500 1501 if (ForceUnprivileged) { 1502 switch (CheckEffectiveAccess(*this, EffectiveContext(), 1503 AccessLoc, Entity)) { 1504 case ::AR_accessible: return Sema::AR_accessible; 1505 case ::AR_inaccessible: return Sema::AR_inaccessible; 1506 case ::AR_dependent: return Sema::AR_dependent; 1507 } 1508 llvm_unreachable("unexpected result from CheckEffectiveAccess"); 1509 } 1510 return CheckAccess(*this, AccessLoc, Entity); 1511} 1512 1513/// Checks access to all the declarations in the given result set. 1514void Sema::CheckLookupAccess(const LookupResult &R) { 1515 assert(getLangOptions().AccessControl 1516 && "performing access check without access control"); 1517 assert(R.getNamingClass() && "performing access check without naming class"); 1518 1519 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 1520 if (I.getAccess() != AS_public) { 1521 AccessTarget Entity(Context, AccessedEntity::Member, 1522 R.getNamingClass(), I.getPair(), 1523 R.getBaseObjectType()); 1524 Entity.setDiag(diag::err_access); 1525 1526 CheckAccess(*this, R.getNameLoc(), Entity); 1527 } 1528 } 1529} 1530 1531void Sema::ActOnStartSuppressingAccessChecks() { 1532 assert(!SuppressAccessChecking && 1533 "Tried to start access check suppression when already started."); 1534 SuppressAccessChecking = true; 1535} 1536 1537void Sema::ActOnStopSuppressingAccessChecks() { 1538 assert(SuppressAccessChecking && 1539 "Tried to stop access check suprression when already stopped."); 1540 SuppressAccessChecking = false; 1541} 1542