clang API Documentation
00001 //===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file provides Sema routines for C++ access control semantics. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/Sema/SemaInternal.h" 00015 #include "clang/Sema/DelayedDiagnostic.h" 00016 #include "clang/Sema/Initialization.h" 00017 #include "clang/Sema/Lookup.h" 00018 #include "clang/AST/ASTContext.h" 00019 #include "clang/AST/CXXInheritance.h" 00020 #include "clang/AST/DeclCXX.h" 00021 #include "clang/AST/DeclFriend.h" 00022 #include "clang/AST/DeclObjC.h" 00023 #include "clang/AST/DependentDiagnostic.h" 00024 #include "clang/AST/ExprCXX.h" 00025 00026 using namespace clang; 00027 using namespace sema; 00028 00029 /// A copy of Sema's enum without AR_delayed. 00030 enum AccessResult { 00031 AR_accessible, 00032 AR_inaccessible, 00033 AR_dependent 00034 }; 00035 00036 /// SetMemberAccessSpecifier - Set the access specifier of a member. 00037 /// Returns true on error (when the previous member decl access specifier 00038 /// is different from the new member decl access specifier). 00039 bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 00040 NamedDecl *PrevMemberDecl, 00041 AccessSpecifier LexicalAS) { 00042 if (!PrevMemberDecl) { 00043 // Use the lexical access specifier. 00044 MemberDecl->setAccess(LexicalAS); 00045 return false; 00046 } 00047 00048 // C++ [class.access.spec]p3: When a member is redeclared its access 00049 // specifier must be same as its initial declaration. 00050 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 00051 Diag(MemberDecl->getLocation(), 00052 diag::err_class_redeclared_with_different_access) 00053 << MemberDecl << LexicalAS; 00054 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 00055 << PrevMemberDecl << PrevMemberDecl->getAccess(); 00056 00057 MemberDecl->setAccess(LexicalAS); 00058 return true; 00059 } 00060 00061 MemberDecl->setAccess(PrevMemberDecl->getAccess()); 00062 return false; 00063 } 00064 00065 static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 00066 DeclContext *DC = D->getDeclContext(); 00067 00068 // This can only happen at top: enum decls only "publish" their 00069 // immediate members. 00070 if (isa<EnumDecl>(DC)) 00071 DC = cast<EnumDecl>(DC)->getDeclContext(); 00072 00073 CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 00074 while (DeclaringClass->isAnonymousStructOrUnion()) 00075 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 00076 return DeclaringClass; 00077 } 00078 00079 namespace { 00080 struct EffectiveContext { 00081 EffectiveContext() : Inner(0), Dependent(false) {} 00082 00083 explicit EffectiveContext(DeclContext *DC) 00084 : Inner(DC), 00085 Dependent(DC->isDependentContext()) { 00086 00087 // C++ [class.access.nest]p1: 00088 // A nested class is a member and as such has the same access 00089 // rights as any other member. 00090 // C++ [class.access]p2: 00091 // A member of a class can also access all the names to which 00092 // the class has access. A local class of a member function 00093 // may access the same names that the member function itself 00094 // may access. 00095 // This almost implies that the privileges of nesting are transitive. 00096 // Technically it says nothing about the local classes of non-member 00097 // functions (which can gain privileges through friendship), but we 00098 // take that as an oversight. 00099 while (true) { 00100 if (isa<CXXRecordDecl>(DC)) { 00101 CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); 00102 Records.push_back(Record); 00103 DC = Record->getDeclContext(); 00104 } else if (isa<FunctionDecl>(DC)) { 00105 FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); 00106 Functions.push_back(Function); 00107 00108 if (Function->getFriendObjectKind()) 00109 DC = Function->getLexicalDeclContext(); 00110 else 00111 DC = Function->getDeclContext(); 00112 } else if (DC->isFileContext()) { 00113 break; 00114 } else { 00115 DC = DC->getParent(); 00116 } 00117 } 00118 } 00119 00120 bool isDependent() const { return Dependent; } 00121 00122 bool includesClass(const CXXRecordDecl *R) const { 00123 R = R->getCanonicalDecl(); 00124 return std::find(Records.begin(), Records.end(), R) 00125 != Records.end(); 00126 } 00127 00128 /// Retrieves the innermost "useful" context. Can be null if we're 00129 /// doing access-control without privileges. 00130 DeclContext *getInnerContext() const { 00131 return Inner; 00132 } 00133 00134 typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 00135 00136 DeclContext *Inner; 00137 SmallVector<FunctionDecl*, 4> Functions; 00138 SmallVector<CXXRecordDecl*, 4> Records; 00139 bool Dependent; 00140 }; 00141 00142 /// Like sema::AccessedEntity, but kindly lets us scribble all over 00143 /// it. 00144 struct AccessTarget : public AccessedEntity { 00145 AccessTarget(const AccessedEntity &Entity) 00146 : AccessedEntity(Entity) { 00147 initialize(); 00148 } 00149 00150 AccessTarget(ASTContext &Context, 00151 MemberNonce _, 00152 CXXRecordDecl *NamingClass, 00153 DeclAccessPair FoundDecl, 00154 QualType BaseObjectType) 00155 : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) { 00156 initialize(); 00157 } 00158 00159 AccessTarget(ASTContext &Context, 00160 BaseNonce _, 00161 CXXRecordDecl *BaseClass, 00162 CXXRecordDecl *DerivedClass, 00163 AccessSpecifier Access) 00164 : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) { 00165 initialize(); 00166 } 00167 00168 bool isInstanceMember() const { 00169 return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember()); 00170 } 00171 00172 bool hasInstanceContext() const { 00173 return HasInstanceContext; 00174 } 00175 00176 class SavedInstanceContext { 00177 public: 00178 ~SavedInstanceContext() { 00179 Target.HasInstanceContext = Has; 00180 } 00181 00182 private: 00183 friend struct AccessTarget; 00184 explicit SavedInstanceContext(AccessTarget &Target) 00185 : Target(Target), Has(Target.HasInstanceContext) {} 00186 AccessTarget &Target; 00187 bool Has; 00188 }; 00189 00190 SavedInstanceContext saveInstanceContext() { 00191 return SavedInstanceContext(*this); 00192 } 00193 00194 void suppressInstanceContext() { 00195 HasInstanceContext = false; 00196 } 00197 00198 const CXXRecordDecl *resolveInstanceContext(Sema &S) const { 00199 assert(HasInstanceContext); 00200 if (CalculatedInstanceContext) 00201 return InstanceContext; 00202 00203 CalculatedInstanceContext = true; 00204 DeclContext *IC = S.computeDeclContext(getBaseObjectType()); 00205 InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0); 00206 return InstanceContext; 00207 } 00208 00209 const CXXRecordDecl *getDeclaringClass() const { 00210 return DeclaringClass; 00211 } 00212 00213 private: 00214 void initialize() { 00215 HasInstanceContext = (isMemberAccess() && 00216 !getBaseObjectType().isNull() && 00217 getTargetDecl()->isCXXInstanceMember()); 00218 CalculatedInstanceContext = false; 00219 InstanceContext = 0; 00220 00221 if (isMemberAccess()) 00222 DeclaringClass = FindDeclaringClass(getTargetDecl()); 00223 else 00224 DeclaringClass = getBaseClass(); 00225 DeclaringClass = DeclaringClass->getCanonicalDecl(); 00226 } 00227 00228 bool HasInstanceContext : 1; 00229 mutable bool CalculatedInstanceContext : 1; 00230 mutable const CXXRecordDecl *InstanceContext; 00231 const CXXRecordDecl *DeclaringClass; 00232 }; 00233 00234 } 00235 00236 /// Checks whether one class might instantiate to the other. 00237 static bool MightInstantiateTo(const CXXRecordDecl *From, 00238 const CXXRecordDecl *To) { 00239 // Declaration names are always preserved by instantiation. 00240 if (From->getDeclName() != To->getDeclName()) 00241 return false; 00242 00243 const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); 00244 const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); 00245 if (FromDC == ToDC) return true; 00246 if (FromDC->isFileContext() || ToDC->isFileContext()) return false; 00247 00248 // Be conservative. 00249 return true; 00250 } 00251 00252 /// Checks whether one class is derived from another, inclusively. 00253 /// Properly indicates when it couldn't be determined due to 00254 /// dependence. 00255 /// 00256 /// This should probably be donated to AST or at least Sema. 00257 static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, 00258 const CXXRecordDecl *Target) { 00259 assert(Derived->getCanonicalDecl() == Derived); 00260 assert(Target->getCanonicalDecl() == Target); 00261 00262 if (Derived == Target) return AR_accessible; 00263 00264 bool CheckDependent = Derived->isDependentContext(); 00265 if (CheckDependent && MightInstantiateTo(Derived, Target)) 00266 return AR_dependent; 00267 00268 AccessResult OnFailure = AR_inaccessible; 00269 SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack 00270 00271 while (true) { 00272 if (Derived->isDependentContext() && !Derived->hasDefinition()) 00273 return AR_dependent; 00274 00275 for (CXXRecordDecl::base_class_const_iterator 00276 I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { 00277 00278 const CXXRecordDecl *RD; 00279 00280 QualType T = I->getType(); 00281 if (const RecordType *RT = T->getAs<RecordType>()) { 00282 RD = cast<CXXRecordDecl>(RT->getDecl()); 00283 } else if (const InjectedClassNameType *IT 00284 = T->getAs<InjectedClassNameType>()) { 00285 RD = IT->getDecl(); 00286 } else { 00287 assert(T->isDependentType() && "non-dependent base wasn't a record?"); 00288 OnFailure = AR_dependent; 00289 continue; 00290 } 00291 00292 RD = RD->getCanonicalDecl(); 00293 if (RD == Target) return AR_accessible; 00294 if (CheckDependent && MightInstantiateTo(RD, Target)) 00295 OnFailure = AR_dependent; 00296 00297 Queue.push_back(RD); 00298 } 00299 00300 if (Queue.empty()) break; 00301 00302 Derived = Queue.back(); 00303 Queue.pop_back(); 00304 } 00305 00306 return OnFailure; 00307 } 00308 00309 00310 static bool MightInstantiateTo(Sema &S, DeclContext *Context, 00311 DeclContext *Friend) { 00312 if (Friend == Context) 00313 return true; 00314 00315 assert(!Friend->isDependentContext() && 00316 "can't handle friends with dependent contexts here"); 00317 00318 if (!Context->isDependentContext()) 00319 return false; 00320 00321 if (Friend->isFileContext()) 00322 return false; 00323 00324 // TODO: this is very conservative 00325 return true; 00326 } 00327 00328 // Asks whether the type in 'context' can ever instantiate to the type 00329 // in 'friend'. 00330 static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 00331 if (Friend == Context) 00332 return true; 00333 00334 if (!Friend->isDependentType() && !Context->isDependentType()) 00335 return false; 00336 00337 // TODO: this is very conservative. 00338 return true; 00339 } 00340 00341 static bool MightInstantiateTo(Sema &S, 00342 FunctionDecl *Context, 00343 FunctionDecl *Friend) { 00344 if (Context->getDeclName() != Friend->getDeclName()) 00345 return false; 00346 00347 if (!MightInstantiateTo(S, 00348 Context->getDeclContext(), 00349 Friend->getDeclContext())) 00350 return false; 00351 00352 CanQual<FunctionProtoType> FriendTy 00353 = S.Context.getCanonicalType(Friend->getType()) 00354 ->getAs<FunctionProtoType>(); 00355 CanQual<FunctionProtoType> ContextTy 00356 = S.Context.getCanonicalType(Context->getType()) 00357 ->getAs<FunctionProtoType>(); 00358 00359 // There isn't any way that I know of to add qualifiers 00360 // during instantiation. 00361 if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 00362 return false; 00363 00364 if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) 00365 return false; 00366 00367 if (!MightInstantiateTo(S, 00368 ContextTy->getResultType(), 00369 FriendTy->getResultType())) 00370 return false; 00371 00372 for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) 00373 if (!MightInstantiateTo(S, 00374 ContextTy->getArgType(I), 00375 FriendTy->getArgType(I))) 00376 return false; 00377 00378 return true; 00379 } 00380 00381 static bool MightInstantiateTo(Sema &S, 00382 FunctionTemplateDecl *Context, 00383 FunctionTemplateDecl *Friend) { 00384 return MightInstantiateTo(S, 00385 Context->getTemplatedDecl(), 00386 Friend->getTemplatedDecl()); 00387 } 00388 00389 static AccessResult MatchesFriend(Sema &S, 00390 const EffectiveContext &EC, 00391 const CXXRecordDecl *Friend) { 00392 if (EC.includesClass(Friend)) 00393 return AR_accessible; 00394 00395 if (EC.isDependent()) { 00396 CanQualType FriendTy 00397 = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); 00398 00399 for (EffectiveContext::record_iterator 00400 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 00401 CanQualType ContextTy 00402 = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); 00403 if (MightInstantiateTo(S, ContextTy, FriendTy)) 00404 return AR_dependent; 00405 } 00406 } 00407 00408 return AR_inaccessible; 00409 } 00410 00411 static AccessResult MatchesFriend(Sema &S, 00412 const EffectiveContext &EC, 00413 CanQualType Friend) { 00414 if (const RecordType *RT = Friend->getAs<RecordType>()) 00415 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 00416 00417 // TODO: we can do better than this 00418 if (Friend->isDependentType()) 00419 return AR_dependent; 00420 00421 return AR_inaccessible; 00422 } 00423 00424 /// Determines whether the given friend class template matches 00425 /// anything in the effective context. 00426 static AccessResult MatchesFriend(Sema &S, 00427 const EffectiveContext &EC, 00428 ClassTemplateDecl *Friend) { 00429 AccessResult OnFailure = AR_inaccessible; 00430 00431 // Check whether the friend is the template of a class in the 00432 // context chain. 00433 for (SmallVectorImpl<CXXRecordDecl*>::const_iterator 00434 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 00435 CXXRecordDecl *Record = *I; 00436 00437 // Figure out whether the current class has a template: 00438 ClassTemplateDecl *CTD; 00439 00440 // A specialization of the template... 00441 if (isa<ClassTemplateSpecializationDecl>(Record)) { 00442 CTD = cast<ClassTemplateSpecializationDecl>(Record) 00443 ->getSpecializedTemplate(); 00444 00445 // ... or the template pattern itself. 00446 } else { 00447 CTD = Record->getDescribedClassTemplate(); 00448 if (!CTD) continue; 00449 } 00450 00451 // It's a match. 00452 if (Friend == CTD->getCanonicalDecl()) 00453 return AR_accessible; 00454 00455 // If the context isn't dependent, it can't be a dependent match. 00456 if (!EC.isDependent()) 00457 continue; 00458 00459 // If the template names don't match, it can't be a dependent 00460 // match. 00461 if (CTD->getDeclName() != Friend->getDeclName()) 00462 continue; 00463 00464 // If the class's context can't instantiate to the friend's 00465 // context, it can't be a dependent match. 00466 if (!MightInstantiateTo(S, CTD->getDeclContext(), 00467 Friend->getDeclContext())) 00468 continue; 00469 00470 // Otherwise, it's a dependent match. 00471 OnFailure = AR_dependent; 00472 } 00473 00474 return OnFailure; 00475 } 00476 00477 /// Determines whether the given friend function matches anything in 00478 /// the effective context. 00479 static AccessResult MatchesFriend(Sema &S, 00480 const EffectiveContext &EC, 00481 FunctionDecl *Friend) { 00482 AccessResult OnFailure = AR_inaccessible; 00483 00484 for (SmallVectorImpl<FunctionDecl*>::const_iterator 00485 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 00486 if (Friend == *I) 00487 return AR_accessible; 00488 00489 if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 00490 OnFailure = AR_dependent; 00491 } 00492 00493 return OnFailure; 00494 } 00495 00496 /// Determines whether the given friend function template matches 00497 /// anything in the effective context. 00498 static AccessResult MatchesFriend(Sema &S, 00499 const EffectiveContext &EC, 00500 FunctionTemplateDecl *Friend) { 00501 if (EC.Functions.empty()) return AR_inaccessible; 00502 00503 AccessResult OnFailure = AR_inaccessible; 00504 00505 for (SmallVectorImpl<FunctionDecl*>::const_iterator 00506 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 00507 00508 FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 00509 if (!FTD) 00510 FTD = (*I)->getDescribedFunctionTemplate(); 00511 if (!FTD) 00512 continue; 00513 00514 FTD = FTD->getCanonicalDecl(); 00515 00516 if (Friend == FTD) 00517 return AR_accessible; 00518 00519 if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 00520 OnFailure = AR_dependent; 00521 } 00522 00523 return OnFailure; 00524 } 00525 00526 /// Determines whether the given friend declaration matches anything 00527 /// in the effective context. 00528 static AccessResult MatchesFriend(Sema &S, 00529 const EffectiveContext &EC, 00530 FriendDecl *FriendD) { 00531 // Whitelist accesses if there's an invalid or unsupported friend 00532 // declaration. 00533 if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) 00534 return AR_accessible; 00535 00536 if (TypeSourceInfo *T = FriendD->getFriendType()) 00537 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 00538 00539 NamedDecl *Friend 00540 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 00541 00542 // FIXME: declarations with dependent or templated scope. 00543 00544 if (isa<ClassTemplateDecl>(Friend)) 00545 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 00546 00547 if (isa<FunctionTemplateDecl>(Friend)) 00548 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 00549 00550 if (isa<CXXRecordDecl>(Friend)) 00551 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 00552 00553 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 00554 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 00555 } 00556 00557 static AccessResult GetFriendKind(Sema &S, 00558 const EffectiveContext &EC, 00559 const CXXRecordDecl *Class) { 00560 AccessResult OnFailure = AR_inaccessible; 00561 00562 // Okay, check friends. 00563 for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 00564 E = Class->friend_end(); I != E; ++I) { 00565 FriendDecl *Friend = *I; 00566 00567 switch (MatchesFriend(S, EC, Friend)) { 00568 case AR_accessible: 00569 return AR_accessible; 00570 00571 case AR_inaccessible: 00572 continue; 00573 00574 case AR_dependent: 00575 OnFailure = AR_dependent; 00576 break; 00577 } 00578 } 00579 00580 // That's it, give up. 00581 return OnFailure; 00582 } 00583 00584 namespace { 00585 00586 /// A helper class for checking for a friend which will grant access 00587 /// to a protected instance member. 00588 struct ProtectedFriendContext { 00589 Sema &S; 00590 const EffectiveContext &EC; 00591 const CXXRecordDecl *NamingClass; 00592 bool CheckDependent; 00593 bool EverDependent; 00594 00595 /// The path down to the current base class. 00596 SmallVector<const CXXRecordDecl*, 20> CurPath; 00597 00598 ProtectedFriendContext(Sema &S, const EffectiveContext &EC, 00599 const CXXRecordDecl *InstanceContext, 00600 const CXXRecordDecl *NamingClass) 00601 : S(S), EC(EC), NamingClass(NamingClass), 00602 CheckDependent(InstanceContext->isDependentContext() || 00603 NamingClass->isDependentContext()), 00604 EverDependent(false) {} 00605 00606 /// Check classes in the current path for friendship, starting at 00607 /// the given index. 00608 bool checkFriendshipAlongPath(unsigned I) { 00609 assert(I < CurPath.size()); 00610 for (unsigned E = CurPath.size(); I != E; ++I) { 00611 switch (GetFriendKind(S, EC, CurPath[I])) { 00612 case AR_accessible: return true; 00613 case AR_inaccessible: continue; 00614 case AR_dependent: EverDependent = true; continue; 00615 } 00616 } 00617 return false; 00618 } 00619 00620 /// Perform a search starting at the given class. 00621 /// 00622 /// PrivateDepth is the index of the last (least derived) class 00623 /// along the current path such that a notional public member of 00624 /// the final class in the path would have access in that class. 00625 bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { 00626 // If we ever reach the naming class, check the current path for 00627 // friendship. We can also stop recursing because we obviously 00628 // won't find the naming class there again. 00629 if (Cur == NamingClass) 00630 return checkFriendshipAlongPath(PrivateDepth); 00631 00632 if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) 00633 EverDependent = true; 00634 00635 // Recurse into the base classes. 00636 for (CXXRecordDecl::base_class_const_iterator 00637 I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) { 00638 00639 // If this is private inheritance, then a public member of the 00640 // base will not have any access in classes derived from Cur. 00641 unsigned BasePrivateDepth = PrivateDepth; 00642 if (I->getAccessSpecifier() == AS_private) 00643 BasePrivateDepth = CurPath.size() - 1; 00644 00645 const CXXRecordDecl *RD; 00646 00647 QualType T = I->getType(); 00648 if (const RecordType *RT = T->getAs<RecordType>()) { 00649 RD = cast<CXXRecordDecl>(RT->getDecl()); 00650 } else if (const InjectedClassNameType *IT 00651 = T->getAs<InjectedClassNameType>()) { 00652 RD = IT->getDecl(); 00653 } else { 00654 assert(T->isDependentType() && "non-dependent base wasn't a record?"); 00655 EverDependent = true; 00656 continue; 00657 } 00658 00659 // Recurse. We don't need to clean up if this returns true. 00660 CurPath.push_back(RD); 00661 if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) 00662 return true; 00663 CurPath.pop_back(); 00664 } 00665 00666 return false; 00667 } 00668 00669 bool findFriendship(const CXXRecordDecl *Cur) { 00670 assert(CurPath.empty()); 00671 CurPath.push_back(Cur); 00672 return findFriendship(Cur, 0); 00673 } 00674 }; 00675 } 00676 00677 /// Search for a class P that EC is a friend of, under the constraint 00678 /// InstanceContext <= P 00679 /// if InstanceContext exists, or else 00680 /// NamingClass <= P 00681 /// and with the additional restriction that a protected member of 00682 /// NamingClass would have some natural access in P, which implicitly 00683 /// imposes the constraint that P <= NamingClass. 00684 /// 00685 /// This isn't quite the condition laid out in the standard. 00686 /// Instead of saying that a notional protected member of NamingClass 00687 /// would have to have some natural access in P, it says the actual 00688 /// target has to have some natural access in P, which opens up the 00689 /// possibility that the target (which is not necessarily a member 00690 /// of NamingClass) might be more accessible along some path not 00691 /// passing through it. That's really a bad idea, though, because it 00692 /// introduces two problems: 00693 /// - Most importantly, it breaks encapsulation because you can 00694 /// access a forbidden base class's members by directly subclassing 00695 /// it elsewhere. 00696 /// - It also makes access substantially harder to compute because it 00697 /// breaks the hill-climbing algorithm: knowing that the target is 00698 /// accessible in some base class would no longer let you change 00699 /// the question solely to whether the base class is accessible, 00700 /// because the original target might have been more accessible 00701 /// because of crazy subclassing. 00702 /// So we don't implement that. 00703 static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, 00704 const CXXRecordDecl *InstanceContext, 00705 const CXXRecordDecl *NamingClass) { 00706 assert(InstanceContext == 0 || 00707 InstanceContext->getCanonicalDecl() == InstanceContext); 00708 assert(NamingClass->getCanonicalDecl() == NamingClass); 00709 00710 // If we don't have an instance context, our constraints give us 00711 // that NamingClass <= P <= NamingClass, i.e. P == NamingClass. 00712 // This is just the usual friendship check. 00713 if (!InstanceContext) return GetFriendKind(S, EC, NamingClass); 00714 00715 ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); 00716 if (PRC.findFriendship(InstanceContext)) return AR_accessible; 00717 if (PRC.EverDependent) return AR_dependent; 00718 return AR_inaccessible; 00719 } 00720 00721 static AccessResult HasAccess(Sema &S, 00722 const EffectiveContext &EC, 00723 const CXXRecordDecl *NamingClass, 00724 AccessSpecifier Access, 00725 const AccessTarget &Target) { 00726 assert(NamingClass->getCanonicalDecl() == NamingClass && 00727 "declaration should be canonicalized before being passed here"); 00728 00729 if (Access == AS_public) return AR_accessible; 00730 assert(Access == AS_private || Access == AS_protected); 00731 00732 AccessResult OnFailure = AR_inaccessible; 00733 00734 for (EffectiveContext::record_iterator 00735 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 00736 // All the declarations in EC have been canonicalized, so pointer 00737 // equality from this point on will work fine. 00738 const CXXRecordDecl *ECRecord = *I; 00739 00740 // [B2] and [M2] 00741 if (Access == AS_private) { 00742 if (ECRecord == NamingClass) 00743 return AR_accessible; 00744 00745 if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) 00746 OnFailure = AR_dependent; 00747 00748 // [B3] and [M3] 00749 } else { 00750 assert(Access == AS_protected); 00751 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 00752 case AR_accessible: break; 00753 case AR_inaccessible: continue; 00754 case AR_dependent: OnFailure = AR_dependent; continue; 00755 } 00756 00757 // C++ [class.protected]p1: 00758 // An additional access check beyond those described earlier in 00759 // [class.access] is applied when a non-static data member or 00760 // non-static member function is a protected member of its naming 00761 // class. As described earlier, access to a protected member is 00762 // granted because the reference occurs in a friend or member of 00763 // some class C. If the access is to form a pointer to member, 00764 // the nested-name-specifier shall name C or a class derived from 00765 // C. All other accesses involve a (possibly implicit) object 00766 // expression. In this case, the class of the object expression 00767 // shall be C or a class derived from C. 00768 // 00769 // We interpret this as a restriction on [M3]. 00770 00771 // In this part of the code, 'C' is just our context class ECRecord. 00772 00773 // These rules are different if we don't have an instance context. 00774 if (!Target.hasInstanceContext()) { 00775 // If it's not an instance member, these restrictions don't apply. 00776 if (!Target.isInstanceMember()) return AR_accessible; 00777 00778 // If it's an instance member, use the pointer-to-member rule 00779 // that the naming class has to be derived from the effective 00780 // context. 00781 00782 // Emulate a MSVC bug where the creation of pointer-to-member 00783 // to protected member of base class is allowed but only from 00784 // static member functions. 00785 if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty()) 00786 if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front())) 00787 if (MD->isStatic()) return AR_accessible; 00788 00789 // Despite the standard's confident wording, there is a case 00790 // where you can have an instance member that's neither in a 00791 // pointer-to-member expression nor in a member access: when 00792 // it names a field in an unevaluated context that can't be an 00793 // implicit member. Pending clarification, we just apply the 00794 // same naming-class restriction here. 00795 // FIXME: we're probably not correctly adding the 00796 // protected-member restriction when we retroactively convert 00797 // an expression to being evaluated. 00798 00799 // We know that ECRecord derives from NamingClass. The 00800 // restriction says to check whether NamingClass derives from 00801 // ECRecord, but that's not really necessary: two distinct 00802 // classes can't be recursively derived from each other. So 00803 // along this path, we just need to check whether the classes 00804 // are equal. 00805 if (NamingClass == ECRecord) return AR_accessible; 00806 00807 // Otherwise, this context class tells us nothing; on to the next. 00808 continue; 00809 } 00810 00811 assert(Target.isInstanceMember()); 00812 00813 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 00814 if (!InstanceContext) { 00815 OnFailure = AR_dependent; 00816 continue; 00817 } 00818 00819 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 00820 case AR_accessible: return AR_accessible; 00821 case AR_inaccessible: continue; 00822 case AR_dependent: OnFailure = AR_dependent; continue; 00823 } 00824 } 00825 } 00826 00827 // [M3] and [B3] say that, if the target is protected in N, we grant 00828 // access if the access occurs in a friend or member of some class P 00829 // that's a subclass of N and where the target has some natural 00830 // access in P. The 'member' aspect is easy to handle because P 00831 // would necessarily be one of the effective-context records, and we 00832 // address that above. The 'friend' aspect is completely ridiculous 00833 // to implement because there are no restrictions at all on P 00834 // *unless* the [class.protected] restriction applies. If it does, 00835 // however, we should ignore whether the naming class is a friend, 00836 // and instead rely on whether any potential P is a friend. 00837 if (Access == AS_protected && Target.isInstanceMember()) { 00838 // Compute the instance context if possible. 00839 const CXXRecordDecl *InstanceContext = 0; 00840 if (Target.hasInstanceContext()) { 00841 InstanceContext = Target.resolveInstanceContext(S); 00842 if (!InstanceContext) return AR_dependent; 00843 } 00844 00845 switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { 00846 case AR_accessible: return AR_accessible; 00847 case AR_inaccessible: return OnFailure; 00848 case AR_dependent: return AR_dependent; 00849 } 00850 llvm_unreachable("impossible friendship kind"); 00851 } 00852 00853 switch (GetFriendKind(S, EC, NamingClass)) { 00854 case AR_accessible: return AR_accessible; 00855 case AR_inaccessible: return OnFailure; 00856 case AR_dependent: return AR_dependent; 00857 } 00858 00859 // Silence bogus warnings 00860 llvm_unreachable("impossible friendship kind"); 00861 } 00862 00863 /// Finds the best path from the naming class to the declaring class, 00864 /// taking friend declarations into account. 00865 /// 00866 /// C++0x [class.access.base]p5: 00867 /// A member m is accessible at the point R when named in class N if 00868 /// [M1] m as a member of N is public, or 00869 /// [M2] m as a member of N is private, and R occurs in a member or 00870 /// friend of class N, or 00871 /// [M3] m as a member of N is protected, and R occurs in a member or 00872 /// friend of class N, or in a member or friend of a class P 00873 /// derived from N, where m as a member of P is public, private, 00874 /// or protected, or 00875 /// [M4] there exists a base class B of N that is accessible at R, and 00876 /// m is accessible at R when named in class B. 00877 /// 00878 /// C++0x [class.access.base]p4: 00879 /// A base class B of N is accessible at R, if 00880 /// [B1] an invented public member of B would be a public member of N, or 00881 /// [B2] R occurs in a member or friend of class N, and an invented public 00882 /// member of B would be a private or protected member of N, or 00883 /// [B3] R occurs in a member or friend of a class P derived from N, and an 00884 /// invented public member of B would be a private or protected member 00885 /// of P, or 00886 /// [B4] there exists a class S such that B is a base class of S accessible 00887 /// at R and S is a base class of N accessible at R. 00888 /// 00889 /// Along a single inheritance path we can restate both of these 00890 /// iteratively: 00891 /// 00892 /// First, we note that M1-4 are equivalent to B1-4 if the member is 00893 /// treated as a notional base of its declaring class with inheritance 00894 /// access equivalent to the member's access. Therefore we need only 00895 /// ask whether a class B is accessible from a class N in context R. 00896 /// 00897 /// Let B_1 .. B_n be the inheritance path in question (i.e. where 00898 /// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 00899 /// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 00900 /// closest accessible base in the path: 00901 /// Access(a, b) = (* access on the base specifier from a to b *) 00902 /// Merge(a, forbidden) = forbidden 00903 /// Merge(a, private) = forbidden 00904 /// Merge(a, b) = min(a,b) 00905 /// Accessible(c, forbidden) = false 00906 /// Accessible(c, private) = (R is c) || IsFriend(c, R) 00907 /// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 00908 /// Accessible(c, public) = true 00909 /// ACAB(n) = public 00910 /// ACAB(i) = 00911 /// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 00912 /// if Accessible(B_i, AccessToBase) then public else AccessToBase 00913 /// 00914 /// B is an accessible base of N at R iff ACAB(1) = public. 00915 /// 00916 /// \param FinalAccess the access of the "final step", or AS_public if 00917 /// there is no final step. 00918 /// \return null if friendship is dependent 00919 static CXXBasePath *FindBestPath(Sema &S, 00920 const EffectiveContext &EC, 00921 AccessTarget &Target, 00922 AccessSpecifier FinalAccess, 00923 CXXBasePaths &Paths) { 00924 // Derive the paths to the desired base. 00925 const CXXRecordDecl *Derived = Target.getNamingClass(); 00926 const CXXRecordDecl *Base = Target.getDeclaringClass(); 00927 00928 // FIXME: fail correctly when there are dependent paths. 00929 bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), 00930 Paths); 00931 assert(isDerived && "derived class not actually derived from base"); 00932 (void) isDerived; 00933 00934 CXXBasePath *BestPath = 0; 00935 00936 assert(FinalAccess != AS_none && "forbidden access after declaring class"); 00937 00938 bool AnyDependent = false; 00939 00940 // Derive the friend-modified access along each path. 00941 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 00942 PI != PE; ++PI) { 00943 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); 00944 00945 // Walk through the path backwards. 00946 AccessSpecifier PathAccess = FinalAccess; 00947 CXXBasePath::iterator I = PI->end(), E = PI->begin(); 00948 while (I != E) { 00949 --I; 00950 00951 assert(PathAccess != AS_none); 00952 00953 // If the declaration is a private member of a base class, there 00954 // is no level of friendship in derived classes that can make it 00955 // accessible. 00956 if (PathAccess == AS_private) { 00957 PathAccess = AS_none; 00958 break; 00959 } 00960 00961 const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); 00962 00963 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 00964 PathAccess = std::max(PathAccess, BaseAccess); 00965 00966 switch (HasAccess(S, EC, NC, PathAccess, Target)) { 00967 case AR_inaccessible: break; 00968 case AR_accessible: 00969 PathAccess = AS_public; 00970 00971 // Future tests are not against members and so do not have 00972 // instance context. 00973 Target.suppressInstanceContext(); 00974 break; 00975 case AR_dependent: 00976 AnyDependent = true; 00977 goto Next; 00978 } 00979 } 00980 00981 // Note that we modify the path's Access field to the 00982 // friend-modified access. 00983 if (BestPath == 0 || PathAccess < BestPath->Access) { 00984 BestPath = &*PI; 00985 BestPath->Access = PathAccess; 00986 00987 // Short-circuit if we found a public path. 00988 if (BestPath->Access == AS_public) 00989 return BestPath; 00990 } 00991 00992 Next: ; 00993 } 00994 00995 assert((!BestPath || BestPath->Access != AS_public) && 00996 "fell out of loop with public path"); 00997 00998 // We didn't find a public path, but at least one path was subject 00999 // to dependent friendship, so delay the check. 01000 if (AnyDependent) 01001 return 0; 01002 01003 return BestPath; 01004 } 01005 01006 /// Given that an entity has protected natural access, check whether 01007 /// access might be denied because of the protected member access 01008 /// restriction. 01009 /// 01010 /// \return true if a note was emitted 01011 static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, 01012 AccessTarget &Target) { 01013 // Only applies to instance accesses. 01014 if (!Target.isInstanceMember()) 01015 return false; 01016 01017 assert(Target.isMemberAccess()); 01018 01019 const CXXRecordDecl *NamingClass = Target.getNamingClass(); 01020 NamingClass = NamingClass->getCanonicalDecl(); 01021 01022 for (EffectiveContext::record_iterator 01023 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 01024 const CXXRecordDecl *ECRecord = *I; 01025 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 01026 case AR_accessible: break; 01027 case AR_inaccessible: continue; 01028 case AR_dependent: continue; 01029 } 01030 01031 // The effective context is a subclass of the declaring class. 01032 // Check whether the [class.protected] restriction is limiting 01033 // access. 01034 01035 // To get this exactly right, this might need to be checked more 01036 // holistically; it's not necessarily the case that gaining 01037 // access here would grant us access overall. 01038 01039 NamedDecl *D = Target.getTargetDecl(); 01040 01041 // If we don't have an instance context, [class.protected] says the 01042 // naming class has to equal the context class. 01043 if (!Target.hasInstanceContext()) { 01044 // If it does, the restriction doesn't apply. 01045 if (NamingClass == ECRecord) continue; 01046 01047 // TODO: it would be great to have a fixit here, since this is 01048 // such an obvious error. 01049 S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject) 01050 << S.Context.getTypeDeclType(ECRecord); 01051 return true; 01052 } 01053 01054 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 01055 assert(InstanceContext && "diagnosing dependent access"); 01056 01057 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 01058 case AR_accessible: continue; 01059 case AR_dependent: continue; 01060 case AR_inaccessible: 01061 break; 01062 } 01063 01064 // Okay, the restriction seems to be what's limiting us. 01065 01066 // Use a special diagnostic for constructors and destructors. 01067 if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) || 01068 (isa<FunctionTemplateDecl>(D) && 01069 isa<CXXConstructorDecl>( 01070 cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) { 01071 S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor) 01072 << isa<CXXDestructorDecl>(D); 01073 return true; 01074 } 01075 01076 // Otherwise, use the generic diagnostic. 01077 S.Diag(D->getLocation(), diag::note_access_protected_restricted_object) 01078 << S.Context.getTypeDeclType(ECRecord); 01079 return true; 01080 } 01081 01082 return false; 01083 } 01084 01085 /// Diagnose the path which caused the given declaration or base class 01086 /// to become inaccessible. 01087 static void DiagnoseAccessPath(Sema &S, 01088 const EffectiveContext &EC, 01089 AccessTarget &Entity) { 01090 AccessSpecifier Access = Entity.getAccess(); 01091 01092 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 01093 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 01094 01095 // Easy case: the decl's natural access determined its path access. 01096 // We have to check against AS_private here in case Access is AS_none, 01097 // indicating a non-public member of a private base class. 01098 if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { 01099 switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) { 01100 case AR_inaccessible: { 01101 if (Access == AS_protected && 01102 TryDiagnoseProtectedAccess(S, EC, Entity)) 01103 return; 01104 01105 // Find an original declaration. 01106 while (D->isOutOfLine()) { 01107 NamedDecl *PrevDecl = 0; 01108 if (VarDecl *VD = dyn_cast<VarDecl>(D)) 01109 PrevDecl = VD->getPreviousDecl(); 01110 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 01111 PrevDecl = FD->getPreviousDecl(); 01112 else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) 01113 PrevDecl = TND->getPreviousDecl(); 01114 else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 01115 if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) 01116 break; 01117 PrevDecl = TD->getPreviousDecl(); 01118 } 01119 if (!PrevDecl) break; 01120 D = PrevDecl; 01121 } 01122 01123 CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); 01124 Decl *ImmediateChild; 01125 if (D->getDeclContext() == DeclaringClass) 01126 ImmediateChild = D; 01127 else { 01128 DeclContext *DC = D->getDeclContext(); 01129 while (DC->getParent() != DeclaringClass) 01130 DC = DC->getParent(); 01131 ImmediateChild = cast<Decl>(DC); 01132 } 01133 01134 // Check whether there's an AccessSpecDecl preceding this in the 01135 // chain of the DeclContext. 01136 bool Implicit = true; 01137 for (CXXRecordDecl::decl_iterator 01138 I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end(); 01139 I != E; ++I) { 01140 if (*I == ImmediateChild) break; 01141 if (isa<AccessSpecDecl>(*I)) { 01142 Implicit = false; 01143 break; 01144 } 01145 } 01146 01147 S.Diag(D->getLocation(), diag::note_access_natural) 01148 << (unsigned) (Access == AS_protected) 01149 << Implicit; 01150 return; 01151 } 01152 01153 case AR_accessible: break; 01154 01155 case AR_dependent: 01156 llvm_unreachable("can't diagnose dependent access failures"); 01157 } 01158 } 01159 01160 CXXBasePaths Paths; 01161 CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths); 01162 01163 CXXBasePath::iterator I = Path.end(), E = Path.begin(); 01164 while (I != E) { 01165 --I; 01166 01167 const CXXBaseSpecifier *BS = I->Base; 01168 AccessSpecifier BaseAccess = BS->getAccessSpecifier(); 01169 01170 // If this is public inheritance, or the derived class is a friend, 01171 // skip this step. 01172 if (BaseAccess == AS_public) 01173 continue; 01174 01175 switch (GetFriendKind(S, EC, I->Class)) { 01176 case AR_accessible: continue; 01177 case AR_inaccessible: break; 01178 case AR_dependent: 01179 llvm_unreachable("can't diagnose dependent access failures"); 01180 } 01181 01182 // Check whether this base specifier is the tighest point 01183 // constraining access. We have to check against AS_private for 01184 // the same reasons as above. 01185 if (BaseAccess == AS_private || BaseAccess >= Access) { 01186 01187 // We're constrained by inheritance, but we want to say 01188 // "declared private here" if we're diagnosing a hierarchy 01189 // conversion and this is the final step. 01190 unsigned diagnostic; 01191 if (D) diagnostic = diag::note_access_constrained_by_path; 01192 else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; 01193 else diagnostic = diag::note_access_constrained_by_path; 01194 01195 S.Diag(BS->getSourceRange().getBegin(), diagnostic) 01196 << BS->getSourceRange() 01197 << (BaseAccess == AS_protected) 01198 << (BS->getAccessSpecifierAsWritten() == AS_none); 01199 01200 if (D) 01201 S.Diag(D->getLocation(), diag::note_field_decl); 01202 01203 return; 01204 } 01205 } 01206 01207 llvm_unreachable("access not apparently constrained by path"); 01208 } 01209 01210 static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 01211 const EffectiveContext &EC, 01212 AccessTarget &Entity) { 01213 const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 01214 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 01215 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 01216 01217 S.Diag(Loc, Entity.getDiag()) 01218 << (Entity.getAccess() == AS_protected) 01219 << (D ? D->getDeclName() : DeclarationName()) 01220 << S.Context.getTypeDeclType(NamingClass) 01221 << S.Context.getTypeDeclType(DeclaringClass); 01222 DiagnoseAccessPath(S, EC, Entity); 01223 } 01224 01225 /// MSVC has a bug where if during an using declaration name lookup, 01226 /// the declaration found is unaccessible (private) and that declaration 01227 /// was bring into scope via another using declaration whose target 01228 /// declaration is accessible (public) then no error is generated. 01229 /// Example: 01230 /// class A { 01231 /// public: 01232 /// int f(); 01233 /// }; 01234 /// class B : public A { 01235 /// private: 01236 /// using A::f; 01237 /// }; 01238 /// class C : public B { 01239 /// private: 01240 /// using B::f; 01241 /// }; 01242 /// 01243 /// Here, B::f is private so this should fail in Standard C++, but 01244 /// because B::f refers to A::f which is public MSVC accepts it. 01245 static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 01246 SourceLocation AccessLoc, 01247 AccessTarget &Entity) { 01248 if (UsingShadowDecl *Shadow = 01249 dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) { 01250 const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl(); 01251 if (Entity.getTargetDecl()->getAccess() == AS_private && 01252 (OrigDecl->getAccess() == AS_public || 01253 OrigDecl->getAccess() == AS_protected)) { 01254 S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible) 01255 << Shadow->getUsingDecl()->getQualifiedNameAsString() 01256 << OrigDecl->getQualifiedNameAsString(); 01257 return true; 01258 } 01259 } 01260 return false; 01261 } 01262 01263 /// Determines whether the accessed entity is accessible. Public members 01264 /// have been weeded out by this point. 01265 static AccessResult IsAccessible(Sema &S, 01266 const EffectiveContext &EC, 01267 AccessTarget &Entity) { 01268 // Determine the actual naming class. 01269 CXXRecordDecl *NamingClass = Entity.getNamingClass(); 01270 while (NamingClass->isAnonymousStructOrUnion()) 01271 NamingClass = cast<CXXRecordDecl>(NamingClass->getParent()); 01272 NamingClass = NamingClass->getCanonicalDecl(); 01273 01274 AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 01275 assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 01276 01277 // Before we try to recalculate access paths, try to white-list 01278 // accesses which just trade in on the final step, i.e. accesses 01279 // which don't require [M4] or [B4]. These are by far the most 01280 // common forms of privileged access. 01281 if (UnprivilegedAccess != AS_none) { 01282 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { 01283 case AR_dependent: 01284 // This is actually an interesting policy decision. We don't 01285 // *have* to delay immediately here: we can do the full access 01286 // calculation in the hope that friendship on some intermediate 01287 // class will make the declaration accessible non-dependently. 01288 // But that's not cheap, and odds are very good (note: assertion 01289 // made without data) that the friend declaration will determine 01290 // access. 01291 return AR_dependent; 01292 01293 case AR_accessible: return AR_accessible; 01294 case AR_inaccessible: break; 01295 } 01296 } 01297 01298 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); 01299 01300 // We lower member accesses to base accesses by pretending that the 01301 // member is a base class of its declaring class. 01302 AccessSpecifier FinalAccess; 01303 01304 if (Entity.isMemberAccess()) { 01305 // Determine if the declaration is accessible from EC when named 01306 // in its declaring class. 01307 NamedDecl *Target = Entity.getTargetDecl(); 01308 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 01309 01310 FinalAccess = Target->getAccess(); 01311 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { 01312 case AR_accessible: 01313 FinalAccess = AS_public; 01314 break; 01315 case AR_inaccessible: break; 01316 case AR_dependent: return AR_dependent; // see above 01317 } 01318 01319 if (DeclaringClass == NamingClass) 01320 return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); 01321 01322 Entity.suppressInstanceContext(); 01323 } else { 01324 FinalAccess = AS_public; 01325 } 01326 01327 assert(Entity.getDeclaringClass() != NamingClass); 01328 01329 // Append the declaration's access if applicable. 01330 CXXBasePaths Paths; 01331 CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); 01332 if (!Path) 01333 return AR_dependent; 01334 01335 assert(Path->Access <= UnprivilegedAccess && 01336 "access along best path worse than direct?"); 01337 if (Path->Access == AS_public) 01338 return AR_accessible; 01339 return AR_inaccessible; 01340 } 01341 01342 static void DelayDependentAccess(Sema &S, 01343 const EffectiveContext &EC, 01344 SourceLocation Loc, 01345 const AccessTarget &Entity) { 01346 assert(EC.isDependent() && "delaying non-dependent access"); 01347 DeclContext *DC = EC.getInnerContext(); 01348 assert(DC->isDependentContext() && "delaying non-dependent access"); 01349 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 01350 Loc, 01351 Entity.isMemberAccess(), 01352 Entity.getAccess(), 01353 Entity.getTargetDecl(), 01354 Entity.getNamingClass(), 01355 Entity.getBaseObjectType(), 01356 Entity.getDiag()); 01357 } 01358 01359 /// Checks access to an entity from the given effective context. 01360 static AccessResult CheckEffectiveAccess(Sema &S, 01361 const EffectiveContext &EC, 01362 SourceLocation Loc, 01363 AccessTarget &Entity) { 01364 assert(Entity.getAccess() != AS_public && "called for public access!"); 01365 01366 if (S.getLangOpts().MicrosoftMode && 01367 IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) 01368 return AR_accessible; 01369 01370 switch (IsAccessible(S, EC, Entity)) { 01371 case AR_dependent: 01372 DelayDependentAccess(S, EC, Loc, Entity); 01373 return AR_dependent; 01374 01375 case AR_inaccessible: 01376 if (!Entity.isQuiet()) 01377 DiagnoseBadAccess(S, Loc, EC, Entity); 01378 return AR_inaccessible; 01379 01380 case AR_accessible: 01381 return AR_accessible; 01382 } 01383 01384 // silence unnecessary warning 01385 llvm_unreachable("invalid access result"); 01386 } 01387 01388 static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 01389 AccessTarget &Entity) { 01390 // If the access path is public, it's accessible everywhere. 01391 if (Entity.getAccess() == AS_public) 01392 return Sema::AR_accessible; 01393 01394 // If we're currently parsing a declaration, we may need to delay 01395 // access control checking, because our effective context might be 01396 // different based on what the declaration comes out as. 01397 // 01398 // For example, we might be parsing a declaration with a scope 01399 // specifier, like this: 01400 // A::private_type A::foo() { ... } 01401 // 01402 // Or we might be parsing something that will turn out to be a friend: 01403 // void foo(A::private_type); 01404 // void B::foo(A::private_type); 01405 if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { 01406 S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); 01407 return Sema::AR_delayed; 01408 } 01409 01410 EffectiveContext EC(S.CurContext); 01411 switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { 01412 case AR_accessible: return Sema::AR_accessible; 01413 case AR_inaccessible: return Sema::AR_inaccessible; 01414 case AR_dependent: return Sema::AR_dependent; 01415 } 01416 llvm_unreachable("falling off end"); 01417 } 01418 01419 void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) { 01420 // Access control for names used in the declarations of functions 01421 // and function templates should normally be evaluated in the context 01422 // of the declaration, just in case it's a friend of something. 01423 // However, this does not apply to local extern declarations. 01424 01425 DeclContext *DC = decl->getDeclContext(); 01426 if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { 01427 if (!DC->isFunctionOrMethod()) DC = fn; 01428 } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) { 01429 // Never a local declaration. 01430 DC = fnt->getTemplatedDecl(); 01431 } 01432 01433 EffectiveContext EC(DC); 01434 01435 AccessTarget Target(DD.getAccessData()); 01436 01437 if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) 01438 DD.Triggered = true; 01439 } 01440 01441 void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 01442 const MultiLevelTemplateArgumentList &TemplateArgs) { 01443 SourceLocation Loc = DD.getAccessLoc(); 01444 AccessSpecifier Access = DD.getAccess(); 01445 01446 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 01447 TemplateArgs); 01448 if (!NamingD) return; 01449 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 01450 TemplateArgs); 01451 if (!TargetD) return; 01452 01453 if (DD.isAccessToMember()) { 01454 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); 01455 NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); 01456 QualType BaseObjectType = DD.getAccessBaseObjectType(); 01457 if (!BaseObjectType.isNull()) { 01458 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, 01459 DeclarationName()); 01460 if (BaseObjectType.isNull()) return; 01461 } 01462 01463 AccessTarget Entity(Context, 01464 AccessTarget::Member, 01465 NamingClass, 01466 DeclAccessPair::make(TargetDecl, Access), 01467 BaseObjectType); 01468 Entity.setDiag(DD.getDiagnostic()); 01469 CheckAccess(*this, Loc, Entity); 01470 } else { 01471 AccessTarget Entity(Context, 01472 AccessTarget::Base, 01473 cast<CXXRecordDecl>(TargetD), 01474 cast<CXXRecordDecl>(NamingD), 01475 Access); 01476 Entity.setDiag(DD.getDiagnostic()); 01477 CheckAccess(*this, Loc, Entity); 01478 } 01479 } 01480 01481 Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 01482 DeclAccessPair Found) { 01483 if (!getLangOpts().AccessControl || 01484 !E->getNamingClass() || 01485 Found.getAccess() == AS_public) 01486 return AR_accessible; 01487 01488 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 01489 Found, QualType()); 01490 Entity.setDiag(diag::err_access) << E->getSourceRange(); 01491 01492 return CheckAccess(*this, E->getNameLoc(), Entity); 01493 } 01494 01495 /// Perform access-control checking on a previously-unresolved member 01496 /// access which has now been resolved to a member. 01497 Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 01498 DeclAccessPair Found) { 01499 if (!getLangOpts().AccessControl || 01500 Found.getAccess() == AS_public) 01501 return AR_accessible; 01502 01503 QualType BaseType = E->getBaseType(); 01504 if (E->isArrow()) 01505 BaseType = BaseType->getAs<PointerType>()->getPointeeType(); 01506 01507 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 01508 Found, BaseType); 01509 Entity.setDiag(diag::err_access) << E->getSourceRange(); 01510 01511 return CheckAccess(*this, E->getMemberLoc(), Entity); 01512 } 01513 01514 /// Is the given special member function accessible for the purposes of 01515 /// deciding whether to define a special member function as deleted? 01516 bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl, 01517 AccessSpecifier access, 01518 QualType objectType) { 01519 // Fast path. 01520 if (access == AS_public || !getLangOpts().AccessControl) return true; 01521 01522 AccessTarget entity(Context, AccessTarget::Member, decl->getParent(), 01523 DeclAccessPair::make(decl, access), objectType); 01524 01525 // Suppress diagnostics. 01526 entity.setDiag(PDiag()); 01527 01528 switch (CheckAccess(*this, SourceLocation(), entity)) { 01529 case AR_accessible: return true; 01530 case AR_inaccessible: return false; 01531 case AR_dependent: llvm_unreachable("dependent for =delete computation"); 01532 case AR_delayed: llvm_unreachable("cannot delay =delete computation"); 01533 } 01534 llvm_unreachable("bad access result"); 01535 } 01536 01537 Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 01538 CXXDestructorDecl *Dtor, 01539 const PartialDiagnostic &PDiag, 01540 QualType ObjectTy) { 01541 if (!getLangOpts().AccessControl) 01542 return AR_accessible; 01543 01544 // There's never a path involved when checking implicit destructor access. 01545 AccessSpecifier Access = Dtor->getAccess(); 01546 if (Access == AS_public) 01547 return AR_accessible; 01548 01549 CXXRecordDecl *NamingClass = Dtor->getParent(); 01550 if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass); 01551 01552 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 01553 DeclAccessPair::make(Dtor, Access), 01554 ObjectTy); 01555 Entity.setDiag(PDiag); // TODO: avoid copy 01556 01557 return CheckAccess(*this, Loc, Entity); 01558 } 01559 01560 /// Checks access to a constructor. 01561 Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 01562 CXXConstructorDecl *Constructor, 01563 const InitializedEntity &Entity, 01564 AccessSpecifier Access, 01565 bool IsCopyBindingRefToTemp) { 01566 if (!getLangOpts().AccessControl || Access == AS_public) 01567 return AR_accessible; 01568 01569 PartialDiagnostic PD(PDiag()); 01570 switch (Entity.getKind()) { 01571 default: 01572 PD = PDiag(IsCopyBindingRefToTemp 01573 ? diag::ext_rvalue_to_reference_access_ctor 01574 : diag::err_access_ctor); 01575 01576 break; 01577 01578 case InitializedEntity::EK_Base: 01579 PD = PDiag(diag::err_access_base_ctor); 01580 PD << Entity.isInheritedVirtualBase() 01581 << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); 01582 break; 01583 01584 case InitializedEntity::EK_Member: { 01585 const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); 01586 PD = PDiag(diag::err_access_field_ctor); 01587 PD << Field->getType() << getSpecialMember(Constructor); 01588 break; 01589 } 01590 01591 case InitializedEntity::EK_LambdaCapture: { 01592 const VarDecl *Var = Entity.getCapturedVar(); 01593 PD = PDiag(diag::err_access_lambda_capture); 01594 PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor); 01595 break; 01596 } 01597 01598 } 01599 01600 return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD); 01601 } 01602 01603 /// Checks access to a constructor. 01604 Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 01605 CXXConstructorDecl *Constructor, 01606 const InitializedEntity &Entity, 01607 AccessSpecifier Access, 01608 const PartialDiagnostic &PD) { 01609 if (!getLangOpts().AccessControl || 01610 Access == AS_public) 01611 return AR_accessible; 01612 01613 CXXRecordDecl *NamingClass = Constructor->getParent(); 01614 01615 // Initializing a base sub-object is an instance method call on an 01616 // object of the derived class. Otherwise, we have an instance method 01617 // call on an object of the constructed type. 01618 CXXRecordDecl *ObjectClass; 01619 if (Entity.getKind() == InitializedEntity::EK_Base) { 01620 ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent(); 01621 } else { 01622 ObjectClass = NamingClass; 01623 } 01624 01625 AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, 01626 DeclAccessPair::make(Constructor, Access), 01627 Context.getTypeDeclType(ObjectClass)); 01628 AccessEntity.setDiag(PD); 01629 01630 return CheckAccess(*this, UseLoc, AccessEntity); 01631 } 01632 01633 /// Checks direct (i.e. non-inherited) access to an arbitrary class 01634 /// member. 01635 Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, 01636 NamedDecl *Target, 01637 const PartialDiagnostic &Diag) { 01638 AccessSpecifier Access = Target->getAccess(); 01639 if (!getLangOpts().AccessControl || 01640 Access == AS_public) 01641 return AR_accessible; 01642 01643 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); 01644 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 01645 DeclAccessPair::make(Target, Access), 01646 QualType()); 01647 Entity.setDiag(Diag); 01648 return CheckAccess(*this, UseLoc, Entity); 01649 } 01650 01651 01652 /// Checks access to an overloaded operator new or delete. 01653 Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 01654 SourceRange PlacementRange, 01655 CXXRecordDecl *NamingClass, 01656 DeclAccessPair Found, 01657 bool Diagnose) { 01658 if (!getLangOpts().AccessControl || 01659 !NamingClass || 01660 Found.getAccess() == AS_public) 01661 return AR_accessible; 01662 01663 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 01664 QualType()); 01665 if (Diagnose) 01666 Entity.setDiag(diag::err_access) 01667 << PlacementRange; 01668 01669 return CheckAccess(*this, OpLoc, Entity); 01670 } 01671 01672 /// Checks access to an overloaded member operator, including 01673 /// conversion operators. 01674 Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 01675 Expr *ObjectExpr, 01676 Expr *ArgExpr, 01677 DeclAccessPair Found) { 01678 if (!getLangOpts().AccessControl || 01679 Found.getAccess() == AS_public) 01680 return AR_accessible; 01681 01682 const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>(); 01683 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 01684 01685 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 01686 ObjectExpr->getType()); 01687 Entity.setDiag(diag::err_access) 01688 << ObjectExpr->getSourceRange() 01689 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 01690 01691 return CheckAccess(*this, OpLoc, Entity); 01692 } 01693 01694 Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 01695 DeclAccessPair Found) { 01696 if (!getLangOpts().AccessControl || 01697 Found.getAccess() == AS_none || 01698 Found.getAccess() == AS_public) 01699 return AR_accessible; 01700 01701 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; 01702 CXXRecordDecl *NamingClass = Ovl->getNamingClass(); 01703 01704 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 01705 /*no instance context*/ QualType()); 01706 Entity.setDiag(diag::err_access) 01707 << Ovl->getSourceRange(); 01708 01709 return CheckAccess(*this, Ovl->getNameLoc(), Entity); 01710 } 01711 01712 /// Checks access for a hierarchy conversion. 01713 /// 01714 /// \param IsBaseToDerived whether this is a base-to-derived conversion (true) 01715 /// or a derived-to-base conversion (false) 01716 /// \param ForceCheck true if this check should be performed even if access 01717 /// control is disabled; some things rely on this for semantics 01718 /// \param ForceUnprivileged true if this check should proceed as if the 01719 /// context had no special privileges 01720 /// \param ADK controls the kind of diagnostics that are used 01721 Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 01722 QualType Base, 01723 QualType Derived, 01724 const CXXBasePath &Path, 01725 unsigned DiagID, 01726 bool ForceCheck, 01727 bool ForceUnprivileged) { 01728 if (!ForceCheck && !getLangOpts().AccessControl) 01729 return AR_accessible; 01730 01731 if (Path.Access == AS_public) 01732 return AR_accessible; 01733 01734 CXXRecordDecl *BaseD, *DerivedD; 01735 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 01736 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 01737 01738 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 01739 Path.Access); 01740 if (DiagID) 01741 Entity.setDiag(DiagID) << Derived << Base; 01742 01743 if (ForceUnprivileged) { 01744 switch (CheckEffectiveAccess(*this, EffectiveContext(), 01745 AccessLoc, Entity)) { 01746 case ::AR_accessible: return Sema::AR_accessible; 01747 case ::AR_inaccessible: return Sema::AR_inaccessible; 01748 case ::AR_dependent: return Sema::AR_dependent; 01749 } 01750 llvm_unreachable("unexpected result from CheckEffectiveAccess"); 01751 } 01752 return CheckAccess(*this, AccessLoc, Entity); 01753 } 01754 01755 /// Checks access to all the declarations in the given result set. 01756 void Sema::CheckLookupAccess(const LookupResult &R) { 01757 assert(getLangOpts().AccessControl 01758 && "performing access check without access control"); 01759 assert(R.getNamingClass() && "performing access check without naming class"); 01760 01761 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 01762 if (I.getAccess() != AS_public) { 01763 AccessTarget Entity(Context, AccessedEntity::Member, 01764 R.getNamingClass(), I.getPair(), 01765 R.getBaseObjectType()); 01766 Entity.setDiag(diag::err_access); 01767 CheckAccess(*this, R.getNameLoc(), Entity); 01768 } 01769 } 01770 } 01771 01772 /// Checks access to Decl from the given class. The check will take access 01773 /// specifiers into account, but no member access expressions and such. 01774 /// 01775 /// \param Decl the declaration to check if it can be accessed 01776 /// \param Class the class/context from which to start the search 01777 /// \return true if the Decl is accessible from the Class, false otherwise. 01778 bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { 01779 if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) { 01780 if (!Decl->isCXXClassMember()) 01781 return true; 01782 01783 QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); 01784 AccessTarget Entity(Context, AccessedEntity::Member, Class, 01785 DeclAccessPair::make(Decl, Decl->getAccess()), 01786 qType); 01787 if (Entity.getAccess() == AS_public) 01788 return true; 01789 01790 EffectiveContext EC(CurContext); 01791 return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; 01792 } 01793 01794 if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) { 01795 // @public and @package ivars are always accessible. 01796 if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public || 01797 Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package) 01798 return true; 01799 01800 01801 01802 // If we are inside a class or category implementation, determine the 01803 // interface we're in. 01804 ObjCInterfaceDecl *ClassOfMethodDecl = 0; 01805 if (ObjCMethodDecl *MD = getCurMethodDecl()) 01806 ClassOfMethodDecl = MD->getClassInterface(); 01807 else if (FunctionDecl *FD = getCurFunctionDecl()) { 01808 if (ObjCImplDecl *Impl 01809 = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) { 01810 if (ObjCImplementationDecl *IMPD 01811 = dyn_cast<ObjCImplementationDecl>(Impl)) 01812 ClassOfMethodDecl = IMPD->getClassInterface(); 01813 else if (ObjCCategoryImplDecl* CatImplClass 01814 = dyn_cast<ObjCCategoryImplDecl>(Impl)) 01815 ClassOfMethodDecl = CatImplClass->getClassInterface(); 01816 } 01817 } 01818 01819 // If we're not in an interface, this ivar is inaccessible. 01820 if (!ClassOfMethodDecl) 01821 return false; 01822 01823 // If we're inside the same interface that owns the ivar, we're fine. 01824 if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface())) 01825 return true; 01826 01827 // If the ivar is private, it's inaccessible. 01828 if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private) 01829 return false; 01830 01831 return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl); 01832 } 01833 01834 return true; 01835 }