//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides Sema routines for C++ access control semantics.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/ExprCXX.h"

using namespace clang;
using namespace sema;

/// A copy of Sema's enum without AR_delayed.
enum AccessResult {
  AR_accessible,
  AR_inaccessible,
  AR_dependent
};

/// SetMemberAccessSpecifier - Set the access specifier of a member.
/// Returns true on error (when the previous member decl access specifier
/// is different from the new member decl access specifier).
bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
                                    NamedDecl *PrevMemberDecl,
                                    AccessSpecifier LexicalAS) {
  if (!PrevMemberDecl) {
    // Use the lexical access specifier.
    MemberDecl->setAccess(LexicalAS);
    return false;
  }

  // C++ [class.access.spec]p3: When a member is redeclared its access
  // specifier must be same as its initial declaration.
  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
    Diag(MemberDecl->getLocation(),
         diag::err_class_redeclared_with_different_access)
      << MemberDecl << LexicalAS;
    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
      << PrevMemberDecl << PrevMemberDecl->getAccess();

    MemberDecl->setAccess(LexicalAS);
    return true;
  }

  MemberDecl->setAccess(PrevMemberDecl->getAccess());
  return false;
}

static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
  DeclContext *DC = D->getDeclContext();

  // This can only happen at top: enum decls only "publish" their
  // immediate members.
  if (isa<EnumDecl>(DC))
    DC = cast<EnumDecl>(DC)->getDeclContext();

  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
  while (DeclaringClass->isAnonymousStructOrUnion())
    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
  return DeclaringClass;
}

namespace {
struct EffectiveContext {
  EffectiveContext() : Inner(0), Dependent(false) {}

  explicit EffectiveContext(DeclContext *DC)
    : Inner(DC),
      Dependent(DC->isDependentContext()) {

    // C++ [class.access.nest]p1:
    //   A nested class is a member and as such has the same access
    //   rights as any other member.
    // C++ [class.access]p2:
    //   A member of a class can also access all the names to which
    //   the class has access.  A local class of a member function
    //   may access the same names that the member function itself
    //   may access.
    // This almost implies that the privileges of nesting are transitive.
    // Technically it says nothing about the local classes of non-member
    // functions (which can gain privileges through friendship), but we
    // take that as an oversight.
    while (true) {
      if (isa<CXXRecordDecl>(DC)) {
        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
        Records.push_back(Record);
        DC = Record->getDeclContext();
      } else if (isa<FunctionDecl>(DC)) {
        FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
        Functions.push_back(Function);
        
        if (Function->getFriendObjectKind())
          DC = Function->getLexicalDeclContext();
        else
          DC = Function->getDeclContext();
      } else if (DC->isFileContext()) {
        break;
      } else {
        DC = DC->getParent();
      }
    }
  }

  bool isDependent() const { return Dependent; }

  bool includesClass(const CXXRecordDecl *R) const {
    R = R->getCanonicalDecl();
    return std::find(Records.begin(), Records.end(), R)
             != Records.end();
  }

  /// Retrieves the innermost "useful" context.  Can be null if we're
  /// doing access-control without privileges.
  DeclContext *getInnerContext() const {
    return Inner;
  }

  typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;

  DeclContext *Inner;
  SmallVector<FunctionDecl*, 4> Functions;
  SmallVector<CXXRecordDecl*, 4> Records;
  bool Dependent;
};

/// Like sema::AccessedEntity, but kindly lets us scribble all over
/// it.
struct AccessTarget : public AccessedEntity {
  AccessTarget(const AccessedEntity &Entity)
    : AccessedEntity(Entity) {
    initialize();
  }
    
  AccessTarget(ASTContext &Context, 
               MemberNonce _,
               CXXRecordDecl *NamingClass,
               DeclAccessPair FoundDecl,
               QualType BaseObjectType)
    : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass,
                     FoundDecl, BaseObjectType) {
    initialize();
  }

  AccessTarget(ASTContext &Context, 
               BaseNonce _,
               CXXRecordDecl *BaseClass,
               CXXRecordDecl *DerivedClass,
               AccessSpecifier Access)
    : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,
                     Access) {
    initialize();
  }

  bool isInstanceMember() const {
    return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
  }

  bool hasInstanceContext() const {
    return HasInstanceContext;
  }

  class SavedInstanceContext {
  public:
    ~SavedInstanceContext() {
      Target.HasInstanceContext = Has;
    }

  private:
    friend struct AccessTarget;
    explicit SavedInstanceContext(AccessTarget &Target)
      : Target(Target), Has(Target.HasInstanceContext) {}
    AccessTarget &Target;
    bool Has;
  };

  SavedInstanceContext saveInstanceContext() {
    return SavedInstanceContext(*this);
  }

  void suppressInstanceContext() {
    HasInstanceContext = false;
  }

  const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
    assert(HasInstanceContext);
    if (CalculatedInstanceContext)
      return InstanceContext;

    CalculatedInstanceContext = true;
    DeclContext *IC = S.computeDeclContext(getBaseObjectType());
    InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
    return InstanceContext;
  }

  const CXXRecordDecl *getDeclaringClass() const {
    return DeclaringClass;
  }

private:
  void initialize() {
    HasInstanceContext = (isMemberAccess() &&
                          !getBaseObjectType().isNull() &&
                          getTargetDecl()->isCXXInstanceMember());
    CalculatedInstanceContext = false;
    InstanceContext = 0;

    if (isMemberAccess())
      DeclaringClass = FindDeclaringClass(getTargetDecl());
    else
      DeclaringClass = getBaseClass();
    DeclaringClass = DeclaringClass->getCanonicalDecl();
  }

  bool HasInstanceContext : 1;
  mutable bool CalculatedInstanceContext : 1;
  mutable const CXXRecordDecl *InstanceContext;
  const CXXRecordDecl *DeclaringClass;
};

}

/// Checks whether one class might instantiate to the other.
static bool MightInstantiateTo(const CXXRecordDecl *From,
                               const CXXRecordDecl *To) {
  // Declaration names are always preserved by instantiation.
  if (From->getDeclName() != To->getDeclName())
    return false;

  const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
  const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
  if (FromDC == ToDC) return true;
  if (FromDC->isFileContext() || ToDC->isFileContext()) return false;

  // Be conservative.
  return true;
}

/// Checks whether one class is derived from another, inclusively.
/// Properly indicates when it couldn't be determined due to
/// dependence.
///
/// This should probably be donated to AST or at least Sema.
static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
                                           const CXXRecordDecl *Target) {
  assert(Derived->getCanonicalDecl() == Derived);
  assert(Target->getCanonicalDecl() == Target);

  if (Derived == Target) return AR_accessible;

  bool CheckDependent = Derived->isDependentContext();
  if (CheckDependent && MightInstantiateTo(Derived, Target))
    return AR_dependent;

  AccessResult OnFailure = AR_inaccessible;
  SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack

  while (true) {
    if (Derived->isDependentContext() && !Derived->hasDefinition())
      return AR_dependent;
    
    for (CXXRecordDecl::base_class_const_iterator
           I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {

      const CXXRecordDecl *RD;

      QualType T = I->getType();
      if (const RecordType *RT = T->getAs<RecordType>()) {
        RD = cast<CXXRecordDecl>(RT->getDecl());
      } else if (const InjectedClassNameType *IT
                   = T->getAs<InjectedClassNameType>()) {
        RD = IT->getDecl();
      } else {
        assert(T->isDependentType() && "non-dependent base wasn't a record?");
        OnFailure = AR_dependent;
        continue;
      }

      RD = RD->getCanonicalDecl();
      if (RD == Target) return AR_accessible;
      if (CheckDependent && MightInstantiateTo(RD, Target))
        OnFailure = AR_dependent;

      Queue.push_back(RD);
    }

    if (Queue.empty()) break;

    Derived = Queue.back();
    Queue.pop_back();
  }

  return OnFailure;
}


static bool MightInstantiateTo(Sema &S, DeclContext *Context,
                               DeclContext *Friend) {
  if (Friend == Context)
    return true;

  assert(!Friend->isDependentContext() &&
         "can't handle friends with dependent contexts here");

  if (!Context->isDependentContext())
    return false;

  if (Friend->isFileContext())
    return false;

  // TODO: this is very conservative
  return true;
}

// Asks whether the type in 'context' can ever instantiate to the type
// in 'friend'.
static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
  if (Friend == Context)
    return true;

  if (!Friend->isDependentType() && !Context->isDependentType())
    return false;

  // TODO: this is very conservative.
  return true;
}

static bool MightInstantiateTo(Sema &S,
                               FunctionDecl *Context,
                               FunctionDecl *Friend) {
  if (Context->getDeclName() != Friend->getDeclName())
    return false;

  if (!MightInstantiateTo(S,
                          Context->getDeclContext(),
                          Friend->getDeclContext()))
    return false;

  CanQual<FunctionProtoType> FriendTy
    = S.Context.getCanonicalType(Friend->getType())
         ->getAs<FunctionProtoType>();
  CanQual<FunctionProtoType> ContextTy
    = S.Context.getCanonicalType(Context->getType())
         ->getAs<FunctionProtoType>();

  // There isn't any way that I know of to add qualifiers
  // during instantiation.
  if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
    return false;

  if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
    return false;

  if (!MightInstantiateTo(S,
                          ContextTy->getResultType(),
                          FriendTy->getResultType()))
    return false;

  for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
    if (!MightInstantiateTo(S,
                            ContextTy->getArgType(I),
                            FriendTy->getArgType(I)))
      return false;

  return true;
}

static bool MightInstantiateTo(Sema &S,
                               FunctionTemplateDecl *Context,
                               FunctionTemplateDecl *Friend) {
  return MightInstantiateTo(S,
                            Context->getTemplatedDecl(),
                            Friend->getTemplatedDecl());
}

static AccessResult MatchesFriend(Sema &S,
                                  const EffectiveContext &EC,
                                  const CXXRecordDecl *Friend) {
  if (EC.includesClass(Friend))
    return AR_accessible;

  if (EC.isDependent()) {
    CanQualType FriendTy
      = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));

    for (EffectiveContext::record_iterator
           I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
      CanQualType ContextTy
        = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
      if (MightInstantiateTo(S, ContextTy, FriendTy))
        return AR_dependent;
    }
  }

  return AR_inaccessible;
}

static AccessResult MatchesFriend(Sema &S,
                                  const EffectiveContext &EC,
                                  CanQualType Friend) {
  if (const RecordType *RT = Friend->getAs<RecordType>())
    return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));

  // TODO: we can do better than this
  if (Friend->isDependentType())
    return AR_dependent;

  return AR_inaccessible;
}

/// Determines whether the given friend class template matches
/// anything in the effective context.
static AccessResult MatchesFriend(Sema &S,
                                  const EffectiveContext &EC,
                                  ClassTemplateDecl *Friend) {
  AccessResult OnFailure = AR_inaccessible;

  // Check whether the friend is the template of a class in the
  // context chain.
  for (SmallVectorImpl<CXXRecordDecl*>::const_iterator
         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
    CXXRecordDecl *Record = *I;

    // Figure out whether the current class has a template:
    ClassTemplateDecl *CTD;

    // A specialization of the template...
    if (isa<ClassTemplateSpecializationDecl>(Record)) {
      CTD = cast<ClassTemplateSpecializationDecl>(Record)
        ->getSpecializedTemplate();

    // ... or the template pattern itself.
    } else {
      CTD = Record->getDescribedClassTemplate();
      if (!CTD) continue;
    }

    // It's a match.
    if (Friend == CTD->getCanonicalDecl())
      return AR_accessible;

    // If the context isn't dependent, it can't be a dependent match.
    if (!EC.isDependent())
      continue;

    // If the template names don't match, it can't be a dependent
    // match.
    if (CTD->getDeclName() != Friend->getDeclName())
      continue;

    // If the class's context can't instantiate to the friend's
    // context, it can't be a dependent match.
    if (!MightInstantiateTo(S, CTD->getDeclContext(),
                            Friend->getDeclContext()))
      continue;

    // Otherwise, it's a dependent match.
    OnFailure = AR_dependent;
  }

  return OnFailure;
}

/// Determines whether the given friend function matches anything in
/// the effective context.
static AccessResult MatchesFriend(Sema &S,
                                  const EffectiveContext &EC,
                                  FunctionDecl *Friend) {
  AccessResult OnFailure = AR_inaccessible;

  for (SmallVectorImpl<FunctionDecl*>::const_iterator
         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
    if (Friend == *I)
      return AR_accessible;

    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
      OnFailure = AR_dependent;
  }

  return OnFailure;
}

/// Determines whether the given friend function template matches
/// anything in the effective context.
static AccessResult MatchesFriend(Sema &S,
                                  const EffectiveContext &EC,
                                  FunctionTemplateDecl *Friend) {
  if (EC.Functions.empty()) return AR_inaccessible;

  AccessResult OnFailure = AR_inaccessible;

  for (SmallVectorImpl<FunctionDecl*>::const_iterator
         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {

    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
    if (!FTD)
      FTD = (*I)->getDescribedFunctionTemplate();
    if (!FTD)
      continue;

    FTD = FTD->getCanonicalDecl();

    if (Friend == FTD)
      return AR_accessible;

    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
      OnFailure = AR_dependent;
  }

  return OnFailure;
}

/// Determines whether the given friend declaration matches anything
/// in the effective context.
static AccessResult MatchesFriend(Sema &S,
                                  const EffectiveContext &EC,
                                  FriendDecl *FriendD) {
  // Whitelist accesses if there's an invalid or unsupported friend
  // declaration.
  if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())
    return AR_accessible;

  if (TypeSourceInfo *T = FriendD->getFriendType())
    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());

  NamedDecl *Friend
    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());

  // FIXME: declarations with dependent or templated scope.

  if (isa<ClassTemplateDecl>(Friend))
    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));

  if (isa<FunctionTemplateDecl>(Friend))
    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));

  if (isa<CXXRecordDecl>(Friend))
    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));

  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
}

static AccessResult GetFriendKind(Sema &S,
                                  const EffectiveContext &EC,
                                  const CXXRecordDecl *Class) {
  AccessResult OnFailure = AR_inaccessible;

  // Okay, check friends.
  for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
         E = Class->friend_end(); I != E; ++I) {
    FriendDecl *Friend = *I;

    switch (MatchesFriend(S, EC, Friend)) {
    case AR_accessible:
      return AR_accessible;

    case AR_inaccessible:
      continue;

    case AR_dependent:
      OnFailure = AR_dependent;
      break;
    }
  }

  // That's it, give up.
  return OnFailure;
}

namespace {

/// A helper class for checking for a friend which will grant access
/// to a protected instance member.
struct ProtectedFriendContext {
  Sema &S;
  const EffectiveContext &EC;
  const CXXRecordDecl *NamingClass;
  bool CheckDependent;
  bool EverDependent;

  /// The path down to the current base class.
  SmallVector<const CXXRecordDecl*, 20> CurPath;

  ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
                         const CXXRecordDecl *InstanceContext,
                         const CXXRecordDecl *NamingClass)
    : S(S), EC(EC), NamingClass(NamingClass),
      CheckDependent(InstanceContext->isDependentContext() ||
                     NamingClass->isDependentContext()),
      EverDependent(false) {}

  /// Check classes in the current path for friendship, starting at
  /// the given index.
  bool checkFriendshipAlongPath(unsigned I) {
    assert(I < CurPath.size());
    for (unsigned E = CurPath.size(); I != E; ++I) {
      switch (GetFriendKind(S, EC, CurPath[I])) {
      case AR_accessible:   return true;
      case AR_inaccessible: continue;
      case AR_dependent:    EverDependent = true; continue;
      }
    }
    return false;
  }

  /// Perform a search starting at the given class.
  ///
  /// PrivateDepth is the index of the last (least derived) class
  /// along the current path such that a notional public member of
  /// the final class in the path would have access in that class.
  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
    // If we ever reach the naming class, check the current path for
    // friendship.  We can also stop recursing because we obviously
    // won't find the naming class there again.
    if (Cur == NamingClass)
      return checkFriendshipAlongPath(PrivateDepth);

    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
      EverDependent = true;

    // Recurse into the base classes.
    for (CXXRecordDecl::base_class_const_iterator
           I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {

      // If this is private inheritance, then a public member of the
      // base will not have any access in classes derived from Cur.
      unsigned BasePrivateDepth = PrivateDepth;
      if (I->getAccessSpecifier() == AS_private)
        BasePrivateDepth = CurPath.size() - 1;

      const CXXRecordDecl *RD;

      QualType T = I->getType();
      if (const RecordType *RT = T->getAs<RecordType>()) {
        RD = cast<CXXRecordDecl>(RT->getDecl());
      } else if (const InjectedClassNameType *IT
                   = T->getAs<InjectedClassNameType>()) {
        RD = IT->getDecl();
      } else {
        assert(T->isDependentType() && "non-dependent base wasn't a record?");
        EverDependent = true;
        continue;
      }

      // Recurse.  We don't need to clean up if this returns true.
      CurPath.push_back(RD);
      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
        return true;
      CurPath.pop_back();
    }

    return false;
  }

  bool findFriendship(const CXXRecordDecl *Cur) {
    assert(CurPath.empty());
    CurPath.push_back(Cur);
    return findFriendship(Cur, 0);
  }
};
}

/// Search for a class P that EC is a friend of, under the constraint
///   InstanceContext <= P
/// if InstanceContext exists, or else
///   NamingClass <= P
/// and with the additional restriction that a protected member of
/// NamingClass would have some natural access in P, which implicitly
/// imposes the constraint that P <= NamingClass.
///
/// This isn't quite the condition laid out in the standard.
/// Instead of saying that a notional protected member of NamingClass
/// would have to have some natural access in P, it says the actual
/// target has to have some natural access in P, which opens up the
/// possibility that the target (which is not necessarily a member
/// of NamingClass) might be more accessible along some path not
/// passing through it.  That's really a bad idea, though, because it
/// introduces two problems:
///   - Most importantly, it breaks encapsulation because you can
///     access a forbidden base class's members by directly subclassing
///     it elsewhere.
///   - It also makes access substantially harder to compute because it
///     breaks the hill-climbing algorithm: knowing that the target is
///     accessible in some base class would no longer let you change
///     the question solely to whether the base class is accessible,
///     because the original target might have been more accessible
///     because of crazy subclassing.
/// So we don't implement that.
static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
                                           const CXXRecordDecl *InstanceContext,
                                           const CXXRecordDecl *NamingClass) {
  assert(InstanceContext == 0 ||
         InstanceContext->getCanonicalDecl() == InstanceContext);
  assert(NamingClass->getCanonicalDecl() == NamingClass);

  // If we don't have an instance context, our constraints give us
  // that NamingClass <= P <= NamingClass, i.e. P == NamingClass.
  // This is just the usual friendship check.
  if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);

  ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
  if (PRC.findFriendship(InstanceContext)) return AR_accessible;
  if (PRC.EverDependent) return AR_dependent;
  return AR_inaccessible;
}

static AccessResult HasAccess(Sema &S,
                              const EffectiveContext &EC,
                              const CXXRecordDecl *NamingClass,
                              AccessSpecifier Access,
                              const AccessTarget &Target) {
  assert(NamingClass->getCanonicalDecl() == NamingClass &&
         "declaration should be canonicalized before being passed here");

  if (Access == AS_public) return AR_accessible;
  assert(Access == AS_private || Access == AS_protected);

  AccessResult OnFailure = AR_inaccessible;

  for (EffectiveContext::record_iterator
         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
    // All the declarations in EC have been canonicalized, so pointer
    // equality from this point on will work fine.
    const CXXRecordDecl *ECRecord = *I;

    // [B2] and [M2]
    if (Access == AS_private) {
      if (ECRecord == NamingClass)
        return AR_accessible;

      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
        OnFailure = AR_dependent;

    // [B3] and [M3]
    } else {
      assert(Access == AS_protected);
      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
      case AR_accessible: break;
      case AR_inaccessible: continue;
      case AR_dependent: OnFailure = AR_dependent; continue;
      }

      // C++ [class.protected]p1:
      //   An additional access check beyond those described earlier in
      //   [class.access] is applied when a non-static data member or
      //   non-static member function is a protected member of its naming
      //   class.  As described earlier, access to a protected member is
      //   granted because the reference occurs in a friend or member of
      //   some class C.  If the access is to form a pointer to member,
      //   the nested-name-specifier shall name C or a class derived from
      //   C. All other accesses involve a (possibly implicit) object
      //   expression. In this case, the class of the object expression
      //   shall be C or a class derived from C.
      //
      // We interpret this as a restriction on [M3].

      // In this part of the code, 'C' is just our context class ECRecord.
      
      // These rules are different if we don't have an instance context.
      if (!Target.hasInstanceContext()) {
        // If it's not an instance member, these restrictions don't apply.
        if (!Target.isInstanceMember()) return AR_accessible;

        // If it's an instance member, use the pointer-to-member rule
        // that the naming class has to be derived from the effective
        // context.

        // Emulate a MSVC bug where the creation of pointer-to-member
        // to protected member of base class is allowed but only from
        // static member functions.
        if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
          if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
            if (MD->isStatic()) return AR_accessible;

        // Despite the standard's confident wording, there is a case
        // where you can have an instance member that's neither in a
        // pointer-to-member expression nor in a member access:  when
        // it names a field in an unevaluated context that can't be an
        // implicit member.  Pending clarification, we just apply the
        // same naming-class restriction here.
        //   FIXME: we're probably not correctly adding the
        //   protected-member restriction when we retroactively convert
        //   an expression to being evaluated.

        // We know that ECRecord derives from NamingClass.  The
        // restriction says to check whether NamingClass derives from
        // ECRecord, but that's not really necessary: two distinct
        // classes can't be recursively derived from each other.  So
        // along this path, we just need to check whether the classes
        // are equal.
        if (NamingClass == ECRecord) return AR_accessible;

        // Otherwise, this context class tells us nothing;  on to the next.
        continue;
      }

      assert(Target.isInstanceMember());

      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
      if (!InstanceContext) {
        OnFailure = AR_dependent;
        continue;
      }

      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
      case AR_accessible: return AR_accessible;
      case AR_inaccessible: continue;
      case AR_dependent: OnFailure = AR_dependent; continue;
      }
    }
  }

  // [M3] and [B3] say that, if the target is protected in N, we grant
  // access if the access occurs in a friend or member of some class P
  // that's a subclass of N and where the target has some natural
  // access in P.  The 'member' aspect is easy to handle because P
  // would necessarily be one of the effective-context records, and we
  // address that above.  The 'friend' aspect is completely ridiculous
  // to implement because there are no restrictions at all on P
  // *unless* the [class.protected] restriction applies.  If it does,
  // however, we should ignore whether the naming class is a friend,
  // and instead rely on whether any potential P is a friend.
  if (Access == AS_protected && Target.isInstanceMember()) {
    // Compute the instance context if possible.
    const CXXRecordDecl *InstanceContext = 0;
    if (Target.hasInstanceContext()) {
      InstanceContext = Target.resolveInstanceContext(S);
      if (!InstanceContext) return AR_dependent;
    }

    switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
    case AR_accessible: return AR_accessible;
    case AR_inaccessible: return OnFailure;
    case AR_dependent: return AR_dependent;
    }
    llvm_unreachable("impossible friendship kind");
  }

  switch (GetFriendKind(S, EC, NamingClass)) {
  case AR_accessible: return AR_accessible;
  case AR_inaccessible: return OnFailure;
  case AR_dependent: return AR_dependent;
  }

  // Silence bogus warnings
  llvm_unreachable("impossible friendship kind");
}

/// Finds the best path from the naming class to the declaring class,
/// taking friend declarations into account.
///
/// C++0x [class.access.base]p5:
///   A member m is accessible at the point R when named in class N if
///   [M1] m as a member of N is public, or
///   [M2] m as a member of N is private, and R occurs in a member or
///        friend of class N, or
///   [M3] m as a member of N is protected, and R occurs in a member or
///        friend of class N, or in a member or friend of a class P
///        derived from N, where m as a member of P is public, private,
///        or protected, or
///   [M4] there exists a base class B of N that is accessible at R, and
///        m is accessible at R when named in class B.
///
/// C++0x [class.access.base]p4:
///   A base class B of N is accessible at R, if
///   [B1] an invented public member of B would be a public member of N, or
///   [B2] R occurs in a member or friend of class N, and an invented public
///        member of B would be a private or protected member of N, or
///   [B3] R occurs in a member or friend of a class P derived from N, and an
///        invented public member of B would be a private or protected member
///        of P, or
///   [B4] there exists a class S such that B is a base class of S accessible
///        at R and S is a base class of N accessible at R.
///
/// Along a single inheritance path we can restate both of these
/// iteratively:
///
/// First, we note that M1-4 are equivalent to B1-4 if the member is
/// treated as a notional base of its declaring class with inheritance
/// access equivalent to the member's access.  Therefore we need only
/// ask whether a class B is accessible from a class N in context R.
///
/// Let B_1 .. B_n be the inheritance path in question (i.e. where
/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the
/// closest accessible base in the path:
///   Access(a, b) = (* access on the base specifier from a to b *)
///   Merge(a, forbidden) = forbidden
///   Merge(a, private) = forbidden
///   Merge(a, b) = min(a,b)
///   Accessible(c, forbidden) = false
///   Accessible(c, private) = (R is c) || IsFriend(c, R)
///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
///   Accessible(c, public) = true
///   ACAB(n) = public
///   ACAB(i) =
///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
///     if Accessible(B_i, AccessToBase) then public else AccessToBase
///
/// B is an accessible base of N at R iff ACAB(1) = public.
///
/// \param FinalAccess the access of the "final step", or AS_public if
///   there is no final step.
/// \return null if friendship is dependent
static CXXBasePath *FindBestPath(Sema &S,
                                 const EffectiveContext &EC,
                                 AccessTarget &Target,
                                 AccessSpecifier FinalAccess,
                                 CXXBasePaths &Paths) {
  // Derive the paths to the desired base.
  const CXXRecordDecl *Derived = Target.getNamingClass();
  const CXXRecordDecl *Base = Target.getDeclaringClass();

  // FIXME: fail correctly when there are dependent paths.
  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
                                          Paths);
  assert(isDerived && "derived class not actually derived from base");
  (void) isDerived;

  CXXBasePath *BestPath = 0;

  assert(FinalAccess != AS_none && "forbidden access after declaring class");

  bool AnyDependent = false;

  // Derive the friend-modified access along each path.
  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
         PI != PE; ++PI) {
    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();

    // Walk through the path backwards.
    AccessSpecifier PathAccess = FinalAccess;
    CXXBasePath::iterator I = PI->end(), E = PI->begin();
    while (I != E) {
      --I;

      assert(PathAccess != AS_none);

      // If the declaration is a private member of a base class, there
      // is no level of friendship in derived classes that can make it
      // accessible.
      if (PathAccess == AS_private) {
        PathAccess = AS_none;
        break;
      }

      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();

      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
      PathAccess = std::max(PathAccess, BaseAccess);

      switch (HasAccess(S, EC, NC, PathAccess, Target)) {
      case AR_inaccessible: break;
      case AR_accessible:
        PathAccess = AS_public;

        // Future tests are not against members and so do not have
        // instance context.
        Target.suppressInstanceContext();
        break;
      case AR_dependent:
        AnyDependent = true;
        goto Next;
      }
    }

    // Note that we modify the path's Access field to the
    // friend-modified access.
    if (BestPath == 0 || PathAccess < BestPath->Access) {
      BestPath = &*PI;
      BestPath->Access = PathAccess;

      // Short-circuit if we found a public path.
      if (BestPath->Access == AS_public)
        return BestPath;
    }

  Next: ;
  }

  assert((!BestPath || BestPath->Access != AS_public) &&
         "fell out of loop with public path");

  // We didn't find a public path, but at least one path was subject
  // to dependent friendship, so delay the check.
  if (AnyDependent)
    return 0;

  return BestPath;
}

/// Given that an entity has protected natural access, check whether
/// access might be denied because of the protected member access
/// restriction.
///
/// \return true if a note was emitted
static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
                                       AccessTarget &Target) {
  // Only applies to instance accesses.
  if (!Target.isInstanceMember())
    return false;

  assert(Target.isMemberAccess());

  const CXXRecordDecl *NamingClass = Target.getNamingClass();
  NamingClass = NamingClass->getCanonicalDecl();

  for (EffectiveContext::record_iterator
         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
    const CXXRecordDecl *ECRecord = *I;
    switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
    case AR_accessible: break;
    case AR_inaccessible: continue;
    case AR_dependent: continue;
    }

    // The effective context is a subclass of the declaring class.
    // Check whether the [class.protected] restriction is limiting
    // access.

    // To get this exactly right, this might need to be checked more
    // holistically;  it's not necessarily the case that gaining
    // access here would grant us access overall.

    NamedDecl *D = Target.getTargetDecl();

    // If we don't have an instance context, [class.protected] says the
    // naming class has to equal the context class.
    if (!Target.hasInstanceContext()) {
      // If it does, the restriction doesn't apply.
      if (NamingClass == ECRecord) continue;

      // TODO: it would be great to have a fixit here, since this is
      // such an obvious error.
      S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
        << S.Context.getTypeDeclType(ECRecord);
      return true;
    }

    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
    assert(InstanceContext && "diagnosing dependent access");

    switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
    case AR_accessible: continue;
    case AR_dependent: continue;
    case AR_inaccessible:
      break;
    }

    // Okay, the restriction seems to be what's limiting us.

    // Use a special diagnostic for constructors and destructors.
    if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) ||
        (isa<FunctionTemplateDecl>(D) &&
         isa<CXXConstructorDecl>(
                cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
      S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
        << isa<CXXDestructorDecl>(D);
      return true;
    }

    // Otherwise, use the generic diagnostic.
    S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
      << S.Context.getTypeDeclType(ECRecord);
    return true;
  }

  return false;
}

/// Diagnose the path which caused the given declaration or base class
/// to become inaccessible.
static void DiagnoseAccessPath(Sema &S,
                               const EffectiveContext &EC,
                               AccessTarget &Entity) {
  AccessSpecifier Access = Entity.getAccess();

  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();

  // Easy case: the decl's natural access determined its path access.
  // We have to check against AS_private here in case Access is AS_none,
  // indicating a non-public member of a private base class.
  if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
    switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
    case AR_inaccessible: {
      if (Access == AS_protected &&
          TryDiagnoseProtectedAccess(S, EC, Entity))
        return;

      // Find an original declaration.
      while (D->isOutOfLine()) {
        NamedDecl *PrevDecl = 0;
        if (VarDecl *VD = dyn_cast<VarDecl>(D))
          PrevDecl = VD->getPreviousDecl();
        else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
          PrevDecl = FD->getPreviousDecl();
        else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
          PrevDecl = TND->getPreviousDecl();
        else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
          if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
            break;
          PrevDecl = TD->getPreviousDecl();
        }
        if (!PrevDecl) break;
        D = PrevDecl;
      }

      CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
      Decl *ImmediateChild;
      if (D->getDeclContext() == DeclaringClass)
        ImmediateChild = D;
      else {
        DeclContext *DC = D->getDeclContext();
        while (DC->getParent() != DeclaringClass)
          DC = DC->getParent();
        ImmediateChild = cast<Decl>(DC);
      }
      
      // Check whether there's an AccessSpecDecl preceding this in the
      // chain of the DeclContext.
      bool Implicit = true;
      for (CXXRecordDecl::decl_iterator
             I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
           I != E; ++I) {
        if (*I == ImmediateChild) break;
        if (isa<AccessSpecDecl>(*I)) {
          Implicit = false;
          break;
        }
      }

      S.Diag(D->getLocation(), diag::note_access_natural)
        << (unsigned) (Access == AS_protected)
        << Implicit;
      return;
    }

    case AR_accessible: break;

    case AR_dependent:
      llvm_unreachable("can't diagnose dependent access failures");
    }
  }

  CXXBasePaths Paths;
  CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);

  CXXBasePath::iterator I = Path.end(), E = Path.begin();
  while (I != E) {
    --I;

    const CXXBaseSpecifier *BS = I->Base;
    AccessSpecifier BaseAccess = BS->getAccessSpecifier();

    // If this is public inheritance, or the derived class is a friend,
    // skip this step.
    if (BaseAccess == AS_public)
      continue;

    switch (GetFriendKind(S, EC, I->Class)) {
    case AR_accessible: continue;
    case AR_inaccessible: break;
    case AR_dependent:
      llvm_unreachable("can't diagnose dependent access failures");
    }

    // Check whether this base specifier is the tighest point
    // constraining access.  We have to check against AS_private for
    // the same reasons as above.
    if (BaseAccess == AS_private || BaseAccess >= Access) {

      // We're constrained by inheritance, but we want to say
      // "declared private here" if we're diagnosing a hierarchy
      // conversion and this is the final step.
      unsigned diagnostic;
      if (D) diagnostic = diag::note_access_constrained_by_path;
      else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
      else diagnostic = diag::note_access_constrained_by_path;

      S.Diag(BS->getSourceRange().getBegin(), diagnostic)
        << BS->getSourceRange()
        << (BaseAccess == AS_protected)
        << (BS->getAccessSpecifierAsWritten() == AS_none);
      
      if (D)
        S.Diag(D->getLocation(), diag::note_field_decl);
      
      return;
    }
  }

  llvm_unreachable("access not apparently constrained by path");
}

static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
                              const EffectiveContext &EC,
                              AccessTarget &Entity) {
  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);

  S.Diag(Loc, Entity.getDiag())
    << (Entity.getAccess() == AS_protected)
    << (D ? D->getDeclName() : DeclarationName())
    << S.Context.getTypeDeclType(NamingClass)
    << S.Context.getTypeDeclType(DeclaringClass);
  DiagnoseAccessPath(S, EC, Entity);
}

/// MSVC has a bug where if during an using declaration name lookup, 
/// the declaration found is unaccessible (private) and that declaration 
/// was bring into scope via another using declaration whose target
/// declaration is accessible (public) then no error is generated.
/// Example:
///   class A {
///   public:
///     int f();
///   };
///   class B : public A {
///   private:
///     using A::f;
///   };
///   class C : public B {
///   private:
///     using B::f;
///   };
///
/// Here, B::f is private so this should fail in Standard C++, but 
/// because B::f refers to A::f which is public MSVC accepts it.
static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 
                                                 SourceLocation AccessLoc,
                                                 AccessTarget &Entity) {
  if (UsingShadowDecl *Shadow =
                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
    if (Entity.getTargetDecl()->getAccess() == AS_private && 
        (OrigDecl->getAccess() == AS_public ||
         OrigDecl->getAccess() == AS_protected)) {
      S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
        << Shadow->getUsingDecl()->getQualifiedNameAsString()
        << OrigDecl->getQualifiedNameAsString();
      return true;
    }
  }
  return false;
}

/// Determines whether the accessed entity is accessible.  Public members
/// have been weeded out by this point.
static AccessResult IsAccessible(Sema &S,
                                 const EffectiveContext &EC,
                                 AccessTarget &Entity) {
  // Determine the actual naming class.
  CXXRecordDecl *NamingClass = Entity.getNamingClass();
  while (NamingClass->isAnonymousStructOrUnion())
    NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
  NamingClass = NamingClass->getCanonicalDecl();

  AccessSpecifier UnprivilegedAccess = Entity.getAccess();
  assert(UnprivilegedAccess != AS_public && "public access not weeded out");

  // Before we try to recalculate access paths, try to white-list
  // accesses which just trade in on the final step, i.e. accesses
  // which don't require [M4] or [B4]. These are by far the most
  // common forms of privileged access.
  if (UnprivilegedAccess != AS_none) {
    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
    case AR_dependent:
      // This is actually an interesting policy decision.  We don't
      // *have* to delay immediately here: we can do the full access
      // calculation in the hope that friendship on some intermediate
      // class will make the declaration accessible non-dependently.
      // But that's not cheap, and odds are very good (note: assertion
      // made without data) that the friend declaration will determine
      // access.
      return AR_dependent;

    case AR_accessible: return AR_accessible;
    case AR_inaccessible: break;
    }
  }

  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();

  // We lower member accesses to base accesses by pretending that the
  // member is a base class of its declaring class.
  AccessSpecifier FinalAccess;

  if (Entity.isMemberAccess()) {
    // Determine if the declaration is accessible from EC when named
    // in its declaring class.
    NamedDecl *Target = Entity.getTargetDecl();
    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();

    FinalAccess = Target->getAccess();
    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
    case AR_accessible:
      FinalAccess = AS_public;
      break;
    case AR_inaccessible: break;
    case AR_dependent: return AR_dependent; // see above
    }

    if (DeclaringClass == NamingClass)
      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);

    Entity.suppressInstanceContext();
  } else {
    FinalAccess = AS_public;
  }

  assert(Entity.getDeclaringClass() != NamingClass);

  // Append the declaration's access if applicable.
  CXXBasePaths Paths;
  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
  if (!Path)
    return AR_dependent;

  assert(Path->Access <= UnprivilegedAccess &&
         "access along best path worse than direct?");
  if (Path->Access == AS_public)
    return AR_accessible;
  return AR_inaccessible;
}

static void DelayDependentAccess(Sema &S,
                                 const EffectiveContext &EC,
                                 SourceLocation Loc,
                                 const AccessTarget &Entity) {
  assert(EC.isDependent() && "delaying non-dependent access");
  DeclContext *DC = EC.getInnerContext();
  assert(DC->isDependentContext() && "delaying non-dependent access");
  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
                              Loc,
                              Entity.isMemberAccess(),
                              Entity.getAccess(),
                              Entity.getTargetDecl(),
                              Entity.getNamingClass(),
                              Entity.getBaseObjectType(),
                              Entity.getDiag());
}

/// Checks access to an entity from the given effective context.
static AccessResult CheckEffectiveAccess(Sema &S,
                                         const EffectiveContext &EC,
                                         SourceLocation Loc,
                                         AccessTarget &Entity) {
  assert(Entity.getAccess() != AS_public && "called for public access!");

  if (S.getLangOpts().MicrosoftMode &&
      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
    return AR_accessible;

  switch (IsAccessible(S, EC, Entity)) {
  case AR_dependent:
    DelayDependentAccess(S, EC, Loc, Entity);
    return AR_dependent;

  case AR_inaccessible:
    if (!Entity.isQuiet())
      DiagnoseBadAccess(S, Loc, EC, Entity);
    return AR_inaccessible;

  case AR_accessible:
    return AR_accessible;
  }

  // silence unnecessary warning
  llvm_unreachable("invalid access result");
}

static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
                                      AccessTarget &Entity) {
  // If the access path is public, it's accessible everywhere.
  if (Entity.getAccess() == AS_public)
    return Sema::AR_accessible;

  // If we're currently parsing a declaration, we may need to delay
  // access control checking, because our effective context might be
  // different based on what the declaration comes out as.
  //
  // For example, we might be parsing a declaration with a scope
  // specifier, like this:
  //   A::private_type A::foo() { ... }
  //
  // Or we might be parsing something that will turn out to be a friend:
  //   void foo(A::private_type);
  //   void B::foo(A::private_type);
  if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
    S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
    return Sema::AR_delayed;
  }

  EffectiveContext EC(S.CurContext);
  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
  case AR_accessible: return Sema::AR_accessible;
  case AR_inaccessible: return Sema::AR_inaccessible;
  case AR_dependent: return Sema::AR_dependent;
  }
  llvm_unreachable("falling off end");
}

void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) {
  // Access control for names used in the declarations of functions
  // and function templates should normally be evaluated in the context
  // of the declaration, just in case it's a friend of something.
  // However, this does not apply to local extern declarations.

  DeclContext *DC = decl->getDeclContext();
  if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
    if (!DC->isFunctionOrMethod()) DC = fn;
  } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) {
    // Never a local declaration.
    DC = fnt->getTemplatedDecl();
  }

  EffectiveContext EC(DC);

  AccessTarget Target(DD.getAccessData());

  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
    DD.Triggered = true;
}

void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
                        const MultiLevelTemplateArgumentList &TemplateArgs) {
  SourceLocation Loc = DD.getAccessLoc();
  AccessSpecifier Access = DD.getAccess();

  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
                                       TemplateArgs);
  if (!NamingD) return;
  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
                                       TemplateArgs);
  if (!TargetD) return;

  if (DD.isAccessToMember()) {
    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
    QualType BaseObjectType = DD.getAccessBaseObjectType();
    if (!BaseObjectType.isNull()) {
      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
                                 DeclarationName());
      if (BaseObjectType.isNull()) return;
    }

    AccessTarget Entity(Context,
                        AccessTarget::Member,
                        NamingClass,
                        DeclAccessPair::make(TargetDecl, Access),
                        BaseObjectType);
    Entity.setDiag(DD.getDiagnostic());
    CheckAccess(*this, Loc, Entity);
  } else {
    AccessTarget Entity(Context,
                        AccessTarget::Base,
                        cast<CXXRecordDecl>(TargetD),
                        cast<CXXRecordDecl>(NamingD),
                        Access);
    Entity.setDiag(DD.getDiagnostic());
    CheckAccess(*this, Loc, Entity);
  }
}

Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
                                                     DeclAccessPair Found) {
  if (!getLangOpts().AccessControl ||
      !E->getNamingClass() ||
      Found.getAccess() == AS_public)
    return AR_accessible;

  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 
                      Found, QualType());
  Entity.setDiag(diag::err_access) << E->getSourceRange();

  return CheckAccess(*this, E->getNameLoc(), Entity);
}

/// Perform access-control checking on a previously-unresolved member
/// access which has now been resolved to a member.
Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
                                                     DeclAccessPair Found) {
  if (!getLangOpts().AccessControl ||
      Found.getAccess() == AS_public)
    return AR_accessible;

  QualType BaseType = E->getBaseType();
  if (E->isArrow())
    BaseType = BaseType->getAs<PointerType>()->getPointeeType();

  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
                      Found, BaseType);
  Entity.setDiag(diag::err_access) << E->getSourceRange();

  return CheckAccess(*this, E->getMemberLoc(), Entity);
}

/// Is the given special member function accessible for the purposes of
/// deciding whether to define a special member function as deleted?
bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
                                                AccessSpecifier access,
                                                QualType objectType) {
  // Fast path.
  if (access == AS_public || !getLangOpts().AccessControl) return true;

  AccessTarget entity(Context, AccessTarget::Member, decl->getParent(),
                      DeclAccessPair::make(decl, access), objectType);

  // Suppress diagnostics.
  entity.setDiag(PDiag());

  switch (CheckAccess(*this, SourceLocation(), entity)) {
  case AR_accessible: return true;
  case AR_inaccessible: return false;
  case AR_dependent: llvm_unreachable("dependent for =delete computation");
  case AR_delayed: llvm_unreachable("cannot delay =delete computation");
  }
  llvm_unreachable("bad access result");
}

Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
                                               CXXDestructorDecl *Dtor,
                                               const PartialDiagnostic &PDiag,
                                               QualType ObjectTy) {
  if (!getLangOpts().AccessControl)
    return AR_accessible;

  // There's never a path involved when checking implicit destructor access.
  AccessSpecifier Access = Dtor->getAccess();
  if (Access == AS_public)
    return AR_accessible;

  CXXRecordDecl *NamingClass = Dtor->getParent();
  if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass);

  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
                      DeclAccessPair::make(Dtor, Access),
                      ObjectTy);
  Entity.setDiag(PDiag); // TODO: avoid copy

  return CheckAccess(*this, Loc, Entity);
}

/// Checks access to a constructor.
Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
                                                CXXConstructorDecl *Constructor,
                                                const InitializedEntity &Entity,
                                                AccessSpecifier Access,
                                                bool IsCopyBindingRefToTemp) {
  if (!getLangOpts().AccessControl || Access == AS_public)
    return AR_accessible;

  PartialDiagnostic PD(PDiag());
  switch (Entity.getKind()) {
  default:
    PD = PDiag(IsCopyBindingRefToTemp
                 ? diag::ext_rvalue_to_reference_access_ctor
                 : diag::err_access_ctor);

    break;

  case InitializedEntity::EK_Base:
    PD = PDiag(diag::err_access_base_ctor);
    PD << Entity.isInheritedVirtualBase()
       << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
    break;

  case InitializedEntity::EK_Member: {
    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
    PD = PDiag(diag::err_access_field_ctor);
    PD << Field->getType() << getSpecialMember(Constructor);
    break;
  }

  case InitializedEntity::EK_LambdaCapture: {
    const VarDecl *Var = Entity.getCapturedVar();
    PD = PDiag(diag::err_access_lambda_capture);
    PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor);
    break;
  }

  }

  return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD);
}

/// Checks access to a constructor.
Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
                                                CXXConstructorDecl *Constructor,
                                                const InitializedEntity &Entity,
                                                AccessSpecifier Access,
                                                const PartialDiagnostic &PD) {
  if (!getLangOpts().AccessControl ||
      Access == AS_public)
    return AR_accessible;

  CXXRecordDecl *NamingClass = Constructor->getParent();

  // Initializing a base sub-object is an instance method call on an
  // object of the derived class.  Otherwise, we have an instance method
  // call on an object of the constructed type.
  CXXRecordDecl *ObjectClass;
  if (Entity.getKind() == InitializedEntity::EK_Base) {
    ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent();
  } else {
    ObjectClass = NamingClass;
  }

  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
                            DeclAccessPair::make(Constructor, Access),
                            Context.getTypeDeclType(ObjectClass));
  AccessEntity.setDiag(PD);

  return CheckAccess(*this, UseLoc, AccessEntity);
} 

/// Checks direct (i.e. non-inherited) access to an arbitrary class
/// member.
Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
                                                 NamedDecl *Target,
                                           const PartialDiagnostic &Diag) {
  AccessSpecifier Access = Target->getAccess();
  if (!getLangOpts().AccessControl ||
      Access == AS_public)
    return AR_accessible;

  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
                      DeclAccessPair::make(Target, Access),
                      QualType());
  Entity.setDiag(Diag);
  return CheckAccess(*this, UseLoc, Entity);
}
                                           

/// Checks access to an overloaded operator new or delete.
Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
                                               SourceRange PlacementRange,
                                               CXXRecordDecl *NamingClass,
                                               DeclAccessPair Found,
                                               bool Diagnose) {
  if (!getLangOpts().AccessControl ||
      !NamingClass ||
      Found.getAccess() == AS_public)
    return AR_accessible;

  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
                      QualType());
  if (Diagnose)
    Entity.setDiag(diag::err_access)
      << PlacementRange;

  return CheckAccess(*this, OpLoc, Entity);
}

/// Checks access to an overloaded member operator, including
/// conversion operators.
Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
                                                   Expr *ObjectExpr,
                                                   Expr *ArgExpr,
                                                   DeclAccessPair Found) {
  if (!getLangOpts().AccessControl ||
      Found.getAccess() == AS_public)
    return AR_accessible;

  const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>();
  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());

  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
                      ObjectExpr->getType());
  Entity.setDiag(diag::err_access)
    << ObjectExpr->getSourceRange()
    << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());

  return CheckAccess(*this, OpLoc, Entity);
}

Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
                                                    DeclAccessPair Found) {
  if (!getLangOpts().AccessControl ||
      Found.getAccess() == AS_none ||
      Found.getAccess() == AS_public)
    return AR_accessible;

  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;
  CXXRecordDecl *NamingClass = Ovl->getNamingClass();

  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
                      /*no instance context*/ QualType());
  Entity.setDiag(diag::err_access)
    << Ovl->getSourceRange();

  return CheckAccess(*this, Ovl->getNameLoc(), Entity);
}

/// Checks access for a hierarchy conversion.
///
/// \param ForceCheck true if this check should be performed even if access
///     control is disabled;  some things rely on this for semantics
/// \param ForceUnprivileged true if this check should proceed as if the
///     context had no special privileges
Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
                                              QualType Base,
                                              QualType Derived,
                                              const CXXBasePath &Path,
                                              unsigned DiagID,
                                              bool ForceCheck,
                                              bool ForceUnprivileged) {
  if (!ForceCheck && !getLangOpts().AccessControl)
    return AR_accessible;

  if (Path.Access == AS_public)
    return AR_accessible;

  CXXRecordDecl *BaseD, *DerivedD;
  BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
  DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());

  AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 
                      Path.Access);
  if (DiagID)
    Entity.setDiag(DiagID) << Derived << Base;

  if (ForceUnprivileged) {
    switch (CheckEffectiveAccess(*this, EffectiveContext(),
                                 AccessLoc, Entity)) {
    case ::AR_accessible: return Sema::AR_accessible;
    case ::AR_inaccessible: return Sema::AR_inaccessible;
    case ::AR_dependent: return Sema::AR_dependent;
    }
    llvm_unreachable("unexpected result from CheckEffectiveAccess");
  }
  return CheckAccess(*this, AccessLoc, Entity);
}

/// Checks access to all the declarations in the given result set.
void Sema::CheckLookupAccess(const LookupResult &R) {
  assert(getLangOpts().AccessControl
         && "performing access check without access control");
  assert(R.getNamingClass() && "performing access check without naming class");

  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
    if (I.getAccess() != AS_public) {
      AccessTarget Entity(Context, AccessedEntity::Member,
                          R.getNamingClass(), I.getPair(),
                          R.getBaseObjectType());
      Entity.setDiag(diag::err_access);
      CheckAccess(*this, R.getNameLoc(), Entity);
    }
  }
}

/// Checks access to Decl from the given class. The check will take access
/// specifiers into account, but no member access expressions and such.
///
/// \param Decl the declaration to check if it can be accessed
/// \param Class the class/context from which to start the search
/// \return true if the Decl is accessible from the Class, false otherwise.
bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
  if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) {
    if (!Decl->isCXXClassMember())
      return true;

    QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
    AccessTarget Entity(Context, AccessedEntity::Member, Class,
                        DeclAccessPair::make(Decl, Decl->getAccess()),
                        qType);
    if (Entity.getAccess() == AS_public)
      return true;

    EffectiveContext EC(CurContext);
    return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
  }
  
  if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) {
    // @public and @package ivars are always accessible.
    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||
        Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)
      return true;
    
    
    
    // If we are inside a class or category implementation, determine the
    // interface we're in.
    ObjCInterfaceDecl *ClassOfMethodDecl = 0;
    if (ObjCMethodDecl *MD = getCurMethodDecl())
      ClassOfMethodDecl =  MD->getClassInterface();
    else if (FunctionDecl *FD = getCurFunctionDecl()) {
      if (ObjCImplDecl *Impl 
            = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) {
        if (ObjCImplementationDecl *IMPD
              = dyn_cast<ObjCImplementationDecl>(Impl))
          ClassOfMethodDecl = IMPD->getClassInterface();
        else if (ObjCCategoryImplDecl* CatImplClass
                   = dyn_cast<ObjCCategoryImplDecl>(Impl))
          ClassOfMethodDecl = CatImplClass->getClassInterface();
      }
    }
    
    // If we're not in an interface, this ivar is inaccessible.
    if (!ClassOfMethodDecl)
      return false;
    
    // If we're inside the same interface that owns the ivar, we're fine.
    if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))
      return true;
    
    // If the ivar is private, it's inaccessible.
    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private)
      return false;
    
    return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);
  }
  
  return true;
}
