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