//===--- AccessRequests.cpp - AccessLevel and AccessScope Requests --------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/AST/AccessRequests.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticsCommon.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/Types.h"

#include "llvm/Support/MathExtras.h"

using namespace swift;

namespace swift {
// Implement the access-control type zone.
#define SWIFT_TYPEID_ZONE SWIFT_ACCESSS_REQUESTS_TYPEID_ZONE
#define SWIFT_TYPEID_HEADER "swift/AST/AccessTypeIDZone.def"
#include "swift/Basic/ImplementTypeIDZone.h"
#undef SWIFT_TYPEID_ZONE
#undef SWIFT_TYPEID_HEADER
}

//----------------------------------------------------------------------------//
// AccessLevel computation
//----------------------------------------------------------------------------//
llvm::Expected<AccessLevel>
AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const {
  assert(!D->hasAccess());

  // Check if the decl has an explicit access control attribute.
  if (auto *AA = D->getAttrs().getAttribute<AccessControlAttr>())
    return AA->getAccess();

  // Special case for accessors, which inherit the access of their storage.
  // decl. A setter attribute can also override this.
  if (auto accessor = dyn_cast<AccessorDecl>(D)) {
    AbstractStorageDecl *storage = accessor->getStorage();
    switch (accessor->getAccessorKind()) {
    case AccessorKind::Get:
    case AccessorKind::Address:
    case AccessorKind::Read:
      return storage->getFormalAccess();
    case AccessorKind::Set:
    case AccessorKind::MutableAddress:
    case AccessorKind::Modify:
      return storage->getSetterFormalAccess();
    case AccessorKind::WillSet:
    case AccessorKind::DidSet:
      // These are only needed to synthesize the setter.
      return AccessLevel::Private;
    }
  }

  DeclContext *DC = D->getDeclContext();

  // Special case for generic parameters; we just give them a dummy
  // access level.
  if (auto genericParam = dyn_cast<GenericTypeParamDecl>(D)) {
    return AccessLevel::Internal;
  }

  // Special case for associated types: inherit access from protocol.
  if (auto assocType = dyn_cast<AssociatedTypeDecl>(D)) {
    auto prot = assocType->getProtocol();
    return std::max(prot->getFormalAccess(), AccessLevel::Internal);
  }

  // Special case for dtors and enum elements: inherit from container
  if (D->getKind() == DeclKind::Destructor ||
      D->getKind() == DeclKind::EnumElement) {
    if (D->isInvalid()) {
      return AccessLevel::Private;
    } else {
      auto container = cast<NominalTypeDecl>(D->getDeclContext());
      return std::max(container->getFormalAccess(), AccessLevel::Internal);
    }
  }

  switch (DC->getContextKind()) {
  case DeclContextKind::TopLevelCodeDecl:
    // Variables declared in a top-level 'guard' statement can be accessed in
    // later top-level code.
    return AccessLevel::FilePrivate;
  case DeclContextKind::AbstractClosureExpr:
    if (isa<ParamDecl>(D)) {
      // Closure parameters may need to be accessible to the enclosing
      // context, for single-expression closures.
      return AccessLevel::FilePrivate;
    } else {
      return AccessLevel::Private;
    }
  case DeclContextKind::SerializedLocal:
  case DeclContextKind::Initializer:
  case DeclContextKind::AbstractFunctionDecl:
  case DeclContextKind::SubscriptDecl:
    return AccessLevel::Private;
  case DeclContextKind::Module:
  case DeclContextKind::FileUnit:
    return AccessLevel::Internal;
  case DeclContextKind::GenericTypeDecl: {
    auto generic = cast<GenericTypeDecl>(DC);
    AccessLevel access = AccessLevel::Internal;
    if (isa<ProtocolDecl>(generic))
      access = std::max(AccessLevel::FilePrivate, generic->getFormalAccess());
    return access;
  }
  case DeclContextKind::ExtensionDecl:
    return cast<ExtensionDecl>(DC)->getDefaultAccessLevel();
  }
  llvm_unreachable("unhandled kind");
}

void AccessLevelRequest::diagnoseCycle(DiagnosticEngine &diags) const {
  // FIXME: Improve this diagnostic.
  auto valueDecl = std::get<0>(getStorage());
  diags.diagnose(valueDecl, diag::circular_reference);
}

void AccessLevelRequest::noteCycleStep(DiagnosticEngine &diags) const {
  auto valueDecl = std::get<0>(getStorage());
  // FIXME: Customize this further.
  diags.diagnose(valueDecl, diag::circular_reference_through);
}

Optional<AccessLevel> AccessLevelRequest::getCachedResult() const {
  auto valueDecl = std::get<0>(getStorage());
  if (valueDecl->hasAccess())
    return valueDecl->TypeAndAccess.getInt().getValue();

  return None;
}

void AccessLevelRequest::cacheResult(AccessLevel value) const {
  auto valueDecl = std::get<0>(getStorage());
  valueDecl->setAccess(value);
}

//----------------------------------------------------------------------------//
// SetterAccessLevel computation
//----------------------------------------------------------------------------//
//
// An AbstractStorageDecl has both its own formal access and also a special
// "setter" formal access like "private(set)" that might override (and lower)
// the normal one, when evaluating the accessibility of mutating accessors.
//
// As this value can be computed, stored, synthesized and set independently from
// the cycle of computation associated with formal accesses, we give it its own
// request.

llvm::Expected<AccessLevel>
SetterAccessLevelRequest::evaluate(Evaluator &evaluator,
                                   AbstractStorageDecl *ASD) const {
  assert(!ASD->Accessors.getInt().hasValue());
  if (auto *AA = ASD->getAttrs().getAttribute<SetterAccessAttr>())
    return AA->getAccess();
  return ASD->getFormalAccess();
}

void SetterAccessLevelRequest::diagnoseCycle(DiagnosticEngine &diags) const {
  // FIXME: Improve this diagnostic.
  auto abstractStorageDecl = std::get<0>(getStorage());
  diags.diagnose(abstractStorageDecl, diag::circular_reference);
}

void SetterAccessLevelRequest::noteCycleStep(DiagnosticEngine &diags) const {
  auto abstractStorageDecl = std::get<0>(getStorage());
  // FIXME: Customize this further.
  diags.diagnose(abstractStorageDecl, diag::circular_reference_through);
}

Optional<AccessLevel> SetterAccessLevelRequest::getCachedResult() const {
  auto abstractStorageDecl = std::get<0>(getStorage());
  if (abstractStorageDecl->Accessors.getInt().hasValue())
    return abstractStorageDecl->Accessors.getInt().getValue();

  return None;
}

void SetterAccessLevelRequest::cacheResult(AccessLevel value) const {
  auto abstractStorageDecl = std::get<0>(getStorage());
  // NB: don't call setSetterAccess here because it drives values through to the
  // associated accessors' formalAccess, which we might also be in the middle of
  // doing a request for. Reserve setSetterAccess for deserialization &
  // clangImporter use.
  assert(!abstractStorageDecl->Accessors.getInt().hasValue());
  abstractStorageDecl->Accessors.setInt(value);
}


//----------------------------------------------------------------------------//
// DefaultAccessLevel computation
//----------------------------------------------------------------------------//

llvm::Expected<std::pair<AccessLevel, AccessLevel>>
DefaultAndMaxAccessLevelRequest::evaluate(Evaluator &evaluator,
                                          ExtensionDecl *ED) const {
  auto &Ctx = ED->getASTContext();
  assert(!ED->hasDefaultAccessLevel());

  AccessLevel maxAccess = AccessLevel::Public;

  if (GenericParamList *genericParams = ED->getGenericParams()) {
    // Only check the trailing 'where' requirements. Other requirements come
    // from the extended type and have already been checked.
    DirectlyReferencedTypeDecls typeDecls =
      evaluateOrDefault(Ctx.evaluator, TypeDeclsFromWhereClauseRequest{ED}, {});

    Optional<AccessScope> maxScope = AccessScope::getPublic();

    for (auto *typeDecl : typeDecls) {
      if (isa<TypeAliasDecl>(typeDecl) || isa<NominalTypeDecl>(typeDecl)) {
        auto scope = typeDecl->getFormalAccessScope(ED->getDeclContext());
        maxScope = maxScope->intersectWith(scope);
      }
    }

    if (!maxScope.hasValue()) {
      // This is an error case and will be diagnosed elsewhere.
      maxAccess = AccessLevel::Public;
    } else if (maxScope->isPublic()) {
      maxAccess = AccessLevel::Public;
    } else if (isa<ModuleDecl>(maxScope->getDeclContext())) {
      maxAccess = AccessLevel::Internal;
    } else {
      // Because extensions are always at top-level, they should never
      // reference declarations not at the top level. (And any such references
      // should be diagnosed elsewhere.) This code should not crash if that
      // occurs, though.
      maxAccess = AccessLevel::FilePrivate;
    }
  }

  if (NominalTypeDecl *nominal = ED->getExtendedNominal()) {
    maxAccess = std::min(maxAccess,
                         std::max(nominal->getFormalAccess(),
                                  AccessLevel::FilePrivate));
  }

  AccessLevel defaultAccess;
  if (auto *AA = ED->getAttrs().getAttribute<AccessControlAttr>())
    defaultAccess = std::max(AA->getAccess(), AccessLevel::FilePrivate);
  else
    defaultAccess = AccessLevel::Internal;

  // Don't set the max or default access level to 'open'.  This should
  // be diagnosed as invalid anyway.
  defaultAccess = std::min(defaultAccess, AccessLevel::Public);
  maxAccess = std::min(maxAccess, AccessLevel::Public);

  // Normally putting a public member in an internal extension is harmless,
  // because that member can never be used elsewhere. But if some of the types
  // in the signature are public, it could actually end up getting picked in
  // overload resolution. Therefore, we only enforce the maximum access if the
  // extension has a 'where' clause.
  if (ED->getTrailingWhereClause())
    defaultAccess = std::min(defaultAccess, maxAccess);
  else
    maxAccess = AccessLevel::Public;

  return std::make_pair(defaultAccess, maxAccess);
}

void DefaultAndMaxAccessLevelRequest::diagnoseCycle(DiagnosticEngine &diags) const {
  // FIXME: Improve this diagnostic.
  auto extensionDecl = std::get<0>(getStorage());
  diags.diagnose(extensionDecl, diag::circular_reference);
}

void DefaultAndMaxAccessLevelRequest::noteCycleStep(DiagnosticEngine &diags) const {
  auto extensionDecl = std::get<0>(getStorage());
  // FIXME: Customize this further.
  diags.diagnose(extensionDecl, diag::circular_reference_through);
}

// Default and Max access levels are stored combined as a 3-bit bitset. The Bits
// are numbered using the 3 middle values of the AccessLevel enumeration, and
// the combined value is just the bitwise-OR of the bits for Default and Max.
//
// For example, if Max=Internal and Default=FilePrivate, we will see:
//
//      0 1 1
//      | | |
//      | | [FilePrivate]
//      | |
//      | [Internal]
//      |
//      [Public]
//
// This is unambiguous to decode because of the following facts:
//
//   - At least one of the bits is set (all-zero means "not yet set").
//   - At most two of the bits are set.
//   - Max >= Default by definition.
//
// So we decode Max as the last (high) bit that is set, and Default as the first
// (low). And add one to each, to map them back into AccessLevels.

Optional<std::pair<AccessLevel,AccessLevel>>
DefaultAndMaxAccessLevelRequest::getCachedResult() const {
  auto extensionDecl = std::get<0>(getStorage());
  if (extensionDecl->hasDefaultAccessLevel()) {
    uint8_t Bits = extensionDecl->getDefaultAndMaxAccessLevelBits();
    assert(Bits != 0x7 && "more than two bits set for Default and Max");
    AccessLevel Max = static_cast<AccessLevel>(llvm::findLastSet(Bits) + 1);
    AccessLevel Default = static_cast<AccessLevel>(llvm::findFirstSet(Bits) + 1);
    assert(Max >= Default);
    return std::make_pair(Default, Max);
  }
  return None;
}

void
DefaultAndMaxAccessLevelRequest::cacheResult(
  std::pair<AccessLevel, AccessLevel> value) const {
  auto extensionDecl = std::get<0>(getStorage());
  extensionDecl->setDefaultAndMaxAccessLevelBits(value.first, value.second);
  assert(getCachedResult().getValue().first == value.first);
  assert(getCachedResult().getValue().second == value.second);
}

// Define request evaluation functions for each of the access requests.
static AbstractRequestFunction *accessRequestFunctions[] = {
#define SWIFT_TYPEID(Name)                                    \
  reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
#include "swift/AST/AccessTypeIDZone.def"
#undef SWIFT_TYPEID
};

void swift::registerAccessRequestFunctions(Evaluator &evaluator) {
  evaluator.registerRequestFunctions(SWIFT_ACCESS_REQUESTS_TYPEID_ZONE,
                                     accessRequestFunctions);
}
