brintos

brintos / llvm-project-archived public Read only

0
0
Text · 70.3 KiB · 17415b4 Raw
1979 lines · cpp
1//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides Sema routines for C++ access control semantics.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/CXXInheritance.h"15#include "clang/AST/DeclCXX.h"16#include "clang/AST/DeclFriend.h"17#include "clang/AST/DeclObjC.h"18#include "clang/AST/DependentDiagnostic.h"19#include "clang/AST/ExprCXX.h"20#include "clang/Basic/Specifiers.h"21#include "clang/Sema/DelayedDiagnostic.h"22#include "clang/Sema/Initialization.h"23#include "clang/Sema/Lookup.h"24 25using namespace clang;26using namespace sema;27 28/// A copy of Sema's enum without AR_delayed.29enum AccessResult {30  AR_accessible,31  AR_inaccessible,32  AR_dependent33};34 35bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,36                                    NamedDecl *PrevMemberDecl,37                                    AccessSpecifier LexicalAS) {38  if (!PrevMemberDecl) {39    // Use the lexical access specifier.40    MemberDecl->setAccess(LexicalAS);41    return false;42  }43 44  // C++ [class.access.spec]p3: When a member is redeclared its access45  // specifier must be same as its initial declaration.46  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {47    Diag(MemberDecl->getLocation(),48         diag::err_class_redeclared_with_different_access)49      << MemberDecl << LexicalAS;50    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)51      << PrevMemberDecl << PrevMemberDecl->getAccess();52 53    MemberDecl->setAccess(LexicalAS);54    return true;55  }56 57  MemberDecl->setAccess(PrevMemberDecl->getAccess());58  return false;59}60 61static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {62  DeclContext *DC = D->getDeclContext();63 64  // This can only happen at top: enum decls only "publish" their65  // immediate members.66  if (isa<EnumDecl>(DC))67    DC = cast<EnumDecl>(DC)->getDeclContext();68 69  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);70  while (DeclaringClass->isAnonymousStructOrUnion())71    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());72  return DeclaringClass;73}74 75namespace {76struct EffectiveContext {77  EffectiveContext() : Inner(nullptr), Dependent(false) {}78 79  explicit EffectiveContext(DeclContext *DC)80    : Inner(DC),81      Dependent(DC->isDependentContext()) {82 83    // An implicit deduction guide is semantically in the context enclosing the84    // class template, but for access purposes behaves like the constructor85    // from which it was produced.86    if (auto *DGD = dyn_cast<CXXDeductionGuideDecl>(DC)) {87      if (DGD->isImplicit()) {88        DC = DGD->getCorrespondingConstructor();89        if (!DC) {90          // The copy deduction candidate doesn't have a corresponding91          // constructor.92          DC = cast<DeclContext>(DGD->getDeducedTemplate()->getTemplatedDecl());93        }94      }95    }96 97    // C++11 [class.access.nest]p1:98    //   A nested class is a member and as such has the same access99    //   rights as any other member.100    // C++11 [class.access]p2:101    //   A member of a class can also access all the names to which102    //   the class has access.  A local class of a member function103    //   may access the same names that the member function itself104    //   may access.105    // This almost implies that the privileges of nesting are transitive.106    // Technically it says nothing about the local classes of non-member107    // functions (which can gain privileges through friendship), but we108    // take that as an oversight.109    while (true) {110      // We want to add canonical declarations to the EC lists for111      // simplicity of checking, but we need to walk up through the112      // actual current DC chain.  Otherwise, something like a local113      // extern or friend which happens to be the canonical114      // declaration will really mess us up.115 116      if (isa<CXXRecordDecl>(DC)) {117        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);118        Records.push_back(Record->getCanonicalDecl());119        DC = Record->getDeclContext();120      } else if (isa<FunctionDecl>(DC)) {121        FunctionDecl *Function = cast<FunctionDecl>(DC);122        Functions.push_back(Function->getCanonicalDecl());123        if (Function->getFriendObjectKind())124          DC = Function->getLexicalDeclContext();125        else126          DC = Function->getDeclContext();127      } else if (DC->isFileContext()) {128        break;129      } else {130        DC = DC->getParent();131      }132    }133  }134 135  bool isDependent() const { return Dependent; }136 137  bool includesClass(const CXXRecordDecl *R) const {138    R = R->getCanonicalDecl();139    return llvm::is_contained(Records, R);140  }141 142  /// Retrieves the innermost "useful" context.  Can be null if we're143  /// doing access-control without privileges.144  DeclContext *getInnerContext() const {145    return Inner;146  }147 148  typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;149 150  DeclContext *Inner;151  SmallVector<FunctionDecl*, 4> Functions;152  SmallVector<CXXRecordDecl*, 4> Records;153  bool Dependent;154};155 156/// Like sema::AccessedEntity, but kindly lets us scribble all over157/// it.158struct AccessTarget : public AccessedEntity {159  AccessTarget(const AccessedEntity &Entity)160    : AccessedEntity(Entity) {161    initialize();162  }163 164  AccessTarget(ASTContext &Context,165               MemberNonce _,166               CXXRecordDecl *NamingClass,167               DeclAccessPair FoundDecl,168               QualType BaseObjectType)169    : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass,170                     FoundDecl, BaseObjectType) {171    initialize();172  }173 174  AccessTarget(ASTContext &Context,175               BaseNonce _,176               CXXRecordDecl *BaseClass,177               CXXRecordDecl *DerivedClass,178               AccessSpecifier Access)179    : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,180                     Access) {181    initialize();182  }183 184  bool isInstanceMember() const {185    return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());186  }187 188  bool hasInstanceContext() const {189    return HasInstanceContext;190  }191 192  class SavedInstanceContext {193  public:194    SavedInstanceContext(SavedInstanceContext &&S)195        : Target(S.Target), Has(S.Has) {196      S.Target = nullptr;197    }198 199    // The move assignment operator is defined as deleted pending further200    // motivation.201    SavedInstanceContext &operator=(SavedInstanceContext &&) = delete;202 203    // The copy constrcutor and copy assignment operator is defined as deleted204    // pending further motivation.205    SavedInstanceContext(const SavedInstanceContext &) = delete;206    SavedInstanceContext &operator=(const SavedInstanceContext &) = delete;207 208    ~SavedInstanceContext() {209      if (Target)210        Target->HasInstanceContext = Has;211    }212 213  private:214    friend struct AccessTarget;215    explicit SavedInstanceContext(AccessTarget &Target)216        : Target(&Target), Has(Target.HasInstanceContext) {}217    AccessTarget *Target;218    bool Has;219  };220 221  SavedInstanceContext saveInstanceContext() {222    return SavedInstanceContext(*this);223  }224 225  void suppressInstanceContext() {226    HasInstanceContext = false;227  }228 229  const CXXRecordDecl *resolveInstanceContext(Sema &S) const {230    assert(HasInstanceContext);231    if (CalculatedInstanceContext)232      return InstanceContext;233 234    CalculatedInstanceContext = true;235    DeclContext *IC = S.computeDeclContext(getBaseObjectType());236    InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl()237                          : nullptr);238    return InstanceContext;239  }240 241  const CXXRecordDecl *getDeclaringClass() const {242    return DeclaringClass;243  }244 245  /// The "effective" naming class is the canonical non-anonymous246  /// class containing the actual naming class.247  const CXXRecordDecl *getEffectiveNamingClass() const {248    const CXXRecordDecl *namingClass = getNamingClass();249    while (namingClass->isAnonymousStructOrUnion())250      namingClass = cast<CXXRecordDecl>(namingClass->getParent());251    return namingClass->getCanonicalDecl();252  }253 254private:255  void initialize() {256    HasInstanceContext = (isMemberAccess() &&257                          !getBaseObjectType().isNull() &&258                          getTargetDecl()->isCXXInstanceMember());259    CalculatedInstanceContext = false;260    InstanceContext = nullptr;261 262    if (isMemberAccess())263      DeclaringClass = FindDeclaringClass(getTargetDecl());264    else265      DeclaringClass = getBaseClass();266    DeclaringClass = DeclaringClass->getCanonicalDecl();267  }268 269  bool HasInstanceContext : 1;270  mutable bool CalculatedInstanceContext : 1;271  mutable const CXXRecordDecl *InstanceContext;272  const CXXRecordDecl *DeclaringClass;273};274 275}276 277/// Checks whether one class might instantiate to the other.278static bool MightInstantiateTo(const CXXRecordDecl *From,279                               const CXXRecordDecl *To) {280  // Declaration names are always preserved by instantiation.281  if (From->getDeclName() != To->getDeclName())282    return false;283 284  const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();285  const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();286  if (FromDC == ToDC) return true;287  if (FromDC->isFileContext() || ToDC->isFileContext()) return false;288 289  // Be conservative.290  return true;291}292 293/// Checks whether one class is derived from another, inclusively.294/// Properly indicates when it couldn't be determined due to295/// dependence.296///297/// This should probably be donated to AST or at least Sema.298static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,299                                           const CXXRecordDecl *Target) {300  assert(Derived->getCanonicalDecl() == Derived);301  assert(Target->getCanonicalDecl() == Target);302 303  if (Derived == Target) return AR_accessible;304 305  bool CheckDependent = Derived->isDependentContext();306  if (CheckDependent && MightInstantiateTo(Derived, Target))307    return AR_dependent;308 309  AccessResult OnFailure = AR_inaccessible;310  SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack311 312  while (true) {313    if (Derived->isDependentContext() && !Derived->hasDefinition() &&314        !Derived->isLambda())315      return AR_dependent;316 317    for (const auto &I : Derived->bases()) {318      const CXXRecordDecl *RD;319 320      QualType T = I.getType();321      if (CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) {322        RD = Rec;323      } else {324        assert(T->isDependentType() && "non-dependent base wasn't a record?");325        OnFailure = AR_dependent;326        continue;327      }328 329      RD = RD->getCanonicalDecl();330      if (RD == Target) return AR_accessible;331      if (CheckDependent && MightInstantiateTo(RD, Target))332        OnFailure = AR_dependent;333 334      Queue.push_back(RD);335    }336 337    if (Queue.empty()) break;338 339    Derived = Queue.pop_back_val();340  }341 342  return OnFailure;343}344 345 346static bool MightInstantiateTo(Sema &S, DeclContext *Context,347                               DeclContext *Friend) {348  if (Friend == Context)349    return true;350 351  assert(!Friend->isDependentContext() &&352         "can't handle friends with dependent contexts here");353 354  if (!Context->isDependentContext())355    return false;356 357  if (Friend->isFileContext())358    return false;359 360  // TODO: this is very conservative361  return true;362}363 364// Asks whether the type in 'context' can ever instantiate to the type365// in 'friend'.366static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {367  if (Friend == Context)368    return true;369 370  if (!Friend->isDependentType() && !Context->isDependentType())371    return false;372 373  // TODO: this is very conservative.374  return true;375}376 377static bool MightInstantiateTo(Sema &S,378                               FunctionDecl *Context,379                               FunctionDecl *Friend) {380  if (Context->getDeclName() != Friend->getDeclName())381    return false;382 383  if (!MightInstantiateTo(S,384                          Context->getDeclContext(),385                          Friend->getDeclContext()))386    return false;387 388  CanQual<FunctionProtoType> FriendTy389    = S.Context.getCanonicalType(Friend->getType())390         ->getAs<FunctionProtoType>();391  CanQual<FunctionProtoType> ContextTy392    = S.Context.getCanonicalType(Context->getType())393         ->getAs<FunctionProtoType>();394 395  // There isn't any way that I know of to add qualifiers396  // during instantiation.397  if (FriendTy.getQualifiers() != ContextTy.getQualifiers())398    return false;399 400  if (FriendTy->getNumParams() != ContextTy->getNumParams())401    return false;402 403  if (!MightInstantiateTo(S, ContextTy->getReturnType(),404                          FriendTy->getReturnType()))405    return false;406 407  for (unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I)408    if (!MightInstantiateTo(S, ContextTy->getParamType(I),409                            FriendTy->getParamType(I)))410      return false;411 412  return true;413}414 415static bool MightInstantiateTo(Sema &S,416                               FunctionTemplateDecl *Context,417                               FunctionTemplateDecl *Friend) {418  return MightInstantiateTo(S,419                            Context->getTemplatedDecl(),420                            Friend->getTemplatedDecl());421}422 423static AccessResult MatchesFriend(Sema &S,424                                  const EffectiveContext &EC,425                                  const CXXRecordDecl *Friend) {426  if (EC.includesClass(Friend))427    return AR_accessible;428 429  if (EC.isDependent()) {430    for (const CXXRecordDecl *Context : EC.Records) {431      if (MightInstantiateTo(Context, Friend))432        return AR_dependent;433    }434  }435 436  return AR_inaccessible;437}438 439static AccessResult MatchesFriend(Sema &S,440                                  const EffectiveContext &EC,441                                  CanQualType Friend) {442  if (const auto *RD = Friend->getAsCXXRecordDecl())443    return MatchesFriend(S, EC, RD);444 445  // TODO: we can do better than this446  if (Friend->isDependentType())447    return AR_dependent;448 449  return AR_inaccessible;450}451 452/// Determines whether the given friend class template matches453/// anything in the effective context.454static AccessResult MatchesFriend(Sema &S,455                                  const EffectiveContext &EC,456                                  ClassTemplateDecl *Friend) {457  AccessResult OnFailure = AR_inaccessible;458 459  // Check whether the friend is the template of a class in the460  // context chain.461  for (SmallVectorImpl<CXXRecordDecl*>::const_iterator462         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {463    CXXRecordDecl *Record = *I;464 465    // Figure out whether the current class has a template:466    ClassTemplateDecl *CTD;467 468    // A specialization of the template...469    if (isa<ClassTemplateSpecializationDecl>(Record)) {470      CTD = cast<ClassTemplateSpecializationDecl>(Record)471        ->getSpecializedTemplate();472 473    // ... or the template pattern itself.474    } else {475      CTD = Record->getDescribedClassTemplate();476      if (!CTD) continue;477    }478 479    // It's a match.480    if (Friend == CTD->getCanonicalDecl())481      return AR_accessible;482 483    // If the context isn't dependent, it can't be a dependent match.484    if (!EC.isDependent())485      continue;486 487    // If the template names don't match, it can't be a dependent488    // match.489    if (CTD->getDeclName() != Friend->getDeclName())490      continue;491 492    // If the class's context can't instantiate to the friend's493    // context, it can't be a dependent match.494    if (!MightInstantiateTo(S, CTD->getDeclContext(),495                            Friend->getDeclContext()))496      continue;497 498    // Otherwise, it's a dependent match.499    OnFailure = AR_dependent;500  }501 502  return OnFailure;503}504 505/// Determines whether the given friend function matches anything in506/// the effective context.507static AccessResult MatchesFriend(Sema &S,508                                  const EffectiveContext &EC,509                                  FunctionDecl *Friend) {510  AccessResult OnFailure = AR_inaccessible;511 512  for (SmallVectorImpl<FunctionDecl*>::const_iterator513         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {514    if (Friend == *I)515      return AR_accessible;516 517    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))518      OnFailure = AR_dependent;519  }520 521  return OnFailure;522}523 524/// Determines whether the given friend function template matches525/// anything in the effective context.526static AccessResult MatchesFriend(Sema &S,527                                  const EffectiveContext &EC,528                                  FunctionTemplateDecl *Friend) {529  if (EC.Functions.empty()) return AR_inaccessible;530 531  AccessResult OnFailure = AR_inaccessible;532 533  for (SmallVectorImpl<FunctionDecl*>::const_iterator534         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {535 536    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();537    if (!FTD)538      FTD = (*I)->getDescribedFunctionTemplate();539    if (!FTD)540      continue;541 542    FTD = FTD->getCanonicalDecl();543 544    if (Friend == FTD)545      return AR_accessible;546 547    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))548      OnFailure = AR_dependent;549  }550 551  return OnFailure;552}553 554/// Determines whether the given friend declaration matches anything555/// in the effective context.556static AccessResult MatchesFriend(Sema &S,557                                  const EffectiveContext &EC,558                                  FriendDecl *FriendD) {559  // Whitelist accesses if there's an invalid or unsupported friend560  // declaration.561  if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())562    return AR_accessible;563 564  if (TypeSourceInfo *T = FriendD->getFriendType())565    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());566 567  NamedDecl *Friend568    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());569 570  // FIXME: declarations with dependent or templated scope.571 572  if (isa<ClassTemplateDecl>(Friend))573    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));574 575  if (isa<FunctionTemplateDecl>(Friend))576    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));577 578  if (isa<CXXRecordDecl>(Friend))579    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));580 581  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");582  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));583}584 585static AccessResult GetFriendKind(Sema &S,586                                  const EffectiveContext &EC,587                                  const CXXRecordDecl *Class) {588  AccessResult OnFailure = AR_inaccessible;589 590  // Okay, check friends.591  for (auto *Friend : Class->friends()) {592    switch (MatchesFriend(S, EC, Friend)) {593    case AR_accessible:594      return AR_accessible;595 596    case AR_inaccessible:597      continue;598 599    case AR_dependent:600      OnFailure = AR_dependent;601      break;602    }603  }604 605  // That's it, give up.606  return OnFailure;607}608 609namespace {610 611/// A helper class for checking for a friend which will grant access612/// to a protected instance member.613struct ProtectedFriendContext {614  Sema &S;615  const EffectiveContext &EC;616  const CXXRecordDecl *NamingClass;617  bool CheckDependent;618  bool EverDependent;619 620  /// The path down to the current base class.621  SmallVector<const CXXRecordDecl*, 20> CurPath;622 623  ProtectedFriendContext(Sema &S, const EffectiveContext &EC,624                         const CXXRecordDecl *InstanceContext,625                         const CXXRecordDecl *NamingClass)626    : S(S), EC(EC), NamingClass(NamingClass),627      CheckDependent(InstanceContext->isDependentContext() ||628                     NamingClass->isDependentContext()),629      EverDependent(false) {}630 631  /// Check classes in the current path for friendship, starting at632  /// the given index.633  bool checkFriendshipAlongPath(unsigned I) {634    assert(I < CurPath.size());635    for (unsigned E = CurPath.size(); I != E; ++I) {636      switch (GetFriendKind(S, EC, CurPath[I])) {637      case AR_accessible:   return true;638      case AR_inaccessible: continue;639      case AR_dependent:    EverDependent = true; continue;640      }641    }642    return false;643  }644 645  /// Perform a search starting at the given class.646  ///647  /// PrivateDepth is the index of the last (least derived) class648  /// along the current path such that a notional public member of649  /// the final class in the path would have access in that class.650  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {651    // If we ever reach the naming class, check the current path for652    // friendship.  We can also stop recursing because we obviously653    // won't find the naming class there again.654    if (Cur == NamingClass)655      return checkFriendshipAlongPath(PrivateDepth);656 657    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))658      EverDependent = true;659 660    // Recurse into the base classes.661    for (const auto &I : Cur->bases()) {662      // If this is private inheritance, then a public member of the663      // base will not have any access in classes derived from Cur.664      unsigned BasePrivateDepth = PrivateDepth;665      if (I.getAccessSpecifier() == AS_private)666        BasePrivateDepth = CurPath.size() - 1;667 668      const CXXRecordDecl *RD;669 670      QualType T = I.getType();671      if (CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) {672        RD = Rec;673      } else {674        assert(T->isDependentType() && "non-dependent base wasn't a record?");675        EverDependent = true;676        continue;677      }678 679      // Recurse.  We don't need to clean up if this returns true.680      CurPath.push_back(RD);681      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))682        return true;683      CurPath.pop_back();684    }685 686    return false;687  }688 689  bool findFriendship(const CXXRecordDecl *Cur) {690    assert(CurPath.empty());691    CurPath.push_back(Cur);692    return findFriendship(Cur, 0);693  }694};695}696 697/// Search for a class P that EC is a friend of, under the constraint698///   InstanceContext <= P699/// if InstanceContext exists, or else700///   NamingClass <= P701/// and with the additional restriction that a protected member of702/// NamingClass would have some natural access in P, which implicitly703/// imposes the constraint that P <= NamingClass.704///705/// This isn't quite the condition laid out in the standard.706/// Instead of saying that a notional protected member of NamingClass707/// would have to have some natural access in P, it says the actual708/// target has to have some natural access in P, which opens up the709/// possibility that the target (which is not necessarily a member710/// of NamingClass) might be more accessible along some path not711/// passing through it.  That's really a bad idea, though, because it712/// introduces two problems:713///   - Most importantly, it breaks encapsulation because you can714///     access a forbidden base class's members by directly subclassing715///     it elsewhere.716///   - It also makes access substantially harder to compute because it717///     breaks the hill-climbing algorithm: knowing that the target is718///     accessible in some base class would no longer let you change719///     the question solely to whether the base class is accessible,720///     because the original target might have been more accessible721///     because of crazy subclassing.722/// So we don't implement that.723static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,724                                           const CXXRecordDecl *InstanceContext,725                                           const CXXRecordDecl *NamingClass) {726  assert(InstanceContext == nullptr ||727         InstanceContext->getCanonicalDecl() == InstanceContext);728  assert(NamingClass->getCanonicalDecl() == NamingClass);729 730  // If we don't have an instance context, our constraints give us731  // that NamingClass <= P <= NamingClass, i.e. P == NamingClass.732  // This is just the usual friendship check.733  if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);734 735  ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);736  if (PRC.findFriendship(InstanceContext)) return AR_accessible;737  if (PRC.EverDependent) return AR_dependent;738  return AR_inaccessible;739}740 741static AccessResult HasAccess(Sema &S,742                              const EffectiveContext &EC,743                              const CXXRecordDecl *NamingClass,744                              AccessSpecifier Access,745                              const AccessTarget &Target) {746  assert(NamingClass->getCanonicalDecl() == NamingClass &&747         "declaration should be canonicalized before being passed here");748 749  if (Access == AS_public) return AR_accessible;750  assert(Access == AS_private || Access == AS_protected);751 752  AccessResult OnFailure = AR_inaccessible;753 754  for (EffectiveContext::record_iterator755         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {756    // All the declarations in EC have been canonicalized, so pointer757    // equality from this point on will work fine.758    const CXXRecordDecl *ECRecord = *I;759 760    // [B2] and [M2]761    if (Access == AS_private) {762      if (ECRecord == NamingClass)763        return AR_accessible;764 765      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))766        OnFailure = AR_dependent;767 768    // [B3] and [M3]769    } else {770      assert(Access == AS_protected);771      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {772      case AR_accessible: break;773      case AR_inaccessible: continue;774      case AR_dependent: OnFailure = AR_dependent; continue;775      }776 777      // C++ [class.protected]p1:778      //   An additional access check beyond those described earlier in779      //   [class.access] is applied when a non-static data member or780      //   non-static member function is a protected member of its naming781      //   class.  As described earlier, access to a protected member is782      //   granted because the reference occurs in a friend or member of783      //   some class C.  If the access is to form a pointer to member,784      //   the nested-name-specifier shall name C or a class derived from785      //   C. All other accesses involve a (possibly implicit) object786      //   expression. In this case, the class of the object expression787      //   shall be C or a class derived from C.788      //789      // We interpret this as a restriction on [M3].790 791      // In this part of the code, 'C' is just our context class ECRecord.792 793      // These rules are different if we don't have an instance context.794      if (!Target.hasInstanceContext()) {795        // If it's not an instance member, these restrictions don't apply.796        if (!Target.isInstanceMember()) return AR_accessible;797 798        // If it's an instance member, use the pointer-to-member rule799        // that the naming class has to be derived from the effective800        // context.801 802        // Emulate a MSVC bug where the creation of pointer-to-member803        // to protected member of base class is allowed but only from804        // static member functions.805        if (S.getLangOpts().MSVCCompat && !EC.Functions.empty())806          if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))807            if (MD->isStatic()) return AR_accessible;808 809        // Despite the standard's confident wording, there is a case810        // where you can have an instance member that's neither in a811        // pointer-to-member expression nor in a member access:  when812        // it names a field in an unevaluated context that can't be an813        // implicit member.  Pending clarification, we just apply the814        // same naming-class restriction here.815        //   FIXME: we're probably not correctly adding the816        //   protected-member restriction when we retroactively convert817        //   an expression to being evaluated.818 819        // We know that ECRecord derives from NamingClass.  The820        // restriction says to check whether NamingClass derives from821        // ECRecord, but that's not really necessary: two distinct822        // classes can't be recursively derived from each other.  So823        // along this path, we just need to check whether the classes824        // are equal.825        if (NamingClass == ECRecord) return AR_accessible;826 827        // Otherwise, this context class tells us nothing;  on to the next.828        continue;829      }830 831      assert(Target.isInstanceMember());832 833      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);834      if (!InstanceContext) {835        OnFailure = AR_dependent;836        continue;837      }838 839      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {840      case AR_accessible: return AR_accessible;841      case AR_inaccessible: continue;842      case AR_dependent: OnFailure = AR_dependent; continue;843      }844    }845  }846 847  // [M3] and [B3] say that, if the target is protected in N, we grant848  // access if the access occurs in a friend or member of some class P849  // that's a subclass of N and where the target has some natural850  // access in P.  The 'member' aspect is easy to handle because P851  // would necessarily be one of the effective-context records, and we852  // address that above.  The 'friend' aspect is completely ridiculous853  // to implement because there are no restrictions at all on P854  // *unless* the [class.protected] restriction applies.  If it does,855  // however, we should ignore whether the naming class is a friend,856  // and instead rely on whether any potential P is a friend.857  if (Access == AS_protected && Target.isInstanceMember()) {858    // Compute the instance context if possible.859    const CXXRecordDecl *InstanceContext = nullptr;860    if (Target.hasInstanceContext()) {861      InstanceContext = Target.resolveInstanceContext(S);862      if (!InstanceContext) return AR_dependent;863    }864 865    switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {866    case AR_accessible: return AR_accessible;867    case AR_inaccessible: return OnFailure;868    case AR_dependent: return AR_dependent;869    }870    llvm_unreachable("impossible friendship kind");871  }872 873  switch (GetFriendKind(S, EC, NamingClass)) {874  case AR_accessible: return AR_accessible;875  case AR_inaccessible: return OnFailure;876  case AR_dependent: return AR_dependent;877  }878 879  // Silence bogus warnings880  llvm_unreachable("impossible friendship kind");881}882 883/// Finds the best path from the naming class to the declaring class,884/// taking friend declarations into account.885///886/// C++0x [class.access.base]p5:887///   A member m is accessible at the point R when named in class N if888///   [M1] m as a member of N is public, or889///   [M2] m as a member of N is private, and R occurs in a member or890///        friend of class N, or891///   [M3] m as a member of N is protected, and R occurs in a member or892///        friend of class N, or in a member or friend of a class P893///        derived from N, where m as a member of P is public, private,894///        or protected, or895///   [M4] there exists a base class B of N that is accessible at R, and896///        m is accessible at R when named in class B.897///898/// C++0x [class.access.base]p4:899///   A base class B of N is accessible at R, if900///   [B1] an invented public member of B would be a public member of N, or901///   [B2] R occurs in a member or friend of class N, and an invented public902///        member of B would be a private or protected member of N, or903///   [B3] R occurs in a member or friend of a class P derived from N, and an904///        invented public member of B would be a private or protected member905///        of P, or906///   [B4] there exists a class S such that B is a base class of S accessible907///        at R and S is a base class of N accessible at R.908///909/// Along a single inheritance path we can restate both of these910/// iteratively:911///912/// First, we note that M1-4 are equivalent to B1-4 if the member is913/// treated as a notional base of its declaring class with inheritance914/// access equivalent to the member's access.  Therefore we need only915/// ask whether a class B is accessible from a class N in context R.916///917/// Let B_1 .. B_n be the inheritance path in question (i.e. where918/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of919/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the920/// closest accessible base in the path:921///   Access(a, b) = (* access on the base specifier from a to b *)922///   Merge(a, forbidden) = forbidden923///   Merge(a, private) = forbidden924///   Merge(a, b) = min(a,b)925///   Accessible(c, forbidden) = false926///   Accessible(c, private) = (R is c) || IsFriend(c, R)927///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)928///   Accessible(c, public) = true929///   ACAB(n) = public930///   ACAB(i) =931///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in932///     if Accessible(B_i, AccessToBase) then public else AccessToBase933///934/// B is an accessible base of N at R iff ACAB(1) = public.935///936/// \param FinalAccess the access of the "final step", or AS_public if937///   there is no final step.938/// \return null if friendship is dependent939static CXXBasePath *FindBestPath(Sema &S,940                                 const EffectiveContext &EC,941                                 AccessTarget &Target,942                                 AccessSpecifier FinalAccess,943                                 CXXBasePaths &Paths) {944  // Derive the paths to the desired base.945  const CXXRecordDecl *Derived = Target.getNamingClass();946  const CXXRecordDecl *Base = Target.getDeclaringClass();947 948  // FIXME: fail correctly when there are dependent paths.949  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),950                                          Paths);951  assert(isDerived && "derived class not actually derived from base");952  (void) isDerived;953 954  CXXBasePath *BestPath = nullptr;955 956  assert(FinalAccess != AS_none && "forbidden access after declaring class");957 958  bool AnyDependent = false;959 960  // Derive the friend-modified access along each path.961  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();962         PI != PE; ++PI) {963    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();964 965    // Walk through the path backwards.966    AccessSpecifier PathAccess = FinalAccess;967    CXXBasePath::iterator I = PI->end(), E = PI->begin();968    while (I != E) {969      --I;970 971      assert(PathAccess != AS_none);972 973      // If the declaration is a private member of a base class, there974      // is no level of friendship in derived classes that can make it975      // accessible.976      if (PathAccess == AS_private) {977        PathAccess = AS_none;978        break;979      }980 981      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();982 983      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();984      PathAccess = std::max(PathAccess, BaseAccess);985 986      switch (HasAccess(S, EC, NC, PathAccess, Target)) {987      case AR_inaccessible: break;988      case AR_accessible:989        PathAccess = AS_public;990 991        // Future tests are not against members and so do not have992        // instance context.993        Target.suppressInstanceContext();994        break;995      case AR_dependent:996        AnyDependent = true;997        goto Next;998      }999    }1000 1001    // Note that we modify the path's Access field to the1002    // friend-modified access.1003    if (BestPath == nullptr || PathAccess < BestPath->Access) {1004      BestPath = &*PI;1005      BestPath->Access = PathAccess;1006 1007      // Short-circuit if we found a public path.1008      if (BestPath->Access == AS_public)1009        return BestPath;1010    }1011 1012  Next: ;1013  }1014 1015  assert((!BestPath || BestPath->Access != AS_public) &&1016         "fell out of loop with public path");1017 1018  // We didn't find a public path, but at least one path was subject1019  // to dependent friendship, so delay the check.1020  if (AnyDependent)1021    return nullptr;1022 1023  return BestPath;1024}1025 1026/// Given that an entity has protected natural access, check whether1027/// access might be denied because of the protected member access1028/// restriction.1029///1030/// \return true if a note was emitted1031static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,1032                                       AccessTarget &Target) {1033  // Only applies to instance accesses.1034  if (!Target.isInstanceMember())1035    return false;1036 1037  assert(Target.isMemberAccess());1038 1039  const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass();1040 1041  for (EffectiveContext::record_iterator1042         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {1043    const CXXRecordDecl *ECRecord = *I;1044    switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {1045    case AR_accessible: break;1046    case AR_inaccessible: continue;1047    case AR_dependent: continue;1048    }1049 1050    // The effective context is a subclass of the declaring class.1051    // Check whether the [class.protected] restriction is limiting1052    // access.1053 1054    // To get this exactly right, this might need to be checked more1055    // holistically;  it's not necessarily the case that gaining1056    // access here would grant us access overall.1057 1058    NamedDecl *D = Target.getTargetDecl();1059 1060    // If we don't have an instance context, [class.protected] says the1061    // naming class has to equal the context class.1062    if (!Target.hasInstanceContext()) {1063      // If it does, the restriction doesn't apply.1064      if (NamingClass == ECRecord) continue;1065 1066      // TODO: it would be great to have a fixit here, since this is1067      // such an obvious error.1068      S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)1069          << S.Context.getCanonicalTagType(ECRecord);1070      return true;1071    }1072 1073    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);1074    assert(InstanceContext && "diagnosing dependent access");1075 1076    switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {1077    case AR_accessible: continue;1078    case AR_dependent: continue;1079    case AR_inaccessible:1080      break;1081    }1082 1083    // Okay, the restriction seems to be what's limiting us.1084 1085    // Use a special diagnostic for constructors and destructors.1086    if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) ||1087        (isa<FunctionTemplateDecl>(D) &&1088         isa<CXXConstructorDecl>(1089                cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {1090      return S.Diag(D->getLocation(),1091                    diag::note_access_protected_restricted_ctordtor)1092             << isa<CXXDestructorDecl>(D->getAsFunction());1093    }1094 1095    // Otherwise, use the generic diagnostic.1096    return S.Diag(D->getLocation(),1097                  diag::note_access_protected_restricted_object)1098           << S.Context.getCanonicalTagType(ECRecord);1099  }1100 1101  return false;1102}1103 1104/// We are unable to access a given declaration due to its direct1105/// access control;  diagnose that.1106static void diagnoseBadDirectAccess(Sema &S,1107                                    const EffectiveContext &EC,1108                                    AccessTarget &entity) {1109  assert(entity.isMemberAccess());1110  NamedDecl *D = entity.getTargetDecl();1111 1112  if (D->getAccess() == AS_protected &&1113      TryDiagnoseProtectedAccess(S, EC, entity))1114    return;1115 1116  // Find an original declaration.1117  while (D->isOutOfLine()) {1118    NamedDecl *PrevDecl = nullptr;1119    if (VarDecl *VD = dyn_cast<VarDecl>(D))1120      PrevDecl = VD->getPreviousDecl();1121    else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))1122      PrevDecl = FD->getPreviousDecl();1123    else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))1124      PrevDecl = TND->getPreviousDecl();1125    else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {1126      if (const auto *RD = dyn_cast<CXXRecordDecl>(TD);1127          RD && RD->isInjectedClassName())1128        break;1129      PrevDecl = TD->getPreviousDecl();1130    }1131    if (!PrevDecl) break;1132    D = PrevDecl;1133  }1134 1135  CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);1136  Decl *ImmediateChild;1137  if (D->getDeclContext() == DeclaringClass)1138    ImmediateChild = D;1139  else {1140    DeclContext *DC = D->getDeclContext();1141    while (DC->getParent() != DeclaringClass)1142      DC = DC->getParent();1143    ImmediateChild = cast<Decl>(DC);1144  }1145 1146  // Check whether there's an AccessSpecDecl preceding this in the1147  // chain of the DeclContext.1148  bool isImplicit = true;1149  for (const auto *I : DeclaringClass->decls()) {1150    if (I == ImmediateChild) break;1151    if (isa<AccessSpecDecl>(I)) {1152      isImplicit = false;1153      break;1154    }1155  }1156 1157  S.Diag(D->getLocation(), diag::note_access_natural)1158    << (unsigned) (D->getAccess() == AS_protected)1159    << isImplicit;1160}1161 1162/// Diagnose the path which caused the given declaration or base class1163/// to become inaccessible.1164static void DiagnoseAccessPath(Sema &S,1165                               const EffectiveContext &EC,1166                               AccessTarget &entity) {1167  // Save the instance context to preserve invariants.1168  AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();1169 1170  // This basically repeats the main algorithm but keeps some more1171  // information.1172 1173  // The natural access so far.1174  AccessSpecifier accessSoFar = AS_public;1175 1176  // Check whether we have special rights to the declaring class.1177  if (entity.isMemberAccess()) {1178    NamedDecl *D = entity.getTargetDecl();1179    accessSoFar = D->getAccess();1180    const CXXRecordDecl *declaringClass = entity.getDeclaringClass();1181 1182    switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) {1183    // If the declaration is accessible when named in its declaring1184    // class, then we must be constrained by the path.1185    case AR_accessible:1186      accessSoFar = AS_public;1187      entity.suppressInstanceContext();1188      break;1189 1190    case AR_inaccessible:1191      if (accessSoFar == AS_private ||1192          declaringClass == entity.getEffectiveNamingClass())1193        return diagnoseBadDirectAccess(S, EC, entity);1194      break;1195 1196    case AR_dependent:1197      llvm_unreachable("cannot diagnose dependent access");1198    }1199  }1200 1201  CXXBasePaths paths;1202  CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths);1203  assert(path.Access != AS_public);1204 1205  CXXBasePath::iterator i = path.end(), e = path.begin();1206  CXXBasePath::iterator constrainingBase = i;1207  while (i != e) {1208    --i;1209 1210    assert(accessSoFar != AS_none && accessSoFar != AS_private);1211 1212    // Is the entity accessible when named in the deriving class, as1213    // modified by the base specifier?1214    const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl();1215    const CXXBaseSpecifier *base = i->Base;1216 1217    // If the access to this base is worse than the access we have to1218    // the declaration, remember it.1219    AccessSpecifier baseAccess = base->getAccessSpecifier();1220    if (baseAccess > accessSoFar) {1221      constrainingBase = i;1222      accessSoFar = baseAccess;1223    }1224 1225    switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) {1226    case AR_inaccessible: break;1227    case AR_accessible:1228      accessSoFar = AS_public;1229      entity.suppressInstanceContext();1230      constrainingBase = nullptr;1231      break;1232    case AR_dependent:1233      llvm_unreachable("cannot diagnose dependent access");1234    }1235 1236    // If this was private inheritance, but we don't have access to1237    // the deriving class, we're done.1238    if (accessSoFar == AS_private) {1239      assert(baseAccess == AS_private);1240      assert(constrainingBase == i);1241      break;1242    }1243  }1244 1245  // If we don't have a constraining base, the access failure must be1246  // due to the original declaration.1247  if (constrainingBase == path.end())1248    return diagnoseBadDirectAccess(S, EC, entity);1249 1250  // We're constrained by inheritance, but we want to say1251  // "declared private here" if we're diagnosing a hierarchy1252  // conversion and this is the final step.1253  unsigned diagnostic;1254  if (entity.isMemberAccess() ||1255      constrainingBase + 1 != path.end()) {1256    diagnostic = diag::note_access_constrained_by_path;1257  } else {1258    diagnostic = diag::note_access_natural;1259  }1260 1261  const CXXBaseSpecifier *base = constrainingBase->Base;1262 1263  S.Diag(base->getSourceRange().getBegin(), diagnostic)1264    << base->getSourceRange()1265    << (base->getAccessSpecifier() == AS_protected)1266    << (base->getAccessSpecifierAsWritten() == AS_none);1267 1268  if (entity.isMemberAccess())1269    S.Diag(entity.getTargetDecl()->getLocation(),1270           diag::note_member_declared_at);1271}1272 1273static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,1274                              const EffectiveContext &EC,1275                              AccessTarget &Entity) {1276  const CXXRecordDecl *NamingClass = Entity.getNamingClass();1277  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();1278  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr);1279 1280  S.Diag(Loc, Entity.getDiag())1281      << (Entity.getAccess() == AS_protected)1282      << (D ? D->getDeclName() : DeclarationName())1283      << S.Context.getCanonicalTagType(NamingClass)1284      << S.Context.getCanonicalTagType(DeclaringClass);1285  DiagnoseAccessPath(S, EC, Entity);1286}1287 1288/// MSVC has a bug where if during an using declaration name lookup,1289/// the declaration found is unaccessible (private) and that declaration1290/// was bring into scope via another using declaration whose target1291/// declaration is accessible (public) then no error is generated.1292/// Example:1293///   class A {1294///   public:1295///     int f();1296///   };1297///   class B : public A {1298///   private:1299///     using A::f;1300///   };1301///   class C : public B {1302///   private:1303///     using B::f;1304///   };1305///1306/// Here, B::f is private so this should fail in Standard C++, but1307/// because B::f refers to A::f which is public MSVC accepts it.1308static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,1309                                                 SourceLocation AccessLoc,1310                                                 AccessTarget &Entity) {1311  if (UsingShadowDecl *Shadow =1312          dyn_cast<UsingShadowDecl>(Entity.getTargetDecl()))1313    if (UsingDecl *UD = dyn_cast<UsingDecl>(Shadow->getIntroducer())) {1314      const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();1315      if (Entity.getTargetDecl()->getAccess() == AS_private &&1316          (OrigDecl->getAccess() == AS_public ||1317           OrigDecl->getAccess() == AS_protected)) {1318        S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)1319            << UD->getQualifiedNameAsString()1320            << OrigDecl->getQualifiedNameAsString();1321        return true;1322      }1323    }1324  return false;1325}1326 1327/// Determines whether the accessed entity is accessible.  Public members1328/// have been weeded out by this point.1329static AccessResult IsAccessible(Sema &S,1330                                 const EffectiveContext &EC,1331                                 AccessTarget &Entity) {1332  // Determine the actual naming class.1333  const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();1334 1335  AccessSpecifier UnprivilegedAccess = Entity.getAccess();1336  assert(UnprivilegedAccess != AS_public && "public access not weeded out");1337 1338  // Before we try to recalculate access paths, try to white-list1339  // accesses which just trade in on the final step, i.e. accesses1340  // which don't require [M4] or [B4]. These are by far the most1341  // common forms of privileged access.1342  if (UnprivilegedAccess != AS_none) {1343    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {1344    case AR_dependent:1345      // This is actually an interesting policy decision.  We don't1346      // *have* to delay immediately here: we can do the full access1347      // calculation in the hope that friendship on some intermediate1348      // class will make the declaration accessible non-dependently.1349      // But that's not cheap, and odds are very good (note: assertion1350      // made without data) that the friend declaration will determine1351      // access.1352      return AR_dependent;1353 1354    case AR_accessible: return AR_accessible;1355    case AR_inaccessible: break;1356    }1357  }1358 1359  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();1360 1361  // We lower member accesses to base accesses by pretending that the1362  // member is a base class of its declaring class.1363  AccessSpecifier FinalAccess;1364 1365  if (Entity.isMemberAccess()) {1366    // Determine if the declaration is accessible from EC when named1367    // in its declaring class.1368    NamedDecl *Target = Entity.getTargetDecl();1369    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();1370 1371    FinalAccess = Target->getAccess();1372    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {1373    case AR_accessible:1374      // Target is accessible at EC when named in its declaring class.1375      // We can now hill-climb and simply check whether the declaring1376      // class is accessible as a base of the naming class.  This is1377      // equivalent to checking the access of a notional public1378      // member with no instance context.1379      FinalAccess = AS_public;1380      Entity.suppressInstanceContext();1381      break;1382    case AR_inaccessible: break;1383    case AR_dependent: return AR_dependent; // see above1384    }1385 1386    if (DeclaringClass == NamingClass)1387      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);1388  } else {1389    FinalAccess = AS_public;1390  }1391 1392  assert(Entity.getDeclaringClass() != NamingClass);1393 1394  // Append the declaration's access if applicable.1395  CXXBasePaths Paths;1396  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);1397  if (!Path)1398    return AR_dependent;1399 1400  assert(Path->Access <= UnprivilegedAccess &&1401         "access along best path worse than direct?");1402  if (Path->Access == AS_public)1403    return AR_accessible;1404  return AR_inaccessible;1405}1406 1407static void DelayDependentAccess(Sema &S,1408                                 const EffectiveContext &EC,1409                                 SourceLocation Loc,1410                                 const AccessTarget &Entity) {1411  assert(EC.isDependent() && "delaying non-dependent access");1412  DeclContext *DC = EC.getInnerContext();1413  assert(DC->isDependentContext() && "delaying non-dependent access");1414  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,1415                              Loc,1416                              Entity.isMemberAccess(),1417                              Entity.getAccess(),1418                              Entity.getTargetDecl(),1419                              Entity.getNamingClass(),1420                              Entity.getBaseObjectType(),1421                              Entity.getDiag());1422}1423 1424/// Checks access to an entity from the given effective context.1425static AccessResult CheckEffectiveAccess(Sema &S,1426                                         const EffectiveContext &EC,1427                                         SourceLocation Loc,1428                                         AccessTarget &Entity) {1429  assert(Entity.getAccess() != AS_public && "called for public access!");1430 1431  switch (IsAccessible(S, EC, Entity)) {1432  case AR_dependent:1433    DelayDependentAccess(S, EC, Loc, Entity);1434    return AR_dependent;1435 1436  case AR_inaccessible:1437    if (S.getLangOpts().MSVCCompat &&1438        IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))1439      return AR_accessible;1440    if (!Entity.isQuiet())1441      DiagnoseBadAccess(S, Loc, EC, Entity);1442    return AR_inaccessible;1443 1444  case AR_accessible:1445    return AR_accessible;1446  }1447 1448  // silence unnecessary warning1449  llvm_unreachable("invalid access result");1450}1451 1452static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,1453                                      AccessTarget &Entity) {1454  // If the access path is public, it's accessible everywhere.1455  if (Entity.getAccess() == AS_public)1456    return Sema::AR_accessible;1457 1458  // If we're currently parsing a declaration, we may need to delay1459  // access control checking, because our effective context might be1460  // different based on what the declaration comes out as.1461  //1462  // For example, we might be parsing a declaration with a scope1463  // specifier, like this:1464  //   A::private_type A::foo() { ... }1465  //1466  // friend declaration should not be delayed because it may lead to incorrect1467  // redeclaration chain, such as:1468  //   class D {1469  //    class E{1470  //     class F{};1471  //     friend  void foo(D::E::F& q);1472  //    };1473  //    friend  void foo(D::E::F& q);1474  //   };1475  if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {1476    // [class.friend]p9:1477    // A member nominated by a friend declaration shall be accessible in the1478    // class containing the friend declaration. The meaning of the friend1479    // declaration is the same whether the friend declaration appears in the1480    // private, protected, or public ([class.mem]) portion of the class1481    // member-specification.1482    Scope *TS = S.getCurScope();1483    bool IsFriendDeclaration = false;1484    while (TS && !IsFriendDeclaration) {1485      IsFriendDeclaration = TS->isFriendScope();1486      TS = TS->getParent();1487    }1488    if (!IsFriendDeclaration) {1489      S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));1490      return Sema::AR_delayed;1491    }1492  }1493 1494  EffectiveContext EC(S.CurContext);1495  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {1496  case AR_accessible: return Sema::AR_accessible;1497  case AR_inaccessible: return Sema::AR_inaccessible;1498  case AR_dependent: return Sema::AR_dependent;1499  }1500  llvm_unreachable("invalid access result");1501}1502 1503void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {1504  // Access control for names used in the declarations of functions1505  // and function templates should normally be evaluated in the context1506  // of the declaration, just in case it's a friend of something.1507  // However, this does not apply to local extern declarations.1508 1509  DeclContext *DC = D->getDeclContext();1510  if (D->isLocalExternDecl()) {1511    DC = D->getLexicalDeclContext();1512  } else if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {1513    DC = FN;1514  } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {1515    if (auto *D = dyn_cast_if_present<DeclContext>(TD->getTemplatedDecl()))1516      DC = D;1517  } else if (auto *RD = dyn_cast<RequiresExprBodyDecl>(D)) {1518    DC = RD;1519  }1520 1521  EffectiveContext EC(DC);1522 1523  AccessTarget Target(DD.getAccessData());1524 1525  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)1526    DD.Triggered = true;1527}1528 1529void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,1530                        const MultiLevelTemplateArgumentList &TemplateArgs) {1531  SourceLocation Loc = DD.getAccessLoc();1532  AccessSpecifier Access = DD.getAccess();1533 1534  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),1535                                       TemplateArgs);1536  if (!NamingD) return;1537  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),1538                                       TemplateArgs);1539  if (!TargetD) return;1540 1541  if (DD.isAccessToMember()) {1542    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);1543    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);1544    QualType BaseObjectType = DD.getAccessBaseObjectType();1545    if (!BaseObjectType.isNull()) {1546      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,1547                                 DeclarationName());1548      if (BaseObjectType.isNull()) return;1549    }1550 1551    AccessTarget Entity(Context,1552                        AccessTarget::Member,1553                        NamingClass,1554                        DeclAccessPair::make(TargetDecl, Access),1555                        BaseObjectType);1556    Entity.setDiag(DD.getDiagnostic());1557    CheckAccess(*this, Loc, Entity);1558  } else {1559    AccessTarget Entity(Context,1560                        AccessTarget::Base,1561                        cast<CXXRecordDecl>(TargetD),1562                        cast<CXXRecordDecl>(NamingD),1563                        Access);1564    Entity.setDiag(DD.getDiagnostic());1565    CheckAccess(*this, Loc, Entity);1566  }1567}1568 1569Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,1570                                                     DeclAccessPair Found) {1571  if (!getLangOpts().AccessControl ||1572      !E->getNamingClass() ||1573      Found.getAccess() == AS_public)1574    return AR_accessible;1575 1576  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),1577                      Found, QualType());1578  Entity.setDiag(diag::err_access) << E->getSourceRange();1579 1580  return CheckAccess(*this, E->getNameLoc(), Entity);1581}1582 1583Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,1584                                                     DeclAccessPair Found) {1585  if (!getLangOpts().AccessControl ||1586      Found.getAccess() == AS_public)1587    return AR_accessible;1588 1589  QualType BaseType = E->getBaseType();1590  if (E->isArrow())1591    BaseType = BaseType->castAs<PointerType>()->getPointeeType();1592 1593  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),1594                      Found, BaseType);1595  Entity.setDiag(diag::err_access) << E->getSourceRange();1596 1597  return CheckAccess(*this, E->getMemberLoc(), Entity);1598}1599 1600bool Sema::isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass,1601                                         DeclAccessPair Found,1602                                         QualType ObjectType,1603                                         SourceLocation Loc,1604                                         const PartialDiagnostic &Diag) {1605  // Fast path.1606  if (Found.getAccess() == AS_public || !getLangOpts().AccessControl)1607    return true;1608 1609  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,1610                      ObjectType);1611 1612  // Suppress diagnostics.1613  Entity.setDiag(Diag);1614 1615  switch (CheckAccess(*this, Loc, Entity)) {1616  case AR_accessible: return true;1617  case AR_inaccessible: return false;1618  case AR_dependent: llvm_unreachable("dependent for =delete computation");1619  case AR_delayed: llvm_unreachable("cannot delay =delete computation");1620  }1621  llvm_unreachable("bad access result");1622}1623 1624Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,1625                                               CXXDestructorDecl *Dtor,1626                                               const PartialDiagnostic &PDiag,1627                                               QualType ObjectTy) {1628  if (!getLangOpts().AccessControl)1629    return AR_accessible;1630 1631  // There's never a path involved when checking implicit destructor access.1632  AccessSpecifier Access = Dtor->getAccess();1633  if (Access == AS_public)1634    return AR_accessible;1635 1636  CXXRecordDecl *NamingClass = Dtor->getParent();1637  if (ObjectTy.isNull())1638    ObjectTy = Context.getCanonicalTagType(NamingClass);1639 1640  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,1641                      DeclAccessPair::make(Dtor, Access),1642                      ObjectTy);1643  Entity.setDiag(PDiag); // TODO: avoid copy1644 1645  return CheckAccess(*this, Loc, Entity);1646}1647 1648Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,1649                                                CXXConstructorDecl *Constructor,1650                                                DeclAccessPair Found,1651                                                const InitializedEntity &Entity,1652                                                bool IsCopyBindingRefToTemp) {1653  if (!getLangOpts().AccessControl || Found.getAccess() == AS_public)1654    return AR_accessible;1655 1656  PartialDiagnostic PD(PDiag());1657  switch (Entity.getKind()) {1658  default:1659    PD = PDiag(IsCopyBindingRefToTemp1660                 ? diag::ext_rvalue_to_reference_access_ctor1661                 : diag::err_access_ctor);1662 1663    break;1664 1665  case InitializedEntity::EK_Base:1666    PD = PDiag(diag::err_access_base_ctor);1667    PD << Entity.isInheritedVirtualBase()1668       << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);1669    break;1670 1671  case InitializedEntity::EK_Member:1672  case InitializedEntity::EK_ParenAggInitMember: {1673    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());1674    PD = PDiag(diag::err_access_field_ctor);1675    PD << Field->getType() << getSpecialMember(Constructor);1676    break;1677  }1678 1679  case InitializedEntity::EK_LambdaCapture: {1680    StringRef VarName = Entity.getCapturedVarName();1681    PD = PDiag(diag::err_access_lambda_capture);1682    PD << VarName << Entity.getType() << getSpecialMember(Constructor);1683    break;1684  }1685 1686  }1687 1688  return CheckConstructorAccess(UseLoc, Constructor, Found, Entity, PD);1689}1690 1691Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,1692                                                CXXConstructorDecl *Constructor,1693                                                DeclAccessPair Found,1694                                                const InitializedEntity &Entity,1695                                                const PartialDiagnostic &PD) {1696  if (!getLangOpts().AccessControl ||1697      Found.getAccess() == AS_public)1698    return AR_accessible;1699 1700  CXXRecordDecl *NamingClass = Constructor->getParent();1701 1702  // Initializing a base sub-object is an instance method call on an1703  // object of the derived class.  Otherwise, we have an instance method1704  // call on an object of the constructed type.1705  //1706  // FIXME: If we have a parent, we're initializing the base class subobject1707  // in aggregate initialization. It's not clear whether the object class1708  // should be the base class or the derived class in that case.1709  CXXRecordDecl *ObjectClass;1710  if ((Entity.getKind() == InitializedEntity::EK_Base ||1711       Entity.getKind() == InitializedEntity::EK_Delegating) &&1712      !Entity.getParent()) {1713    ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent();1714  } else if (auto *Shadow =1715                 dyn_cast<ConstructorUsingShadowDecl>(Found.getDecl())) {1716    // If we're using an inheriting constructor to construct an object,1717    // the object class is the derived class, not the base class.1718    ObjectClass = Shadow->getParent();1719  } else {1720    ObjectClass = NamingClass;1721  }1722 1723  AccessTarget AccessEntity(1724      Context, AccessTarget::Member, NamingClass,1725      DeclAccessPair::make(Constructor, Found.getAccess()),1726      Context.getCanonicalTagType(ObjectClass));1727  AccessEntity.setDiag(PD);1728 1729  return CheckAccess(*this, UseLoc, AccessEntity);1730}1731 1732Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,1733                                               SourceRange PlacementRange,1734                                               CXXRecordDecl *NamingClass,1735                                               DeclAccessPair Found,1736                                               bool Diagnose) {1737  if (!getLangOpts().AccessControl ||1738      !NamingClass ||1739      Found.getAccess() == AS_public)1740    return AR_accessible;1741 1742  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,1743                      QualType());1744  if (Diagnose)1745    Entity.setDiag(diag::err_access)1746      << PlacementRange;1747 1748  return CheckAccess(*this, OpLoc, Entity);1749}1750 1751Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,1752                                           CXXRecordDecl *NamingClass,1753                                           DeclAccessPair Found) {1754  if (!getLangOpts().AccessControl ||1755      !NamingClass ||1756      Found.getAccess() == AS_public)1757    return AR_accessible;1758 1759  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,1760                      Found, QualType());1761 1762  return CheckAccess(*this, UseLoc, Entity);1763}1764 1765Sema::AccessResult1766Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc,1767                                         CXXRecordDecl *DecomposedClass,1768                                         DeclAccessPair Field) {1769  if (!getLangOpts().AccessControl ||1770      Field.getAccess() == AS_public)1771    return AR_accessible;1772 1773  AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field,1774                      Context.getCanonicalTagType(DecomposedClass));1775  Entity.setDiag(diag::err_decomp_decl_inaccessible_field);1776 1777  return CheckAccess(*this, UseLoc, Entity);1778}1779 1780Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,1781                                                   Expr *ObjectExpr,1782                                                   const SourceRange &Range,1783                                                   DeclAccessPair Found) {1784  if (!getLangOpts().AccessControl || Found.getAccess() == AS_public)1785    return AR_accessible;1786 1787  auto *NamingClass = ObjectExpr->getType()->castAsCXXRecordDecl();1788  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,1789                      ObjectExpr->getType());1790  Entity.setDiag(diag::err_access) << ObjectExpr->getSourceRange() << Range;1791 1792  return CheckAccess(*this, OpLoc, Entity);1793}1794 1795Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,1796                                                   Expr *ObjectExpr,1797                                                   Expr *ArgExpr,1798                                                   DeclAccessPair Found) {1799  return CheckMemberOperatorAccess(1800      OpLoc, ObjectExpr, ArgExpr ? ArgExpr->getSourceRange() : SourceRange(),1801      Found);1802}1803 1804Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,1805                                                   Expr *ObjectExpr,1806                                                   ArrayRef<Expr *> ArgExprs,1807                                                   DeclAccessPair FoundDecl) {1808  SourceRange R;1809  if (!ArgExprs.empty()) {1810    R = SourceRange(ArgExprs.front()->getBeginLoc(),1811                    ArgExprs.back()->getEndLoc());1812  }1813 1814  return CheckMemberOperatorAccess(OpLoc, ObjectExpr, R, FoundDecl);1815}1816 1817Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {1818  assert(isa<CXXMethodDecl>(target->getAsFunction()));1819 1820  // Friendship lookup is a redeclaration lookup, so there's never an1821  // inheritance path modifying access.1822  AccessSpecifier access = target->getAccess();1823 1824  if (!getLangOpts().AccessControl || access == AS_public)1825    return AR_accessible;1826 1827  CXXMethodDecl *method = cast<CXXMethodDecl>(target->getAsFunction());1828 1829  AccessTarget entity(Context, AccessTarget::Member,1830                      cast<CXXRecordDecl>(target->getDeclContext()),1831                      DeclAccessPair::make(target, access),1832                      /*no instance context*/ QualType());1833  entity.setDiag(diag::err_access_friend_function)1834      << (method->getQualifier() ? method->getQualifierLoc().getSourceRange()1835                                 : method->getNameInfo().getSourceRange());1836 1837  // We need to bypass delayed-diagnostics because we might be called1838  // while the ParsingDeclarator is active.1839  EffectiveContext EC(CurContext);1840  switch (CheckEffectiveAccess(*this, EC, target->getLocation(), entity)) {1841  case ::AR_accessible: return Sema::AR_accessible;1842  case ::AR_inaccessible: return Sema::AR_inaccessible;1843  case ::AR_dependent: return Sema::AR_dependent;1844  }1845  llvm_unreachable("invalid access result");1846}1847 1848Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,1849                                                    DeclAccessPair Found) {1850  if (!getLangOpts().AccessControl ||1851      Found.getAccess() == AS_none ||1852      Found.getAccess() == AS_public)1853    return AR_accessible;1854 1855  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;1856  CXXRecordDecl *NamingClass = Ovl->getNamingClass();1857 1858  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,1859                      /*no instance context*/ QualType());1860  Entity.setDiag(diag::err_access)1861    << Ovl->getSourceRange();1862 1863  return CheckAccess(*this, Ovl->getNameLoc(), Entity);1864}1865 1866Sema::AccessResult Sema::CheckBaseClassAccess(1867    SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,1868    const CXXBasePath &Path, unsigned DiagID,1869    llvm::function_ref<void(PartialDiagnostic &)> SetupPDiag, bool ForceCheck,1870    bool ForceUnprivileged) {1871  if (!ForceCheck && !getLangOpts().AccessControl)1872    return AR_accessible;1873 1874  if (Path.Access == AS_public)1875    return AR_accessible;1876 1877  AccessTarget Entity(Context, AccessTarget::Base, Base, Derived, Path.Access);1878  if (DiagID)1879    SetupPDiag(Entity.setDiag(DiagID));1880 1881  if (ForceUnprivileged) {1882    switch (1883        CheckEffectiveAccess(*this, EffectiveContext(), AccessLoc, Entity)) {1884    case ::AR_accessible:1885      return Sema::AR_accessible;1886    case ::AR_inaccessible:1887      return Sema::AR_inaccessible;1888    case ::AR_dependent:1889      return Sema::AR_dependent;1890    }1891    llvm_unreachable("unexpected result from CheckEffectiveAccess");1892  }1893  return CheckAccess(*this, AccessLoc, Entity);1894}1895 1896Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,1897                                              QualType Base, QualType Derived,1898                                              const CXXBasePath &Path,1899                                              unsigned DiagID, bool ForceCheck,1900                                              bool ForceUnprivileged) {1901  return CheckBaseClassAccess(1902      AccessLoc, Base->getAsCXXRecordDecl(), Derived->getAsCXXRecordDecl(),1903      Path, DiagID, [&](PartialDiagnostic &PD) { PD << Derived << Base; },1904      ForceCheck, ForceUnprivileged);1905}1906 1907void Sema::CheckLookupAccess(const LookupResult &R) {1908  assert(getLangOpts().AccessControl1909         && "performing access check without access control");1910  assert(R.getNamingClass() && "performing access check without naming class");1911 1912  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {1913    if (I.getAccess() != AS_public) {1914      AccessTarget Entity(Context, AccessedEntity::Member,1915                          R.getNamingClass(), I.getPair(),1916                          R.getBaseObjectType());1917      Entity.setDiag(diag::err_access);1918      CheckAccess(*this, R.getNameLoc(), Entity);1919    }1920  }1921}1922 1923bool Sema::IsSimplyAccessible(NamedDecl *Target, CXXRecordDecl *NamingClass,1924                              QualType BaseType) {1925  // Perform the C++ accessibility checks first.1926  if (Target->isCXXClassMember() && NamingClass) {1927    if (!getLangOpts().CPlusPlus)1928      return false;1929    // The unprivileged access is AS_none as we don't know how the member was1930    // accessed, which is described by the access in DeclAccessPair.1931    // `IsAccessible` will examine the actual access of Target (i.e.1932    // Decl->getAccess()) when calculating the access.1933    AccessTarget Entity(Context, AccessedEntity::Member, NamingClass,1934                        DeclAccessPair::make(Target, AS_none), BaseType);1935    EffectiveContext EC(CurContext);1936    return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;1937  }1938 1939  if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Target)) {1940    // @public and @package ivars are always accessible.1941    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||1942        Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)1943      return true;1944 1945    // If we are inside a class or category implementation, determine the1946    // interface we're in.1947    ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;1948    if (ObjCMethodDecl *MD = getCurMethodDecl())1949      ClassOfMethodDecl =  MD->getClassInterface();1950    else if (FunctionDecl *FD = getCurFunctionDecl()) {1951      if (ObjCImplDecl *Impl1952            = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) {1953        if (ObjCImplementationDecl *IMPD1954              = dyn_cast<ObjCImplementationDecl>(Impl))1955          ClassOfMethodDecl = IMPD->getClassInterface();1956        else if (ObjCCategoryImplDecl* CatImplClass1957                   = dyn_cast<ObjCCategoryImplDecl>(Impl))1958          ClassOfMethodDecl = CatImplClass->getClassInterface();1959      }1960    }1961 1962    // If we're not in an interface, this ivar is inaccessible.1963    if (!ClassOfMethodDecl)1964      return false;1965 1966    // If we're inside the same interface that owns the ivar, we're fine.1967    if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))1968      return true;1969 1970    // If the ivar is private, it's inaccessible.1971    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private)1972      return false;1973 1974    return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);1975  }1976 1977  return true;1978}1979