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