SemaAccess.cpp revision 4f9506a27cb6b865bf38beea48eadfa9dc93f510
129f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// 260d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 360d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// The LLVM Compiler Infrastructure 460d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 560d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// This file is distributed under the University of Illinois Open Source 660d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// License. See LICENSE.TXT for details. 760d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 860d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson//===----------------------------------------------------------------------===// 960d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 1060d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// This file provides Sema routines for C++ access control semantics. 1160d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 1260d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson//===----------------------------------------------------------------------===// 13c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson 14c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson#include "Sema.h" 1592f883177b162928a8e632e4e3b93fafd2b26072John McCall#include "Lookup.h" 16c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson#include "clang/AST/ASTContext.h" 17a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/CXXInheritance.h" 18a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/DeclCXX.h" 19c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall#include "clang/AST/ExprCXX.h" 20c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 21c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlssonusing namespace clang; 22c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson 2329f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// SetMemberAccessSpecifier - Set the access specifier of a member. 2429f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// Returns true on error (when the previous member decl access specifier 2529f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// is different from the new member decl access specifier). 261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 27c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson NamedDecl *PrevMemberDecl, 28c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson AccessSpecifier LexicalAS) { 29c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (!PrevMemberDecl) { 30c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // Use the lexical access specifier. 31c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(LexicalAS); 32c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 33c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 35c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // C++ [class.access.spec]p3: When a member is redeclared its access 36c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // specifier must be same as its initial declaration. 37c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diag(MemberDecl->getLocation(), 391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump diag::err_class_redeclared_with_different_access) 40c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << MemberDecl << LexicalAS; 41c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 42c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << PrevMemberDecl << PrevMemberDecl->getAccess(); 4344e067bd8f923ba8e7c24b2189e06717d70015c8John McCall 4444e067bd8f923ba8e7c24b2189e06717d70015c8John McCall MemberDecl->setAccess(LexicalAS); 45c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return true; 46c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 48c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(PrevMemberDecl->getAccess()); 49c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 50c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson} 5129f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson 52726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl/// Find a class on the derivation path between Derived and Base that is 53726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl/// inaccessible. If @p NoPrivileges is true, special access rights (members 54726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl/// and friends) are not considered. 55726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redlconst CXXBaseSpecifier *Sema::FindInaccessibleBase( 56a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor QualType Derived, QualType Base, CXXBasePaths &Paths, bool NoPrivileges) { 57c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson Base = Context.getCanonicalType(Base).getUnqualifiedType(); 581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(!Paths.isAmbiguous(Base) && 59c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson "Can't check base class access if set of paths is ambiguous"); 60c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson assert(Paths.isRecordingPaths() && 61c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson "Can't check base class access without recorded paths"); 62c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 63726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 64726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl const CXXBaseSpecifier *InaccessibleBase = 0; 65726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 66726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl const CXXRecordDecl *CurrentClassDecl = 0; 67f8080a39e6e576a820dadb7a4e0bcf5e7c8ffa35Anders Carlsson if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(getCurFunctionDecl())) 68f8080a39e6e576a820dadb7a4e0bcf5e7c8ffa35Anders Carlsson CurrentClassDecl = MD->getParent(); 69f8080a39e6e576a820dadb7a4e0bcf5e7c8ffa35Anders Carlsson 70a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end(); 71c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson Path != PathsEnd; ++Path) { 72726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 73c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson bool FoundInaccessibleBase = false; 74726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 75a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (CXXBasePath::const_iterator Element = Path->begin(), 76c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson ElementEnd = Path->end(); Element != ElementEnd; ++Element) { 77c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson const CXXBaseSpecifier *Base = Element->Base; 78726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 79c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson switch (Base->getAccessSpecifier()) { 80c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson default: 81c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson assert(0 && "invalid access specifier"); 82c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson case AS_public: 83c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson // Nothing to do. 84c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson break; 85c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson case AS_private: 86f8080a39e6e576a820dadb7a4e0bcf5e7c8ffa35Anders Carlsson // FIXME: Check if the current function/class is a friend. 87726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl if (NoPrivileges || CurrentClassDecl != Element->Class) 88f8080a39e6e576a820dadb7a4e0bcf5e7c8ffa35Anders Carlsson FoundInaccessibleBase = true; 89c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson break; 90726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl case AS_protected: 9114734f7d2a69f9076e8a06954f06d3313063e7f9Anders Carlsson // FIXME: Implement 9214734f7d2a69f9076e8a06954f06d3313063e7f9Anders Carlsson break; 93c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 94726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 95c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson if (FoundInaccessibleBase) { 96726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl InaccessibleBase = Base; 97c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson break; 98c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 99c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 100726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 101c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson if (!FoundInaccessibleBase) { 102c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson // We found a path to the base, our work here is done. 103726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl return 0; 104c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 105c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 106c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 107726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl assert(InaccessibleBase && "no path found, but no inaccessible base"); 108726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl return InaccessibleBase; 109726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl} 110726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 111726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl/// CheckBaseClassAccess - Check that a derived class can access its base class 112726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl/// and report an error if it can't. [class.access.base] 1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Sema::CheckBaseClassAccess(QualType Derived, QualType Base, 114726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl unsigned InaccessibleBaseID, 115a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePaths &Paths, SourceLocation AccessLoc, 116726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl DeclarationName Name) { 117726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 118726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl if (!getLangOptions().AccessControl) 119726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl return false; 120726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl const CXXBaseSpecifier *InaccessibleBase = FindInaccessibleBase( 121726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl Derived, Base, Paths); 122726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 123726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl if (InaccessibleBase) { 1241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diag(AccessLoc, InaccessibleBaseID) 125d8f9cb03ad5ba30094995c254e2b7afcef34d813Anders Carlsson << Derived << Base << Name; 126c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 127726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl AccessSpecifier AS = InaccessibleBase->getAccessSpecifierAsWritten(); 128726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 129c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson // If there's no written access specifier, then the inheritance specifier 130c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson // is implicitly private. 131c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson if (AS == AS_none) 132726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl Diag(InaccessibleBase->getSourceRange().getBegin(), 133c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson diag::note_inheritance_implicitly_private_here); 134c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson else 135726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl Diag(InaccessibleBase->getSourceRange().getBegin(), 136c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson diag::note_inheritance_specifier_here) << AS; 137c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 138c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson return true; 139c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 140726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 14129f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson return false; 14229f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson} 14392f883177b162928a8e632e4e3b93fafd2b26072John McCall 14492f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Diagnose the path which caused the given declaration to become 14592f883177b162928a8e632e4e3b93fafd2b26072John McCall/// inaccessible. 14692f883177b162928a8e632e4e3b93fafd2b26072John McCallstatic void DiagnoseAccessPath(Sema &S, const LookupResult &R, NamedDecl *D, 14792f883177b162928a8e632e4e3b93fafd2b26072John McCall AccessSpecifier Access) { 14892f883177b162928a8e632e4e3b93fafd2b26072John McCall // Easy case: the decl's natural access determined its path access. 14992f883177b162928a8e632e4e3b93fafd2b26072John McCall if (Access == D->getAccess() || D->getAccess() == AS_private) { 15092f883177b162928a8e632e4e3b93fafd2b26072John McCall S.Diag(D->getLocation(), diag::note_access_natural) 15192f883177b162928a8e632e4e3b93fafd2b26072John McCall << (unsigned) (Access == AS_protected); 15292f883177b162928a8e632e4e3b93fafd2b26072John McCall return; 15392f883177b162928a8e632e4e3b93fafd2b26072John McCall } 15492f883177b162928a8e632e4e3b93fafd2b26072John McCall 15592f883177b162928a8e632e4e3b93fafd2b26072John McCall // TODO: flesh this out 15692f883177b162928a8e632e4e3b93fafd2b26072John McCall S.Diag(D->getLocation(), diag::note_access_constrained_by_path) 15792f883177b162928a8e632e4e3b93fafd2b26072John McCall << (unsigned) (Access == AS_protected); 15892f883177b162928a8e632e4e3b93fafd2b26072John McCall} 15992f883177b162928a8e632e4e3b93fafd2b26072John McCall 16092f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Checks access to the given declaration in the current context. 16192f883177b162928a8e632e4e3b93fafd2b26072John McCall/// 16292f883177b162928a8e632e4e3b93fafd2b26072John McCall/// \param R the means via which the access was made; must have a naming 16392f883177b162928a8e632e4e3b93fafd2b26072John McCall/// class set 16492f883177b162928a8e632e4e3b93fafd2b26072John McCall/// \param D the declaration accessed 16592f883177b162928a8e632e4e3b93fafd2b26072John McCall/// \param Access the best access along any inheritance path from the 16692f883177b162928a8e632e4e3b93fafd2b26072John McCall/// naming class to the declaration. AS_none means the path is impossible 16792f883177b162928a8e632e4e3b93fafd2b26072John McCallbool Sema::CheckAccess(const LookupResult &R, NamedDecl *D, 16892f883177b162928a8e632e4e3b93fafd2b26072John McCall AccessSpecifier Access) { 16992f883177b162928a8e632e4e3b93fafd2b26072John McCall assert(R.getNamingClass() && "performing access check without naming class"); 17092f883177b162928a8e632e4e3b93fafd2b26072John McCall 17192f883177b162928a8e632e4e3b93fafd2b26072John McCall // If the access path is public, it's accessible everywhere. 17292f883177b162928a8e632e4e3b93fafd2b26072John McCall if (Access == AS_public) 17392f883177b162928a8e632e4e3b93fafd2b26072John McCall return false; 17492f883177b162928a8e632e4e3b93fafd2b26072John McCall 1752f514480c448708ec382a684cf5e035d3a827ec8John McCall // If we're currently parsing a top-level declaration, delay 1762f514480c448708ec382a684cf5e035d3a827ec8John McCall // diagnostics. This is the only case where parsing a declaration 1772f514480c448708ec382a684cf5e035d3a827ec8John McCall // can actually change our effective context for the purposes of 1782f514480c448708ec382a684cf5e035d3a827ec8John McCall // access control. 1792f514480c448708ec382a684cf5e035d3a827ec8John McCall if (CurContext->isFileContext() && ParsingDeclDepth) { 1802f514480c448708ec382a684cf5e035d3a827ec8John McCall DelayedDiagnostics.push_back( 1812f514480c448708ec382a684cf5e035d3a827ec8John McCall DelayedDiagnostic::makeAccess(R.getNameLoc(), D, Access, 1822f514480c448708ec382a684cf5e035d3a827ec8John McCall R.getNamingClass())); 1832f514480c448708ec382a684cf5e035d3a827ec8John McCall return false; 1842f514480c448708ec382a684cf5e035d3a827ec8John McCall } 1852f514480c448708ec382a684cf5e035d3a827ec8John McCall 1862f514480c448708ec382a684cf5e035d3a827ec8John McCall return CheckEffectiveAccess(CurContext, R, D, Access); 1872f514480c448708ec382a684cf5e035d3a827ec8John McCall} 1882f514480c448708ec382a684cf5e035d3a827ec8John McCall 1892f514480c448708ec382a684cf5e035d3a827ec8John McCall/// Checks access from the given effective context. 1902f514480c448708ec382a684cf5e035d3a827ec8John McCallbool Sema::CheckEffectiveAccess(DeclContext *EffectiveContext, 1912f514480c448708ec382a684cf5e035d3a827ec8John McCall const LookupResult &R, 1922f514480c448708ec382a684cf5e035d3a827ec8John McCall NamedDecl *D, AccessSpecifier Access) { 1932f514480c448708ec382a684cf5e035d3a827ec8John McCall DeclContext *DC = EffectiveContext; 19492f883177b162928a8e632e4e3b93fafd2b26072John McCall while (isa<CXXRecordDecl>(DC) && 19592f883177b162928a8e632e4e3b93fafd2b26072John McCall cast<CXXRecordDecl>(DC)->isAnonymousStructOrUnion()) 19692f883177b162928a8e632e4e3b93fafd2b26072John McCall DC = DC->getParent(); 19792f883177b162928a8e632e4e3b93fafd2b26072John McCall 19892f883177b162928a8e632e4e3b93fafd2b26072John McCall CXXRecordDecl *CurRecord; 19992f883177b162928a8e632e4e3b93fafd2b26072John McCall if (isa<CXXRecordDecl>(DC)) 20092f883177b162928a8e632e4e3b93fafd2b26072John McCall CurRecord = cast<CXXRecordDecl>(DC); 20192f883177b162928a8e632e4e3b93fafd2b26072John McCall else if (isa<CXXMethodDecl>(DC)) 20292f883177b162928a8e632e4e3b93fafd2b26072John McCall CurRecord = cast<CXXMethodDecl>(DC)->getParent(); 20392f883177b162928a8e632e4e3b93fafd2b26072John McCall else { 20492f883177b162928a8e632e4e3b93fafd2b26072John McCall Diag(R.getNameLoc(), diag::err_access_outside_class) 20592f883177b162928a8e632e4e3b93fafd2b26072John McCall << (Access == AS_protected); 20692f883177b162928a8e632e4e3b93fafd2b26072John McCall DiagnoseAccessPath(*this, R, D, Access); 20792f883177b162928a8e632e4e3b93fafd2b26072John McCall return true; 20892f883177b162928a8e632e4e3b93fafd2b26072John McCall } 20992f883177b162928a8e632e4e3b93fafd2b26072John McCall 21092f883177b162928a8e632e4e3b93fafd2b26072John McCall CXXRecordDecl *NamingClass = R.getNamingClass(); 21192f883177b162928a8e632e4e3b93fafd2b26072John McCall while (NamingClass->isAnonymousStructOrUnion()) 21292f883177b162928a8e632e4e3b93fafd2b26072John McCall // This should be guaranteed by the fact that the decl has 21392f883177b162928a8e632e4e3b93fafd2b26072John McCall // non-public access. If not, we should make it guaranteed! 21492f883177b162928a8e632e4e3b93fafd2b26072John McCall NamingClass = cast<CXXRecordDecl>(NamingClass); 21592f883177b162928a8e632e4e3b93fafd2b26072John McCall 21692f883177b162928a8e632e4e3b93fafd2b26072John McCall // White-list accesses from within the declaring class. 21792f883177b162928a8e632e4e3b93fafd2b26072John McCall if (Access != AS_none && 21892f883177b162928a8e632e4e3b93fafd2b26072John McCall CurRecord->getCanonicalDecl() == NamingClass->getCanonicalDecl()) 21992f883177b162928a8e632e4e3b93fafd2b26072John McCall return false; 22092f883177b162928a8e632e4e3b93fafd2b26072John McCall 22192f883177b162928a8e632e4e3b93fafd2b26072John McCall // Protected access. 22292f883177b162928a8e632e4e3b93fafd2b26072John McCall if (Access == AS_protected) { 22392f883177b162928a8e632e4e3b93fafd2b26072John McCall // FIXME: implement [class.protected]p1 22492f883177b162928a8e632e4e3b93fafd2b26072John McCall if (CurRecord->isDerivedFrom(NamingClass)) 22592f883177b162928a8e632e4e3b93fafd2b26072John McCall return false; 22692f883177b162928a8e632e4e3b93fafd2b26072John McCall 22792f883177b162928a8e632e4e3b93fafd2b26072John McCall // FIXME: dependent classes 22892f883177b162928a8e632e4e3b93fafd2b26072John McCall } 22992f883177b162928a8e632e4e3b93fafd2b26072John McCall 23092f883177b162928a8e632e4e3b93fafd2b26072John McCall // FIXME: friends 23192f883177b162928a8e632e4e3b93fafd2b26072John McCall 23292f883177b162928a8e632e4e3b93fafd2b26072John McCall // Okay, it's a bad access, reject it. 23392f883177b162928a8e632e4e3b93fafd2b26072John McCall 23492f883177b162928a8e632e4e3b93fafd2b26072John McCall 23592f883177b162928a8e632e4e3b93fafd2b26072John McCall CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext()); 23692f883177b162928a8e632e4e3b93fafd2b26072John McCall 23792f883177b162928a8e632e4e3b93fafd2b26072John McCall if (Access == AS_protected) { 23892f883177b162928a8e632e4e3b93fafd2b26072John McCall Diag(R.getNameLoc(), diag::err_access_protected) 23992f883177b162928a8e632e4e3b93fafd2b26072John McCall << Context.getTypeDeclType(DeclaringClass) 24092f883177b162928a8e632e4e3b93fafd2b26072John McCall << Context.getTypeDeclType(CurRecord); 24192f883177b162928a8e632e4e3b93fafd2b26072John McCall DiagnoseAccessPath(*this, R, D, Access); 24292f883177b162928a8e632e4e3b93fafd2b26072John McCall return true; 24392f883177b162928a8e632e4e3b93fafd2b26072John McCall } 24492f883177b162928a8e632e4e3b93fafd2b26072John McCall 24592f883177b162928a8e632e4e3b93fafd2b26072John McCall assert(Access == AS_private || Access == AS_none); 24692f883177b162928a8e632e4e3b93fafd2b26072John McCall Diag(R.getNameLoc(), diag::err_access_private) 24792f883177b162928a8e632e4e3b93fafd2b26072John McCall << Context.getTypeDeclType(DeclaringClass) 24892f883177b162928a8e632e4e3b93fafd2b26072John McCall << Context.getTypeDeclType(CurRecord); 24992f883177b162928a8e632e4e3b93fafd2b26072John McCall DiagnoseAccessPath(*this, R, D, Access); 25092f883177b162928a8e632e4e3b93fafd2b26072John McCall return true; 25192f883177b162928a8e632e4e3b93fafd2b26072John McCall} 25292f883177b162928a8e632e4e3b93fafd2b26072John McCall 2532f514480c448708ec382a684cf5e035d3a827ec8John McCallvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) { 2542f514480c448708ec382a684cf5e035d3a827ec8John McCall NamedDecl *D = DD.AccessData.Decl; 2552f514480c448708ec382a684cf5e035d3a827ec8John McCall 2562f514480c448708ec382a684cf5e035d3a827ec8John McCall // Fake up a lookup result. 2572f514480c448708ec382a684cf5e035d3a827ec8John McCall LookupResult R(*this, D->getDeclName(), DD.Loc, LookupOrdinaryName); 2582f514480c448708ec382a684cf5e035d3a827ec8John McCall R.suppressDiagnostics(); 2592f514480c448708ec382a684cf5e035d3a827ec8John McCall R.setNamingClass(DD.AccessData.NamingClass); 2602f514480c448708ec382a684cf5e035d3a827ec8John McCall 2612f514480c448708ec382a684cf5e035d3a827ec8John McCall // Pretend we did this from the context of the newly-parsed 2622f514480c448708ec382a684cf5e035d3a827ec8John McCall // declaration. 2632f514480c448708ec382a684cf5e035d3a827ec8John McCall DeclContext *EffectiveContext = Ctx->getDeclContext(); 2642f514480c448708ec382a684cf5e035d3a827ec8John McCall 2652f514480c448708ec382a684cf5e035d3a827ec8John McCall if (CheckEffectiveAccess(EffectiveContext, R, D, DD.AccessData.Access)) 2662f514480c448708ec382a684cf5e035d3a827ec8John McCall DD.Triggered = true; 2672f514480c448708ec382a684cf5e035d3a827ec8John McCall} 2682f514480c448708ec382a684cf5e035d3a827ec8John McCall 269c373d48502ca7683ab55385f5bd624d778eb288dJohn McCallbool Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 270c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall NamedDecl *D, AccessSpecifier Access) { 271c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall if (!getLangOptions().AccessControl || !E->getNamingClass()) 272c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall return false; 273c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 274c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall // Fake up a lookup result. 275c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall LookupResult R(*this, E->getName(), E->getNameLoc(), LookupOrdinaryName); 276c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall R.suppressDiagnostics(); 277c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 278c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall R.setNamingClass(E->getNamingClass()); 279c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall R.addDecl(D, Access); 280c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 281c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall // FIXME: protected check (triggers for member-address expressions) 282c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 283c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall return CheckAccess(R, D, Access); 284c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 285c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 286c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// Perform access-control checking on a previously-unresolved member 287c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// access which has now been resolved to a member. 288c373d48502ca7683ab55385f5bd624d778eb288dJohn McCallbool Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 289c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall NamedDecl *D, AccessSpecifier Access) { 290c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall if (!getLangOptions().AccessControl) 291c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall return false; 292c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 293c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall // Fake up a lookup result. 294c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall LookupResult R(*this, E->getMemberName(), E->getMemberLoc(), 295c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall LookupOrdinaryName); 296c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall R.suppressDiagnostics(); 297c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 298c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall R.setNamingClass(E->getNamingClass()); 299c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall R.addDecl(D, Access); 300c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 301c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall if (CheckAccess(R, D, Access)) 302c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall return true; 303c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 304c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall // FIXME: protected check 305c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 306c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall return false; 307c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 308c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 3094f9506a27cb6b865bf38beea48eadfa9dc93f510John McCallbool Sema::CheckDestructorAccess(SourceLocation Loc, 3104f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall QualType T) { 3114f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (!getLangOptions().AccessControl) 3124f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall return false; 3134f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 3144f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall const RecordType *Record = T->getAs<RecordType>(); 3154f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (!Record) 3164f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall return false; 3174f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 3184f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Record->getDecl()); 3194f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall CXXDestructorDecl *Dtor = NamingClass->getDestructor(Context); 3204f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 3214f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall AccessSpecifier Access = Dtor->getAccess(); 3224f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (Access == AS_public) 3234f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall return false; 3244f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 3254f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall LookupResult R(*this, Dtor->getDeclName(), Loc, LookupOrdinaryName); 3264f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall R.suppressDiagnostics(); 3274f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 3284f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall R.setNamingClass(NamingClass); 3294f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall return CheckAccess(R, Dtor, Access); 3304f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 3314f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall // FIXME: protected check 3324f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall} 3334f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 334b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to a constructor. 335b13b737a2450167c82e148590e8019b839ce6b98John McCallbool Sema::CheckConstructorAccess(SourceLocation UseLoc, 336b13b737a2450167c82e148590e8019b839ce6b98John McCall CXXConstructorDecl *Constructor, 337b13b737a2450167c82e148590e8019b839ce6b98John McCall AccessSpecifier Access) { 338b13b737a2450167c82e148590e8019b839ce6b98John McCall if (!getLangOptions().AccessControl) 339b13b737a2450167c82e148590e8019b839ce6b98John McCall return false; 340b13b737a2450167c82e148590e8019b839ce6b98John McCall 341b13b737a2450167c82e148590e8019b839ce6b98John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Constructor->getParent()); 342b13b737a2450167c82e148590e8019b839ce6b98John McCall 343b13b737a2450167c82e148590e8019b839ce6b98John McCall LookupResult R(*this, Constructor->getDeclName(), UseLoc, LookupOrdinaryName); 344b13b737a2450167c82e148590e8019b839ce6b98John McCall R.suppressDiagnostics(); 345b13b737a2450167c82e148590e8019b839ce6b98John McCall 346b13b737a2450167c82e148590e8019b839ce6b98John McCall R.setNamingClass(NamingClass); 347b13b737a2450167c82e148590e8019b839ce6b98John McCall return CheckAccess(R, Constructor, Access); 348b13b737a2450167c82e148590e8019b839ce6b98John McCall} 349b13b737a2450167c82e148590e8019b839ce6b98John McCall 350b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to an overloaded member operator, including 351b13b737a2450167c82e148590e8019b839ce6b98John McCall/// conversion operators. 3525357b615364c17ea024c757354c58ae2a520d216John McCallbool Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 3535357b615364c17ea024c757354c58ae2a520d216John McCall Expr *ObjectExpr, 3545357b615364c17ea024c757354c58ae2a520d216John McCall NamedDecl *MemberOperator, 3555357b615364c17ea024c757354c58ae2a520d216John McCall AccessSpecifier Access) { 3565357b615364c17ea024c757354c58ae2a520d216John McCall if (!getLangOptions().AccessControl) 3575357b615364c17ea024c757354c58ae2a520d216John McCall return false; 3585357b615364c17ea024c757354c58ae2a520d216John McCall 3595357b615364c17ea024c757354c58ae2a520d216John McCall const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); 3605357b615364c17ea024c757354c58ae2a520d216John McCall assert(RT && "found member operator but object expr not of record type"); 3615357b615364c17ea024c757354c58ae2a520d216John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 3625357b615364c17ea024c757354c58ae2a520d216John McCall 3635357b615364c17ea024c757354c58ae2a520d216John McCall LookupResult R(*this, DeclarationName(), OpLoc, LookupOrdinaryName); 3645357b615364c17ea024c757354c58ae2a520d216John McCall R.suppressDiagnostics(); 3655357b615364c17ea024c757354c58ae2a520d216John McCall 3665357b615364c17ea024c757354c58ae2a520d216John McCall R.setNamingClass(NamingClass); 3675357b615364c17ea024c757354c58ae2a520d216John McCall if (CheckAccess(R, MemberOperator, Access)) 3685357b615364c17ea024c757354c58ae2a520d216John McCall return true; 3695357b615364c17ea024c757354c58ae2a520d216John McCall 3705357b615364c17ea024c757354c58ae2a520d216John McCall // FIXME: protected check 3715357b615364c17ea024c757354c58ae2a520d216John McCall 3725357b615364c17ea024c757354c58ae2a520d216John McCall return false; 3735357b615364c17ea024c757354c58ae2a520d216John McCall} 3745357b615364c17ea024c757354c58ae2a520d216John McCall 37592f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Checks access to all the declarations in the given result set. 37692f883177b162928a8e632e4e3b93fafd2b26072John McCallvoid Sema::CheckAccess(const LookupResult &R) { 37792f883177b162928a8e632e4e3b93fafd2b26072John McCall for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) 37892f883177b162928a8e632e4e3b93fafd2b26072John McCall CheckAccess(R, *I, I.getAccess()); 37992f883177b162928a8e632e4e3b93fafd2b26072John McCall} 380