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