SemaAccess.cpp revision db73c684ba61fed4087af488e8610657ec638c17
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 "Sema.h" 15#include "Lookup.h" 16#include "clang/AST/ASTContext.h" 17#include "clang/AST/CXXInheritance.h" 18#include "clang/AST/DeclCXX.h" 19#include "clang/AST/DeclFriend.h" 20#include "clang/AST/DependentDiagnostic.h" 21#include "clang/AST/ExprCXX.h" 22 23using namespace clang; 24 25/// SetMemberAccessSpecifier - Set the access specifier of a member. 26/// Returns true on error (when the previous member decl access specifier 27/// is different from the new member decl access specifier). 28bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 29 NamedDecl *PrevMemberDecl, 30 AccessSpecifier LexicalAS) { 31 if (!PrevMemberDecl) { 32 // Use the lexical access specifier. 33 MemberDecl->setAccess(LexicalAS); 34 return false; 35 } 36 37 // C++ [class.access.spec]p3: When a member is redeclared its access 38 // specifier must be same as its initial declaration. 39 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 40 Diag(MemberDecl->getLocation(), 41 diag::err_class_redeclared_with_different_access) 42 << MemberDecl << LexicalAS; 43 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 44 << PrevMemberDecl << PrevMemberDecl->getAccess(); 45 46 MemberDecl->setAccess(LexicalAS); 47 return true; 48 } 49 50 MemberDecl->setAccess(PrevMemberDecl->getAccess()); 51 return false; 52} 53 54namespace { 55struct EffectiveContext { 56 EffectiveContext() : Inner(0), Dependent(false) {} 57 58 explicit EffectiveContext(DeclContext *DC) 59 : Inner(DC), 60 Dependent(DC->isDependentContext()) { 61 62 // C++ [class.access.nest]p1: 63 // A nested class is a member and as such has the same access 64 // rights as any other member. 65 // C++ [class.access]p2: 66 // A member of a class can also access all the names to which 67 // the class has access. A local class of a member function 68 // may access the same names that the member function itself 69 // may access. 70 // This almost implies that the privileges of nesting are transitive. 71 // Technically it says nothing about the local classes of non-member 72 // functions (which can gain privileges through friendship), but we 73 // take that as an oversight. 74 while (true) { 75 if (isa<CXXRecordDecl>(DC)) { 76 CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); 77 Records.push_back(Record); 78 DC = Record->getDeclContext(); 79 } else if (isa<FunctionDecl>(DC)) { 80 FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); 81 Functions.push_back(Function); 82 DC = Function->getDeclContext(); 83 } else if (DC->isFileContext()) { 84 break; 85 } else { 86 DC = DC->getParent(); 87 } 88 } 89 } 90 91 bool isDependent() const { return Dependent; } 92 93 bool includesClass(const CXXRecordDecl *R) const { 94 R = R->getCanonicalDecl(); 95 return std::find(Records.begin(), Records.end(), R) 96 != Records.end(); 97 } 98 99 /// Retrieves the innermost "useful" context. Can be null if we're 100 /// doing access-control without privileges. 101 DeclContext *getInnerContext() const { 102 return Inner; 103 } 104 105 typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 106 107 DeclContext *Inner; 108 llvm::SmallVector<FunctionDecl*, 4> Functions; 109 llvm::SmallVector<CXXRecordDecl*, 4> Records; 110 bool Dependent; 111}; 112} 113 114static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 115 DeclContext *DC = D->getDeclContext(); 116 117 // This can only happen at top: enum decls only "publish" their 118 // immediate members. 119 if (isa<EnumDecl>(DC)) 120 DC = cast<EnumDecl>(DC)->getDeclContext(); 121 122 CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 123 while (DeclaringClass->isAnonymousStructOrUnion()) 124 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 125 return DeclaringClass; 126} 127 128static bool MightInstantiateTo(Sema &S, DeclContext *Context, 129 DeclContext *Friend) { 130 if (Friend == Context) 131 return true; 132 133 assert(!Friend->isDependentContext() && 134 "can't handle friends with dependent contexts here"); 135 136 if (!Context->isDependentContext()) 137 return false; 138 139 if (Friend->isFileContext()) 140 return false; 141 142 // TODO: this is very conservative 143 return true; 144} 145 146// Asks whether the type in 'context' can ever instantiate to the type 147// in 'friend'. 148static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 149 if (Friend == Context) 150 return true; 151 152 if (!Friend->isDependentType() && !Context->isDependentType()) 153 return false; 154 155 // TODO: this is very conservative. 156 return true; 157} 158 159static bool MightInstantiateTo(Sema &S, 160 FunctionDecl *Context, 161 FunctionDecl *Friend) { 162 if (Context->getDeclName() != Friend->getDeclName()) 163 return false; 164 165 if (!MightInstantiateTo(S, 166 Context->getDeclContext(), 167 Friend->getDeclContext())) 168 return false; 169 170 CanQual<FunctionProtoType> FriendTy 171 = S.Context.getCanonicalType(Friend->getType()) 172 ->getAs<FunctionProtoType>(); 173 CanQual<FunctionProtoType> ContextTy 174 = S.Context.getCanonicalType(Context->getType()) 175 ->getAs<FunctionProtoType>(); 176 177 // There isn't any way that I know of to add qualifiers 178 // during instantiation. 179 if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 180 return false; 181 182 if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) 183 return false; 184 185 if (!MightInstantiateTo(S, 186 ContextTy->getResultType(), 187 FriendTy->getResultType())) 188 return false; 189 190 for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) 191 if (!MightInstantiateTo(S, 192 ContextTy->getArgType(I), 193 FriendTy->getArgType(I))) 194 return false; 195 196 return true; 197} 198 199static bool MightInstantiateTo(Sema &S, 200 FunctionTemplateDecl *Context, 201 FunctionTemplateDecl *Friend) { 202 return MightInstantiateTo(S, 203 Context->getTemplatedDecl(), 204 Friend->getTemplatedDecl()); 205} 206 207static Sema::AccessResult MatchesFriend(Sema &S, 208 const EffectiveContext &EC, 209 const CXXRecordDecl *Friend) { 210 if (EC.includesClass(Friend)) 211 return Sema::AR_accessible; 212 213 if (EC.isDependent()) { 214 CanQualType FriendTy 215 = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); 216 217 for (EffectiveContext::record_iterator 218 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 219 CanQualType ContextTy 220 = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); 221 if (MightInstantiateTo(S, ContextTy, FriendTy)) 222 return Sema::AR_dependent; 223 } 224 } 225 226 return Sema::AR_inaccessible; 227} 228 229static Sema::AccessResult MatchesFriend(Sema &S, 230 const EffectiveContext &EC, 231 CanQualType Friend) { 232 if (const RecordType *RT = Friend->getAs<RecordType>()) 233 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 234 235 // TODO: we can do better than this 236 if (Friend->isDependentType()) 237 return Sema::AR_dependent; 238 239 return Sema::AR_inaccessible; 240} 241 242/// Determines whether the given friend class template matches 243/// anything in the effective context. 244static Sema::AccessResult MatchesFriend(Sema &S, 245 const EffectiveContext &EC, 246 ClassTemplateDecl *Friend) { 247 Sema::AccessResult OnFailure = Sema::AR_inaccessible; 248 249 // Check whether the friend is the template of a class in the 250 // context chain. 251 for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator 252 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 253 CXXRecordDecl *Record = *I; 254 255 // Figure out whether the current class has a template: 256 ClassTemplateDecl *CTD; 257 258 // A specialization of the template... 259 if (isa<ClassTemplateSpecializationDecl>(Record)) { 260 CTD = cast<ClassTemplateSpecializationDecl>(Record) 261 ->getSpecializedTemplate(); 262 263 // ... or the template pattern itself. 264 } else { 265 CTD = Record->getDescribedClassTemplate(); 266 if (!CTD) continue; 267 } 268 269 // It's a match. 270 if (Friend == CTD->getCanonicalDecl()) 271 return Sema::AR_accessible; 272 273 // If the context isn't dependent, it can't be a dependent match. 274 if (!EC.isDependent()) 275 continue; 276 277 // If the template names don't match, it can't be a dependent 278 // match. This isn't true in C++0x because of template aliases. 279 if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName()) 280 continue; 281 282 // If the class's context can't instantiate to the friend's 283 // context, it can't be a dependent match. 284 if (!MightInstantiateTo(S, CTD->getDeclContext(), 285 Friend->getDeclContext())) 286 continue; 287 288 // Otherwise, it's a dependent match. 289 OnFailure = Sema::AR_dependent; 290 } 291 292 return OnFailure; 293} 294 295/// Determines whether the given friend function matches anything in 296/// the effective context. 297static Sema::AccessResult MatchesFriend(Sema &S, 298 const EffectiveContext &EC, 299 FunctionDecl *Friend) { 300 Sema::AccessResult OnFailure = Sema::AR_inaccessible; 301 302 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 303 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 304 if (Friend == *I) 305 return Sema::AR_accessible; 306 307 if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 308 OnFailure = Sema::AR_dependent; 309 } 310 311 return OnFailure; 312} 313 314/// Determines whether the given friend function template matches 315/// anything in the effective context. 316static Sema::AccessResult MatchesFriend(Sema &S, 317 const EffectiveContext &EC, 318 FunctionTemplateDecl *Friend) { 319 if (EC.Functions.empty()) return Sema::AR_inaccessible; 320 321 Sema::AccessResult OnFailure = Sema::AR_inaccessible; 322 323 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 324 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 325 326 FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 327 if (!FTD) 328 FTD = (*I)->getDescribedFunctionTemplate(); 329 if (!FTD) 330 continue; 331 332 FTD = FTD->getCanonicalDecl(); 333 334 if (Friend == FTD) 335 return Sema::AR_accessible; 336 337 if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 338 OnFailure = Sema::AR_dependent; 339 } 340 341 return OnFailure; 342} 343 344/// Determines whether the given friend declaration matches anything 345/// in the effective context. 346static Sema::AccessResult MatchesFriend(Sema &S, 347 const EffectiveContext &EC, 348 FriendDecl *FriendD) { 349 if (TypeSourceInfo *T = FriendD->getFriendType()) 350 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 351 352 NamedDecl *Friend 353 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 354 355 // FIXME: declarations with dependent or templated scope. 356 357 if (isa<ClassTemplateDecl>(Friend)) 358 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 359 360 if (isa<FunctionTemplateDecl>(Friend)) 361 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 362 363 if (isa<CXXRecordDecl>(Friend)) 364 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 365 366 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 367 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 368} 369 370static Sema::AccessResult GetFriendKind(Sema &S, 371 const EffectiveContext &EC, 372 const CXXRecordDecl *Class) { 373 Sema::AccessResult OnFailure = Sema::AR_inaccessible; 374 375 // Okay, check friends. 376 for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 377 E = Class->friend_end(); I != E; ++I) { 378 FriendDecl *Friend = *I; 379 380 switch (MatchesFriend(S, EC, Friend)) { 381 case Sema::AR_accessible: 382 return Sema::AR_accessible; 383 384 case Sema::AR_inaccessible: 385 break; 386 387 case Sema::AR_dependent: 388 OnFailure = Sema::AR_dependent; 389 break; 390 391 case Sema::AR_delayed: 392 llvm_unreachable("cannot get delayed answer from MatchesFriend"); 393 } 394 } 395 396 // That's it, give up. 397 return OnFailure; 398} 399 400static Sema::AccessResult HasAccess(Sema &S, 401 const EffectiveContext &EC, 402 const CXXRecordDecl *NamingClass, 403 AccessSpecifier Access) { 404 assert(NamingClass->getCanonicalDecl() == NamingClass && 405 "declaration should be canonicalized before being passed here"); 406 407 if (Access == AS_public) return Sema::AR_accessible; 408 assert(Access == AS_private || Access == AS_protected); 409 410 for (EffectiveContext::record_iterator 411 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 412 // All the declarations in EC have been canonicalized, so pointer 413 // equality from this point on will work fine. 414 const CXXRecordDecl *ECRecord = *I; 415 416 // [B2] and [M2] 417 if (ECRecord == NamingClass) 418 return Sema::AR_accessible; 419 420 // [B3] and [M3] 421 if (Access == AS_protected && 422 ECRecord->isDerivedFrom(const_cast<CXXRecordDecl*>(NamingClass))) 423 return Sema::AR_accessible; 424 } 425 426 return GetFriendKind(S, EC, NamingClass); 427} 428 429/// Finds the best path from the naming class to the declaring class, 430/// taking friend declarations into account. 431/// 432/// C++0x [class.access.base]p5: 433/// A member m is accessible at the point R when named in class N if 434/// [M1] m as a member of N is public, or 435/// [M2] m as a member of N is private, and R occurs in a member or 436/// friend of class N, or 437/// [M3] m as a member of N is protected, and R occurs in a member or 438/// friend of class N, or in a member or friend of a class P 439/// derived from N, where m as a member of P is public, private, 440/// or protected, or 441/// [M4] there exists a base class B of N that is accessible at R, and 442/// m is accessible at R when named in class B. 443/// 444/// C++0x [class.access.base]p4: 445/// A base class B of N is accessible at R, if 446/// [B1] an invented public member of B would be a public member of N, or 447/// [B2] R occurs in a member or friend of class N, and an invented public 448/// member of B would be a private or protected member of N, or 449/// [B3] R occurs in a member or friend of a class P derived from N, and an 450/// invented public member of B would be a private or protected member 451/// of P, or 452/// [B4] there exists a class S such that B is a base class of S accessible 453/// at R and S is a base class of N accessible at R. 454/// 455/// Along a single inheritance path we can restate both of these 456/// iteratively: 457/// 458/// First, we note that M1-4 are equivalent to B1-4 if the member is 459/// treated as a notional base of its declaring class with inheritance 460/// access equivalent to the member's access. Therefore we need only 461/// ask whether a class B is accessible from a class N in context R. 462/// 463/// Let B_1 .. B_n be the inheritance path in question (i.e. where 464/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 465/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 466/// closest accessible base in the path: 467/// Access(a, b) = (* access on the base specifier from a to b *) 468/// Merge(a, forbidden) = forbidden 469/// Merge(a, private) = forbidden 470/// Merge(a, b) = min(a,b) 471/// Accessible(c, forbidden) = false 472/// Accessible(c, private) = (R is c) || IsFriend(c, R) 473/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 474/// Accessible(c, public) = true 475/// ACAB(n) = public 476/// ACAB(i) = 477/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 478/// if Accessible(B_i, AccessToBase) then public else AccessToBase 479/// 480/// B is an accessible base of N at R iff ACAB(1) = public. 481/// 482/// \param FinalAccess the access of the "final step", or AS_none if 483/// there is no final step. 484/// \return null if friendship is dependent 485static CXXBasePath *FindBestPath(Sema &S, 486 const EffectiveContext &EC, 487 CXXRecordDecl *Derived, 488 CXXRecordDecl *Base, 489 AccessSpecifier FinalAccess, 490 CXXBasePaths &Paths) { 491 // Derive the paths to the desired base. 492 bool isDerived = Derived->isDerivedFrom(Base, Paths); 493 assert(isDerived && "derived class not actually derived from base"); 494 (void) isDerived; 495 496 CXXBasePath *BestPath = 0; 497 498 assert(FinalAccess != AS_none && "forbidden access after declaring class"); 499 500 bool AnyDependent = false; 501 502 // Derive the friend-modified access along each path. 503 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 504 PI != PE; ++PI) { 505 506 // Walk through the path backwards. 507 AccessSpecifier PathAccess = FinalAccess; 508 CXXBasePath::iterator I = PI->end(), E = PI->begin(); 509 while (I != E) { 510 --I; 511 512 assert(PathAccess != AS_none); 513 514 // If the declaration is a private member of a base class, there 515 // is no level of friendship in derived classes that can make it 516 // accessible. 517 if (PathAccess == AS_private) { 518 PathAccess = AS_none; 519 break; 520 } 521 522 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 523 PathAccess = std::max(PathAccess, BaseAccess); 524 switch (HasAccess(S, EC, I->Class, PathAccess)) { 525 case Sema::AR_inaccessible: break; 526 case Sema::AR_accessible: PathAccess = AS_public; break; 527 case Sema::AR_dependent: 528 AnyDependent = true; 529 goto Next; 530 case Sema::AR_delayed: 531 llvm_unreachable("friend resolution is never delayed"); break; 532 } 533 } 534 535 // Note that we modify the path's Access field to the 536 // friend-modified access. 537 if (BestPath == 0 || PathAccess < BestPath->Access) { 538 BestPath = &*PI; 539 BestPath->Access = PathAccess; 540 541 // Short-circuit if we found a public path. 542 if (BestPath->Access == AS_public) 543 return BestPath; 544 } 545 546 Next: ; 547 } 548 549 assert((!BestPath || BestPath->Access != AS_public) && 550 "fell out of loop with public path"); 551 552 // We didn't find a public path, but at least one path was subject 553 // to dependent friendship, so delay the check. 554 if (AnyDependent) 555 return 0; 556 557 return BestPath; 558} 559 560/// Diagnose the path which caused the given declaration or base class 561/// to become inaccessible. 562static void DiagnoseAccessPath(Sema &S, 563 const EffectiveContext &EC, 564 const Sema::AccessedEntity &Entity) { 565 AccessSpecifier Access = Entity.getAccess(); 566 CXXRecordDecl *NamingClass = Entity.getNamingClass(); 567 NamingClass = NamingClass->getCanonicalDecl(); 568 569 NamedDecl *D; 570 CXXRecordDecl *DeclaringClass; 571 if (Entity.isMemberAccess()) { 572 D = Entity.getTargetDecl(); 573 DeclaringClass = FindDeclaringClass(D); 574 } else { 575 D = 0; 576 DeclaringClass = Entity.getBaseClass(); 577 } 578 DeclaringClass = DeclaringClass->getCanonicalDecl(); 579 580 // Easy case: the decl's natural access determined its path access. 581 // We have to check against AS_private here in case Access is AS_none, 582 // indicating a non-public member of a private base class. 583 if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { 584 switch (HasAccess(S, EC, DeclaringClass, D->getAccess())) { 585 case Sema::AR_inaccessible: { 586 S.Diag(D->getLocation(), diag::note_access_natural) 587 << (unsigned) (Access == AS_protected) 588 << /*FIXME: not implicitly*/ 0; 589 return; 590 } 591 592 case Sema::AR_accessible: break; 593 594 case Sema::AR_dependent: 595 case Sema::AR_delayed: 596 llvm_unreachable("dependent/delayed not allowed"); 597 return; 598 } 599 } 600 601 CXXBasePaths Paths; 602 CXXBasePath &Path = *FindBestPath(S, EC, NamingClass, DeclaringClass, 603 AS_public, Paths); 604 605 CXXBasePath::iterator I = Path.end(), E = Path.begin(); 606 while (I != E) { 607 --I; 608 609 const CXXBaseSpecifier *BS = I->Base; 610 AccessSpecifier BaseAccess = BS->getAccessSpecifier(); 611 612 // If this is public inheritance, or the derived class is a friend, 613 // skip this step. 614 if (BaseAccess == AS_public) 615 continue; 616 617 switch (GetFriendKind(S, EC, I->Class)) { 618 case Sema::AR_accessible: continue; 619 case Sema::AR_inaccessible: break; 620 621 case Sema::AR_dependent: 622 case Sema::AR_delayed: 623 llvm_unreachable("dependent friendship, should not be diagnosing"); 624 } 625 626 // Check whether this base specifier is the tighest point 627 // constraining access. We have to check against AS_private for 628 // the same reasons as above. 629 if (BaseAccess == AS_private || BaseAccess >= Access) { 630 631 // We're constrained by inheritance, but we want to say 632 // "declared private here" if we're diagnosing a hierarchy 633 // conversion and this is the final step. 634 unsigned diagnostic; 635 if (D) diagnostic = diag::note_access_constrained_by_path; 636 else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; 637 else diagnostic = diag::note_access_constrained_by_path; 638 639 S.Diag(BS->getSourceRange().getBegin(), diagnostic) 640 << BS->getSourceRange() 641 << (BaseAccess == AS_protected) 642 << (BS->getAccessSpecifierAsWritten() == AS_none); 643 return; 644 } 645 } 646 647 llvm_unreachable("access not apparently constrained by path"); 648} 649 650static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 651 const EffectiveContext &EC, 652 const Sema::AccessedEntity &Entity) { 653 const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 654 NamedDecl *D; 655 const CXXRecordDecl *DeclaringClass; 656 if (Entity.isMemberAccess()) { 657 D = Entity.getTargetDecl(); 658 DeclaringClass = FindDeclaringClass(D); 659 } else { 660 D = 0; 661 DeclaringClass = Entity.getBaseClass(); 662 } 663 664 S.Diag(Loc, Entity.getDiag()) 665 << (Entity.getAccess() == AS_protected) 666 << (D ? D->getDeclName() : DeclarationName()) 667 << S.Context.getTypeDeclType(NamingClass) 668 << S.Context.getTypeDeclType(DeclaringClass); 669 DiagnoseAccessPath(S, EC, Entity); 670} 671 672/// Determines whether the accessed entity is accessible. Public members 673/// have been weeded out by this point. 674static Sema::AccessResult IsAccessible(Sema &S, 675 const EffectiveContext &EC, 676 const Sema::AccessedEntity &Entity) { 677 // Determine the actual naming class. 678 CXXRecordDecl *NamingClass = Entity.getNamingClass(); 679 while (NamingClass->isAnonymousStructOrUnion()) 680 NamingClass = cast<CXXRecordDecl>(NamingClass->getParent()); 681 NamingClass = NamingClass->getCanonicalDecl(); 682 683 AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 684 assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 685 686 // Before we try to recalculate access paths, try to white-list 687 // accesses which just trade in on the final step, i.e. accesses 688 // which don't require [M4] or [B4]. These are by far the most 689 // common forms of access. 690 if (UnprivilegedAccess != AS_none) { 691 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess)) { 692 case Sema::AR_dependent: 693 // This is actually an interesting policy decision. We don't 694 // *have* to delay immediately here: we can do the full access 695 // calculation in the hope that friendship on some intermediate 696 // class will make the declaration accessible non-dependently. 697 // But that's not cheap, and odds are very good (note: assertion 698 // made without data) that the friend declaration will determine 699 // access. 700 return Sema::AR_dependent; 701 702 case Sema::AR_accessible: return Sema::AR_accessible; 703 case Sema::AR_inaccessible: break; 704 case Sema::AR_delayed: 705 llvm_unreachable("friendship never subject to contextual delay"); 706 } 707 } 708 709 // Determine the declaring class. 710 CXXRecordDecl *DeclaringClass; 711 if (Entity.isMemberAccess()) { 712 DeclaringClass = FindDeclaringClass(Entity.getTargetDecl()); 713 } else { 714 DeclaringClass = Entity.getBaseClass(); 715 } 716 DeclaringClass = DeclaringClass->getCanonicalDecl(); 717 718 // We lower member accesses to base accesses by pretending that the 719 // member is a base class of its declaring class. 720 AccessSpecifier FinalAccess; 721 722 if (Entity.isMemberAccess()) { 723 // Determine if the declaration is accessible from EC when named 724 // in its declaring class. 725 NamedDecl *Target = Entity.getTargetDecl(); 726 727 FinalAccess = Target->getAccess(); 728 switch (HasAccess(S, EC, DeclaringClass, FinalAccess)) { 729 case Sema::AR_accessible: FinalAccess = AS_public; break; 730 case Sema::AR_inaccessible: break; 731 case Sema::AR_dependent: return Sema::AR_dependent; // see above 732 case Sema::AR_delayed: llvm_unreachable("friend status is never delayed"); 733 } 734 735 if (DeclaringClass == NamingClass) 736 return (FinalAccess == AS_public 737 ? Sema::AR_accessible 738 : Sema::AR_inaccessible); 739 } else { 740 FinalAccess = AS_public; 741 } 742 743 assert(DeclaringClass != NamingClass); 744 745 // Append the declaration's access if applicable. 746 CXXBasePaths Paths; 747 CXXBasePath *Path = FindBestPath(S, EC, NamingClass, DeclaringClass, 748 FinalAccess, Paths); 749 if (!Path) 750 return Sema::AR_dependent; 751 752 assert(Path->Access <= UnprivilegedAccess && 753 "access along best path worse than direct?"); 754 if (Path->Access == AS_public) 755 return Sema::AR_accessible; 756 return Sema::AR_inaccessible; 757} 758 759static void DelayAccess(Sema &S, 760 const EffectiveContext &EC, 761 SourceLocation Loc, 762 const Sema::AccessedEntity &Entity) { 763 assert(EC.isDependent() && "delaying non-dependent access"); 764 DeclContext *DC = EC.getInnerContext(); 765 assert(DC->isDependentContext() && "delaying non-dependent access"); 766 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 767 Loc, 768 Entity.isMemberAccess(), 769 Entity.getAccess(), 770 Entity.getTargetDecl(), 771 Entity.getNamingClass(), 772 Entity.getDiag()); 773} 774 775/// Checks access to an entity from the given effective context. 776static Sema::AccessResult CheckEffectiveAccess(Sema &S, 777 const EffectiveContext &EC, 778 SourceLocation Loc, 779 const Sema::AccessedEntity &Entity) { 780 assert(Entity.getAccess() != AS_public && "called for public access!"); 781 782 switch (IsAccessible(S, EC, Entity)) { 783 case Sema::AR_dependent: 784 DelayAccess(S, EC, Loc, Entity); 785 return Sema::AR_dependent; 786 787 case Sema::AR_delayed: 788 llvm_unreachable("IsAccessible cannot contextually delay"); 789 790 case Sema::AR_inaccessible: 791 if (!Entity.isQuiet()) 792 DiagnoseBadAccess(S, Loc, EC, Entity); 793 return Sema::AR_inaccessible; 794 795 case Sema::AR_accessible: 796 break; 797 } 798 799 // We only consider the natural access of the declaration when 800 // deciding whether to do the protected check. 801 if (Entity.isMemberAccess() && Entity.getAccess() == AS_protected) { 802 NamedDecl *D = Entity.getTargetDecl(); 803 if (isa<FieldDecl>(D) || 804 (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())) { 805 // FIXME: implement [class.protected] 806 } 807 } 808 809 return Sema::AR_accessible; 810} 811 812static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 813 const Sema::AccessedEntity &Entity) { 814 // If the access path is public, it's accessible everywhere. 815 if (Entity.getAccess() == AS_public) 816 return Sema::AR_accessible; 817 818 // If we're currently parsing a top-level declaration, delay 819 // diagnostics. This is the only case where parsing a declaration 820 // can actually change our effective context for the purposes of 821 // access control. 822 if (S.CurContext->isFileContext() && S.ParsingDeclDepth) { 823 S.DelayedDiagnostics.push_back( 824 Sema::DelayedDiagnostic::makeAccess(Loc, Entity)); 825 return Sema::AR_delayed; 826 } 827 828 return CheckEffectiveAccess(S, EffectiveContext(S.CurContext), 829 Loc, Entity); 830} 831 832void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) { 833 // Pretend we did this from the context of the newly-parsed 834 // declaration. 835 EffectiveContext EC(Ctx->getDeclContext()); 836 837 if (CheckEffectiveAccess(*this, EC, DD.Loc, DD.getAccessData())) 838 DD.Triggered = true; 839} 840 841void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 842 const MultiLevelTemplateArgumentList &TemplateArgs) { 843 SourceLocation Loc = DD.getAccessLoc(); 844 AccessSpecifier Access = DD.getAccess(); 845 846 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 847 TemplateArgs); 848 if (!NamingD) return; 849 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 850 TemplateArgs); 851 if (!TargetD) return; 852 853 if (DD.isAccessToMember()) { 854 AccessedEntity Entity(Context, 855 AccessedEntity::Member, 856 cast<CXXRecordDecl>(NamingD), 857 Access, 858 cast<NamedDecl>(TargetD)); 859 Entity.setDiag(DD.getDiagnostic()); 860 CheckAccess(*this, Loc, Entity); 861 } else { 862 AccessedEntity Entity(Context, 863 AccessedEntity::Base, 864 cast<CXXRecordDecl>(TargetD), 865 cast<CXXRecordDecl>(NamingD), 866 Access); 867 Entity.setDiag(DD.getDiagnostic()); 868 CheckAccess(*this, Loc, Entity); 869 } 870} 871 872Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 873 DeclAccessPair Found) { 874 if (!getLangOptions().AccessControl || 875 !E->getNamingClass() || 876 Found.getAccess() == AS_public) 877 return AR_accessible; 878 879 AccessedEntity Entity(Context, AccessedEntity::Member, E->getNamingClass(), 880 Found); 881 Entity.setDiag(diag::err_access) << E->getSourceRange(); 882 883 return CheckAccess(*this, E->getNameLoc(), Entity); 884} 885 886/// Perform access-control checking on a previously-unresolved member 887/// access which has now been resolved to a member. 888Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 889 DeclAccessPair Found) { 890 if (!getLangOptions().AccessControl || 891 Found.getAccess() == AS_public) 892 return AR_accessible; 893 894 AccessedEntity Entity(Context, AccessedEntity::Member, E->getNamingClass(), 895 Found); 896 Entity.setDiag(diag::err_access) << E->getSourceRange(); 897 898 return CheckAccess(*this, E->getMemberLoc(), Entity); 899} 900 901Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 902 CXXDestructorDecl *Dtor, 903 const PartialDiagnostic &PDiag) { 904 if (!getLangOptions().AccessControl) 905 return AR_accessible; 906 907 // There's never a path involved when checking implicit destructor access. 908 AccessSpecifier Access = Dtor->getAccess(); 909 if (Access == AS_public) 910 return AR_accessible; 911 912 CXXRecordDecl *NamingClass = Dtor->getParent(); 913 AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, 914 DeclAccessPair::make(Dtor, Access)); 915 Entity.setDiag(PDiag); // TODO: avoid copy 916 917 return CheckAccess(*this, Loc, Entity); 918} 919 920/// Checks access to a constructor. 921Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 922 CXXConstructorDecl *Constructor, 923 AccessSpecifier Access) { 924 if (!getLangOptions().AccessControl || 925 Access == AS_public) 926 return AR_accessible; 927 928 CXXRecordDecl *NamingClass = Constructor->getParent(); 929 AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, 930 DeclAccessPair::make(Constructor, Access)); 931 Entity.setDiag(diag::err_access_ctor); 932 933 return CheckAccess(*this, UseLoc, Entity); 934} 935 936/// Checks direct (i.e. non-inherited) access to an arbitrary class 937/// member. 938Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, 939 NamedDecl *Target, 940 const PartialDiagnostic &Diag) { 941 AccessSpecifier Access = Target->getAccess(); 942 if (!getLangOptions().AccessControl || 943 Access == AS_public) 944 return AR_accessible; 945 946 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); 947 AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, 948 DeclAccessPair::make(Target, Access)); 949 Entity.setDiag(Diag); 950 return CheckAccess(*this, UseLoc, Entity); 951} 952 953 954/// Checks access to an overloaded operator new or delete. 955Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 956 SourceRange PlacementRange, 957 CXXRecordDecl *NamingClass, 958 DeclAccessPair Found) { 959 if (!getLangOptions().AccessControl || 960 !NamingClass || 961 Found.getAccess() == AS_public) 962 return AR_accessible; 963 964 AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found); 965 Entity.setDiag(diag::err_access) 966 << PlacementRange; 967 968 return CheckAccess(*this, OpLoc, Entity); 969} 970 971/// Checks access to an overloaded member operator, including 972/// conversion operators. 973Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 974 Expr *ObjectExpr, 975 Expr *ArgExpr, 976 DeclAccessPair Found) { 977 if (!getLangOptions().AccessControl || 978 Found.getAccess() == AS_public) 979 return AR_accessible; 980 981 const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); 982 assert(RT && "found member operator but object expr not of record type"); 983 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 984 985 AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found); 986 Entity.setDiag(diag::err_access) 987 << ObjectExpr->getSourceRange() 988 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 989 990 return CheckAccess(*this, OpLoc, Entity); 991} 992 993Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 994 DeclAccessPair Found) { 995 if (!getLangOptions().AccessControl || 996 Found.getAccess() == AS_none || 997 Found.getAccess() == AS_public) 998 return AR_accessible; 999 1000 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer(); 1001 NestedNameSpecifier *Qualifier = Ovl->getQualifier(); 1002 assert(Qualifier && "address of overloaded member without qualifier"); 1003 1004 CXXScopeSpec SS; 1005 SS.setScopeRep(Qualifier); 1006 SS.setRange(Ovl->getQualifierRange()); 1007 DeclContext *DC = computeDeclContext(SS); 1008 assert(DC && DC->isRecord() && "scope did not resolve to record"); 1009 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(DC); 1010 1011 AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found); 1012 Entity.setDiag(diag::err_access) 1013 << Ovl->getSourceRange(); 1014 1015 return CheckAccess(*this, Ovl->getNameLoc(), Entity); 1016} 1017 1018 1019/// Checks access for a hierarchy conversion. 1020/// 1021/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) 1022/// or a derived-to-base conversion (false) 1023/// \param ForceCheck true if this check should be performed even if access 1024/// control is disabled; some things rely on this for semantics 1025/// \param ForceUnprivileged true if this check should proceed as if the 1026/// context had no special privileges 1027/// \param ADK controls the kind of diagnostics that are used 1028Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 1029 QualType Base, 1030 QualType Derived, 1031 const CXXBasePath &Path, 1032 unsigned DiagID, 1033 bool ForceCheck, 1034 bool ForceUnprivileged) { 1035 if (!ForceCheck && !getLangOptions().AccessControl) 1036 return AR_accessible; 1037 1038 if (Path.Access == AS_public) 1039 return AR_accessible; 1040 1041 CXXRecordDecl *BaseD, *DerivedD; 1042 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 1043 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 1044 1045 AccessedEntity Entity(Context, AccessedEntity::Base, BaseD, DerivedD, 1046 Path.Access); 1047 if (DiagID) 1048 Entity.setDiag(DiagID) << Derived << Base; 1049 1050 if (ForceUnprivileged) 1051 return CheckEffectiveAccess(*this, EffectiveContext(), AccessLoc, Entity); 1052 return CheckAccess(*this, AccessLoc, Entity); 1053} 1054 1055/// Checks access to all the declarations in the given result set. 1056void Sema::CheckLookupAccess(const LookupResult &R) { 1057 assert(getLangOptions().AccessControl 1058 && "performing access check without access control"); 1059 assert(R.getNamingClass() && "performing access check without naming class"); 1060 1061 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 1062 if (I.getAccess() != AS_public) { 1063 AccessedEntity Entity(Context, AccessedEntity::Member, 1064 R.getNamingClass(), 1065 I.getPair()); 1066 Entity.setDiag(diag::err_access); 1067 1068 CheckAccess(*this, R.getNameLoc(), Entity); 1069 } 1070 } 1071} 1072