//===--- ASTContext.h - AST Context Object ----------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the ASTContext interface.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_ASTCONTEXT_H
#define SWIFT_AST_ASTCONTEXT_H

#include "swift/AST/Evaluator.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Import.h"
#include "swift/AST/SearchPathOptions.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/Types.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/Located.h"
#include "swift/Basic/Malloc.h"
#include "clang/AST/DeclTemplate.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include <functional>
#include <memory>
#include <utility>
#include <vector>

namespace clang {
  class Decl;
  class MacroInfo;
  class Module;
  class ObjCInterfaceDecl;
}

namespace llvm {
  class LLVMContext;
}

namespace swift {
  class AbstractFunctionDecl;
  class ASTContext;
  enum class Associativity : unsigned char;
  class AvailabilityContext;
  class BoundGenericType;
  class ClangModuleLoader;
  class ClangNode;
  class ClangTypeConverter;
  class ConcreteDeclRef;
  class ConstructorDecl;
  class Decl;
  class DeclContext;
  class DefaultArgumentInitializer;
  class DerivativeAttr;
  class DifferentiableAttr;
  class ExtensionDecl;
  class ForeignRepresentationInfo;
  class FuncDecl;
  class GenericContext;
  class InFlightDiagnostic;
  class IterableDeclContext;
  class LazyContextData;
  class LazyIterableDeclContextData;
  class LazyMemberLoader;
  class ModuleDependencies;
  class PatternBindingDecl;
  class PatternBindingInitializer;
  class SourceFile;
  class SourceLoc;
  class Type;
  class TypeVariableType;
  class TupleType;
  class FunctionType;
  class GenericSignatureBuilder;
  class ArchetypeType;
  class Identifier;
  class InheritedNameSet;
  class ModuleDecl;
  class ModuleDependenciesCache;
  class ModuleLoader;
  class NominalTypeDecl;
  class NormalProtocolConformance;
  class OpaqueTypeDecl;
  class InheritedProtocolConformance;
  class SelfProtocolConformance;
  class SpecializedProtocolConformance;
  enum class ProtocolConformanceState;
  class Pattern;
  enum PointerTypeKind : unsigned;
  class PrecedenceGroupDecl;
  class TupleTypeElt;
  class EnumElementDecl;
  class ProtocolDecl;
  class SubstitutableType;
  class SourceManager;
  class ValueDecl;
  class DiagnosticEngine;
  struct RawComment;
  class DocComment;
  class SILBoxType;
  class SILTransform;
  class TypeAliasDecl;
  class VarDecl;
  class UnifiedStatsReporter;
  class IndexSubset;
  struct SILAutoDiffDerivativeFunctionKey;
  struct InterfaceSubContextDelegate;
  class TypeCheckCompletionCallback;

  enum class KnownProtocolKind : uint8_t;

namespace namelookup {
  class ImportCache;
}

namespace syntax {
  class SyntaxArena;
}

/// The arena in which a particular ASTContext allocation will go.
enum class AllocationArena {
  /// The permanent arena, which is tied to the lifetime of
  /// the ASTContext.
  ///
  /// All global declarations and types need to be allocated into this arena.
  /// At present, everything that is not a type involving a type variable is
  /// allocated in this arena.
  Permanent,
  /// The constraint solver's temporary arena, which is tied to the
  /// lifetime of a particular instance of the constraint solver.
  ///
  /// Any type involving a type variable is allocated in this arena.
  ConstraintSolver
};

/// Lists the set of "known" Foundation entities that are used in the
/// compiler.
///
/// While the names of Foundation types aren't likely to change in
/// Objective-C, their mapping into Swift can. Therefore, when
/// referring to names of Foundation entities in Swift, use this enum
/// and \c ASTContext::getSwiftName or \c ASTContext::getSwiftId.
enum class KnownFoundationEntity {
#define FOUNDATION_ENTITY(Name) Name,
#include "swift/AST/KnownFoundationEntities.def"
};

/// Retrieve the Foundation entity kind for the given Objective-C
/// entity name.
Optional<KnownFoundationEntity> getKnownFoundationEntity(StringRef name);

/// Introduces a new constraint checker arena, whose lifetime is
/// tied to the lifetime of this RAII object.
class ConstraintCheckerArenaRAII {
  ASTContext &Self;
  void *Data;

public:
  /// Introduces a new constraint checker arena, supplanting any
  /// existing constraint checker arena.
  ///
  /// \param self The ASTContext into which this constraint checker arena
  /// will be installed.
  ///
  /// \param allocator The allocator used for allocating any data that
  /// goes into the constraint checker arena.
  ConstraintCheckerArenaRAII(ASTContext &self,
                             llvm::BumpPtrAllocator &allocator);

  ConstraintCheckerArenaRAII(const ConstraintCheckerArenaRAII &) = delete;
  ConstraintCheckerArenaRAII(ConstraintCheckerArenaRAII &&) = delete;

  ConstraintCheckerArenaRAII &
  operator=(const ConstraintCheckerArenaRAII &) = delete;

  ConstraintCheckerArenaRAII &
  operator=(ConstraintCheckerArenaRAII &&) = delete;

  ~ConstraintCheckerArenaRAII();
};

class SILLayout; // From SIL

/// A set of missing witnesses for a given conformance. These are temporarily
/// stashed in the ASTContext so the type checker can get at them.
///
/// The only subclass is owned by the type checker, so it can hide its own
/// data structures.
class MissingWitnessesBase {
public:
  virtual ~MissingWitnessesBase();
};

/// ASTContext - This object creates and owns the AST objects.
/// However, this class does more than just maintain context within an AST.
/// It is the closest thing to thread-local or compile-local storage in this
/// code base. Why? SourceKit uses this code with multiple threads per Unix
/// process. Each thread processes a different source file. Each thread has its
/// own instance of ASTContext, and that instance persists for the duration of
/// the thread, throughout all phases of the compilation. (The name "ASTContext"
/// is a bit of a misnomer here.) Why not use thread-local storage? This code
/// may use DispatchQueues and pthread-style TLS won't work with code that uses
/// DispatchQueues. Summary: if you think you need a global or static variable,
/// you probably need to put it here instead.

class ASTContext final {
  ASTContext(const ASTContext&) = delete;
  void operator=(const ASTContext&) = delete;

  ASTContext(LangOptions &langOpts, TypeCheckerOptions &typeckOpts,
             SearchPathOptions &SearchPathOpts,
             ClangImporterOptions &ClangImporterOpts,
             SourceManager &SourceMgr,
             DiagnosticEngine &Diags);

public:
  // Members that should only be used by ASTContext.cpp.
  struct Implementation;
  Implementation &getImpl() const;

  friend ConstraintCheckerArenaRAII;

  void operator delete(void *Data) throw();

  static ASTContext *get(LangOptions &langOpts, TypeCheckerOptions &typeckOpts,
                         SearchPathOptions &SearchPathOpts,
                         ClangImporterOptions &ClangImporterOpts,
                         SourceManager &SourceMgr, DiagnosticEngine &Diags);
  ~ASTContext();

  /// Optional table of counters to report, nullptr when not collecting.
  ///
  /// This must be initialized early so that Allocate() doesn't try to access
  /// it before being set to null.
  UnifiedStatsReporter *Stats = nullptr;

  /// The language options used for translation.
  const LangOptions &LangOpts;

  /// The type checker options.
  const TypeCheckerOptions &TypeCheckerOpts;

  /// The search path options used by this AST context.
  SearchPathOptions &SearchPathOpts;

  /// The clang importer options used by this AST context.
  ClangImporterOptions &ClangImporterOpts;

  /// The source manager object.
  SourceManager &SourceMgr;

  /// Diags - The diagnostics engine.
  DiagnosticEngine &Diags;

  TypeCheckCompletionCallback *CompletionCallback = nullptr;

  /// The request-evaluator that is used to process various requests.
  Evaluator evaluator;

  /// The builtin module.
  ModuleDecl * const TheBuiltinModule;

  /// The standard library module.
  mutable ModuleDecl *TheStdlibModule = nullptr;

  /// The name of the standard library module "Swift".
  Identifier StdlibModuleName;

  /// The name of the SwiftShims module "SwiftShims".
  Identifier SwiftShimsModuleName;

  // Define the set of known identifiers.
#define IDENTIFIER_WITH_NAME(Name, IdStr) Identifier Id_##Name;
#include "swift/AST/KnownIdentifiers.def"

  /// Cache for names of canonical GenericTypeParamTypes.
  mutable llvm::DenseMap<unsigned, Identifier>
    CanonicalGenericTypeParamTypeNames;

  /// Cache of remapped types (useful for diagnostics).
  llvm::StringMap<Type> RemappedTypes;

  /// The # of times we have performed typo correction.
  unsigned NumTypoCorrections = 0;

  /// The next auto-closure discriminator.  This needs to be preserved
  /// across invocations of both the parser and the type-checker.
  unsigned NextAutoClosureDiscriminator = 0;

  /// Cached mapping from types to their associated tangent spaces.
  llvm::DenseMap<Type, Optional<TangentSpace>> AutoDiffTangentSpaces;
  
  /// A cache of derivative function types per configuration.
  llvm::DenseMap<SILAutoDiffDerivativeFunctionKey, CanSILFunctionType>
      SILAutoDiffDerivativeFunctions;

  /// Cache of `@differentiable` attributes keyed by parameter indices. Used to
  /// diagnose duplicate `@differentiable` attributes for the same key.
  llvm::DenseMap<std::pair<Decl *, IndexSubset *>, DifferentiableAttr *>
      DifferentiableAttrs;

  /// Cache of `@derivative` attributes keyed by parameter indices and
  /// derivative function kind. Used to diagnose duplicate `@derivative`
  /// attributes for the same key.
  // NOTE(TF-680): relaxing the uniqueness condition to use derivative generic
  // signature as a key is possible. It requires derivative generic signature
  // mangling to avoid name collisions for SIL derivative functions with the
  // same parameter indices but different derivative generic signatures.
  llvm::DenseMap<
      std::tuple<Decl *, IndexSubset *, AutoDiffDerivativeFunctionKind>,
      llvm::SmallPtrSet<DerivativeAttr *, 1>>
      DerivativeAttrs;

private:
  /// The current generation number, which reflects the number of
  /// times that external modules have been loaded.
  ///
  /// Various places in the AST, such as the set of extensions associated with
  /// a nominal type, keep track of the generation number they saw and will
  /// automatically update when they are out of date.
  unsigned CurrentGeneration = 0;

  friend class Pattern;

  /// Mapping from patterns that store interface types that will be lazily
  /// resolved to contextual types, to the declaration context in which the
  /// pattern resides.
  llvm::DenseMap<const Pattern *, DeclContext *>
    DelayedPatternContexts;

  /// Cache of module names that fail the 'canImport' test in this context.
  llvm::SmallPtrSet<Identifier, 8> FailedModuleImportNames;
  
public:
  /// Retrieve the allocator for the given arena.
  llvm::BumpPtrAllocator &
  getAllocator(AllocationArena arena = AllocationArena::Permanent) const;

public:
  /// Allocate - Allocate memory from the ASTContext bump pointer.
  void *Allocate(unsigned long bytes, unsigned alignment,
                 AllocationArena arena = AllocationArena::Permanent) const {
    if (bytes == 0)
      return nullptr;

    if (LangOpts.UseMalloc)
      return AlignedAlloc(bytes, alignment);

    if (arena == AllocationArena::Permanent && Stats)
      Stats->getFrontendCounters().NumASTBytesAllocated += bytes;
    return getAllocator(arena).Allocate(bytes, alignment);
  }

  template <typename T>
  T *Allocate(AllocationArena arena = AllocationArena::Permanent) const {
    T *res = (T *) Allocate(sizeof(T), alignof(T), arena);
    new (res) T();
    return res;
  }

  template <typename T>
  MutableArrayRef<T> AllocateUninitialized(unsigned NumElts,
              AllocationArena Arena = AllocationArena::Permanent) const {
    T *Data = (T *) Allocate(sizeof(T) * NumElts, alignof(T), Arena);
    return { Data, NumElts };
  }

  template <typename T>
  MutableArrayRef<T> Allocate(unsigned numElts,
              AllocationArena arena = AllocationArena::Permanent) const {
    T *res = (T *) Allocate(sizeof(T) * numElts, alignof(T), arena);
    for (unsigned i = 0; i != numElts; ++i)
      new (res+i) T();
    return {res, numElts};
  }

  /// Allocate a copy of the specified object.
  template <typename T>
  typename std::remove_reference<T>::type *AllocateObjectCopy(T &&t,
              AllocationArena arena = AllocationArena::Permanent) const {
    // This function cannot be named AllocateCopy because it would always win
    // overload resolution over the AllocateCopy(ArrayRef<T>).
    using TNoRef = typename std::remove_reference<T>::type;
    TNoRef *res = (TNoRef *) Allocate(sizeof(TNoRef), alignof(TNoRef), arena);
    new (res) TNoRef(std::forward<T>(t));
    return res;
  }

  template <typename T, typename It>
  T *AllocateCopy(It start, It end,
                  AllocationArena arena = AllocationArena::Permanent) const {
    T *res = (T*)Allocate(sizeof(T)*(end-start), alignof(T), arena);
    for (unsigned i = 0; start != end; ++start, ++i)
      new (res+i) T(*start);
    return res;
  }

  template<typename T, size_t N>
  MutableArrayRef<T> AllocateCopy(T (&array)[N],
      AllocationArena arena = AllocationArena::Permanent) const {
    return MutableArrayRef<T>(AllocateCopy<T>(array, array+N, arena), N);
  }

  template<typename T>
  MutableArrayRef<T> AllocateCopy(ArrayRef<T> array,
      AllocationArena arena = AllocationArena::Permanent) const {
    return MutableArrayRef<T>(AllocateCopy<T>(array.begin(),array.end(), arena),
                              array.size());
  }

  template <typename T>
  MutableArrayRef<T>
  AllocateCopy(const std::vector<T> &vec,
               AllocationArena arena = AllocationArena::Permanent) const {
    return AllocateCopy(ArrayRef<T>(vec), arena);
  }

  template<typename T>
  ArrayRef<T> AllocateCopy(const SmallVectorImpl<T> &vec,
      AllocationArena arena = AllocationArena::Permanent) const {
    return AllocateCopy(ArrayRef<T>(vec), arena);
  }

  template<typename T>
  MutableArrayRef<T>
  AllocateCopy(SmallVectorImpl<T> &vec,
               AllocationArena arena = AllocationArena::Permanent) const {
    return AllocateCopy(MutableArrayRef<T>(vec), arena);
  }

  StringRef AllocateCopy(StringRef Str,
                    AllocationArena arena = AllocationArena::Permanent) const {
    ArrayRef<char> Result =
        AllocateCopy(llvm::makeArrayRef(Str.data(), Str.size()), arena);
    return StringRef(Result.data(), Result.size());
  }

  template<typename T, typename Vector, typename Set>
  MutableArrayRef<T>
  AllocateCopy(llvm::SetVector<T, Vector, Set> setVector,
               AllocationArena arena = AllocationArena::Permanent) const {
    return MutableArrayRef<T>(AllocateCopy<T>(setVector.begin(),
                                              setVector.end(),
                                              arena),
                              setVector.size());
  }

  /// Retrive the syntax node memory manager for this context.
  llvm::IntrusiveRefCntPtr<syntax::SyntaxArena> getSyntaxArena() const;

  /// Set a new stats reporter.
  void setStatsReporter(UnifiedStatsReporter *stats);

public:
  /// getIdentifier - Return the uniqued and AST-Context-owned version of the
  /// specified string.
  Identifier getIdentifier(StringRef Str) const;

  /// Decide how to interpret two precedence groups.
  Associativity associateInfixOperators(PrecedenceGroupDecl *left,
                                        PrecedenceGroupDecl *right) const;

  /// Retrieve the declaration of Swift.Error.
  ProtocolDecl *getErrorDecl() const;
  CanType getExceptionType() const;
  
#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
  /** Retrieve the declaration of Swift.NAME. */ \
  DECL_CLASS *get##NAME##Decl() const;
#include "swift/AST/KnownStdlibTypes.def"

  /// Retrieve the declaration of Swift.Optional<T>.Some.
  EnumElementDecl *getOptionalSomeDecl() const;
  
  /// Retrieve the declaration of Swift.Optional<T>.None.
  EnumElementDecl *getOptionalNoneDecl() const;

  /// Retrieve the declaration of the "pointee" property of a pointer type.
  VarDecl *getPointerPointeePropertyDecl(PointerTypeKind ptrKind) const;

  /// Retrieve the type Swift.AnyObject.
  CanType getAnyObjectType() const;

  // SWIFT_ENABLE_TENSORFLOW
  /// Retrieve the decl for TensorFlow.TensorHandle iff the TensorFlow module
  /// has been imported.  Otherwise, this returns null.
  ClassDecl *getTensorHandleDecl() const;

  /// Retrieve the decl for TensorFlow.TensorShape iff the TensorFlow module
  /// has been imported.  Otherwise, this returns null.
  StructDecl *getTensorShapeDecl() const;

  /// Retrieve the decl for TensorFlow.TensorDataType iff the TensorFlow module
  /// has been imported.  Otherwise, this returns null.
  StructDecl *getTensorDataTypeDecl() const;

  /// Retrieve the decl for the Quote module iff it has been imported.
  /// Otherwise, this returns null.
  ModuleDecl *getQuoteModule() const;

  /// Retrieve the decl for Quote.Tree iff the Quote module has been imported.
  /// Otherwise, this returns null.
  ProtocolDecl *getTreeDecl() const;

  /// Retrieve the decl for Quote.Quote iff the Quote module has been imported.
  /// Otherwise, this returns null.
  ClassDecl *getQuoteDecl() const;

  /// Retrieve the decl for Quote.FunctionQuoteN iff the Quote module has been
  /// imported. Otherwise, this returns null.
  ClassDecl *getFunctionQuoteDecl(unsigned n) const;

  /// Retrieve the type Swift.Never.
  CanType getNeverType() const;

#define KNOWN_SDK_TYPE_DECL(MODULE, NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
  /** Retrieve the declaration of MODULE.NAME. */ \
  DECL_CLASS *get##NAME##Decl() const; \
\
  /** Retrieve the type of MODULE.NAME. */ \
  Type get##NAME##Type() const;
#include "swift/AST/KnownSDKTypes.def"

  // Declare accessors for the known declarations.
#define FUNC_DECL(Name, Id) \
  FuncDecl *get##Name() const;
#include "swift/AST/KnownDecls.def"

  /// Get the '+' function on two RangeReplaceableCollection.
  FuncDecl *getPlusFunctionOnRangeReplaceableCollection() const;

  /// Get the '+' function on two String.
  FuncDecl *getPlusFunctionOnString() const;

  /// Get Sequence.makeIterator().
  FuncDecl *getSequenceMakeIterator() const;

  /// Check whether the standard library provides all the correct
  /// intrinsic support for Optional<T>.
  ///
  /// If this is true, the four methods above all promise to return
  /// non-null.
  bool hasOptionalIntrinsics() const;

  /// Check whether the standard library provides all the correct
  /// intrinsic support for UnsafeMutablePointer<T> function arguments.
  ///
  /// If this is true, the methods getConvert*ToPointerArgument
  /// all promise to return non-null.
  bool hasPointerArgumentIntrinsics() const;

  /// Check whether the standard library provides all the correct
  /// intrinsic support for array literals.
  ///
  /// If this is true, the method getAllocateUninitializedArray
  /// promises to return non-null.
  bool hasArrayLiteralIntrinsics() const;

  /// Retrieve the declaration of Swift.Bool.init(_builtinBooleanLiteral:)
  ConcreteDeclRef getBoolBuiltinInitDecl() const;

  /// Retrieve the witness for init(_builtinIntegerLiteral:).
  ConcreteDeclRef getIntBuiltinInitDecl(NominalTypeDecl *intDecl) const;

  /// Retrieve the witness for init(_builtinFloatLiteral:).
  ConcreteDeclRef getFloatBuiltinInitDecl(NominalTypeDecl *floatDecl) const;

  /// Retrieve the witness for (_builtinStringLiteral:utf8CodeUnitCount:isASCII:).
  ConcreteDeclRef getStringBuiltinInitDecl(NominalTypeDecl *stringDecl) const;

  ConcreteDeclRef getBuiltinInitDecl(NominalTypeDecl *decl,
                                     KnownProtocolKind builtinProtocol,
                llvm::function_ref<DeclName (ASTContext &ctx)> initName) const;
  
  /// Retrieve the declaration of Swift.<(Int, Int) -> Bool.
  FuncDecl *getLessThanIntDecl() const;

  /// Retrieve the declaration of Swift.==(Int, Int) -> Bool.
  FuncDecl *getEqualIntDecl() const;

  /// Retrieve the declaration of Swift._hashValue<H>(for: H) -> Int.
  FuncDecl *getHashValueForDecl() const;

  /// Retrieve the declaration of Array.append(element:)
  FuncDecl *getArrayAppendElementDecl() const;

  /// Retrieve the declaration of
  /// Array.reserveCapacityForAppend(newElementsCount: Int)
  FuncDecl *getArrayReserveCapacityDecl() const;

  /// Retrieve the declaration of String.init(_builtinStringLiteral ...)
  ConstructorDecl *getMakeUTF8StringDecl() const;

  // Retrieve the declaration of Swift._stdlib_isOSVersionAtLeast.
  FuncDecl *getIsOSVersionAtLeastDecl() const;

  /// Look for the declaration with the given name within the
  /// Swift module.
  void lookupInSwiftModule(StringRef name,
                           SmallVectorImpl<ValueDecl *> &results) const;

  /// Retrieve a specific, known protocol.
  ProtocolDecl *getProtocol(KnownProtocolKind kind) const;
  
  /// Determine whether the given nominal type is one of the standard
  /// library or Cocoa framework types that is known to be bridged by another
  /// module's overlay, for layering or implementation detail reasons.
  bool isTypeBridgedInExternalModule(NominalTypeDecl *nominal) const;

  /// True if the given type is an Objective-C class that serves as the bridged
  /// object type for many Swift value types, meaning that the conversion from
  /// an object to a value is a conditional cast.
  bool isObjCClassWithMultipleSwiftBridgedTypes(Type t);

  /// Get the Objective-C type that a Swift type bridges to, if any.
  /// 
  /// \param dc The context in which bridging is occurring.
  /// \param type The Swift for which we are querying bridging behavior.
  /// \param bridgedValueType The specific value type that is bridged,
  /// which will usually by the same as \c type.
  Type getBridgedToObjC(const DeclContext *dc, Type type,
                        Type *bridgedValueType = nullptr) const;

private:
  ClangTypeConverter &getClangTypeConverter();

public:
  /// Get the Clang type corresponding to a Swift function type.
  ///
  /// \param params The function parameters.
  /// \param resultTy The Swift result type.
  /// \param trueRep The actual calling convention, which must be C-compatible.
  const clang::Type *
  getClangFunctionType(ArrayRef<AnyFunctionType::Param> params, Type resultTy,
                       FunctionTypeRepresentation trueRep);

  /// Get the canonical Clang type corresponding to a SIL function type.
  ///
  /// SIL analog of \c ASTContext::getClangFunctionType .
  const clang::Type *
  getCanonicalClangFunctionType(
    ArrayRef<SILParameterInfo> params, Optional<SILResultInfo> result,
    SILFunctionType::Representation trueRep);

  /// Instantiates "Impl.Converter" if needed, then calls
  /// ClangTypeConverter::getClangTemplateArguments.
  std::unique_ptr<TemplateInstantiationError> getClangTemplateArguments(
      const clang::TemplateParameterList *templateParams,
      ArrayRef<Type> genericArgs,
      SmallVectorImpl<clang::TemplateArgument> &templateArgs);

  /// Get the Swift declaration that a Clang declaration was exported from,
  /// if applicable.
  const Decl *getSwiftDeclForExportedClangDecl(const clang::Decl *decl);

  /// General conversion method from Swift types -> Clang types.
  ///
  /// HACK: This method is only intended to be called from a specific place in
  /// IRGen. For converting function types, strongly prefer using one of the
  /// other methods instead, instead of manually iterating over parameters
  /// and results.
  const clang::Type *getClangTypeForIRGen(Type ty);

  /// Determine whether the given Swift type is representable in a
  /// given foreign language.
  ForeignRepresentationInfo
  getForeignRepresentationInfo(NominalTypeDecl *nominal,
                               ForeignLanguage language,
                               const DeclContext *dc);

  /// Add a cleanup function to be called when the ASTContext is deallocated.
  void addCleanup(std::function<void(void)> cleanup);

  /// Add a cleanup to run the given object's destructor when the ASTContext is
  /// deallocated.
  template<typename T>
  void addDestructorCleanup(T &object) {
    addCleanup([&object]{ object.~T(); });
  }

  /// Get the runtime availability of the class metadata update callback
  /// mechanism for the target platform.
  AvailabilityContext getObjCMetadataUpdateCallbackAvailability();

  /// Get the runtime availability of the objc_getClass() hook for the target
  /// platform.
  AvailabilityContext getObjCGetClassHookAvailability();
  
  /// Get the runtime availability of features introduced in the Swift 5.0
  /// compiler for the target platform.
  AvailabilityContext getSwift50Availability();

  /// Get the runtime availability of the opaque types language feature for the
  /// target platform.
  AvailabilityContext getOpaqueTypeAvailability();

  /// Get the runtime availability of the objc_loadClassref() entry point for
  /// the target platform.
  AvailabilityContext getObjCClassStubsAvailability();

  /// Get the runtime availability of features introduced in the Swift 5.1
  /// compiler for the target platform.
  AvailabilityContext getSwift51Availability();

  /// Get the runtime availability of
  /// swift_getTypeByMangledNameInContextInMetadataState.
  AvailabilityContext getTypesInAbstractMetadataStateAvailability();

  /// Get the runtime availability of support for prespecialized generic 
  /// metadata.
  AvailabilityContext getPrespecializedGenericMetadataAvailability();

  /// Get the runtime availability of the swift_compareTypeContextDescriptors
  /// for the target platform.
  AvailabilityContext getCompareTypeContextDescriptorsAvailability();

  /// Get the runtime availability of the
  /// swift_compareProtocolConformanceDescriptors entry point for the target
  /// platform.
  AvailabilityContext getCompareProtocolConformanceDescriptorsAvailability();

  /// Get the runtime availability of support for inter-module prespecialized
  /// generic metadata.
  AvailabilityContext getIntermodulePrespecializedGenericMetadataAvailability();

  /// Get the runtime availability of support for concurrency.
  AvailabilityContext getConcurrencyAvailability();

  /// Get the runtime availability of support for differentiation.
  AvailabilityContext getDifferentiationAvailability();

  /// Get the runtime availability of features introduced in the Swift 5.2
  /// compiler for the target platform.
  AvailabilityContext getSwift52Availability();

  /// Get the runtime availability of features introduced in the Swift 5.3
  /// compiler for the target platform.
  AvailabilityContext getSwift53Availability();

  /// Get the runtime availability of features introduced in the Swift 5.4
  /// compiler for the target platform.
  AvailabilityContext getSwift54Availability();

  /// Get the runtime availability of features that have been introduced in the
  /// Swift compiler for future versions of the target platform.
  AvailabilityContext getSwiftFutureAvailability();


  //===--------------------------------------------------------------------===//
  // Diagnostics Helper functions
  //===--------------------------------------------------------------------===//

  bool hadError() const;
  
  //===--------------------------------------------------------------------===//
  // Type manipulation routines.
  //===--------------------------------------------------------------------===//

  // Builtin type and simple types that are used frequently.
  const CanType TheErrorType;             /// This is the ErrorType singleton.
  const CanType TheUnresolvedType;        /// This is the UnresolvedType singleton.
  const CanType TheEmptyTupleType;        /// This is '()', aka Void
  const CanType TheAnyType;               /// This is 'Any', the empty protocol composition
#define SINGLETON_TYPE(SHORT_ID, ID) \
  const CanType The##SHORT_ID##Type;
#include "swift/AST/TypeNodes.def"

  const CanType TheIEEE32Type;            /// 32-bit IEEE floating point
  const CanType TheIEEE64Type;            /// 64-bit IEEE floating point
  
  // Target specific types.
  const CanType TheIEEE16Type;            /// 16-bit IEEE floating point
  const CanType TheIEEE80Type;            /// 80-bit IEEE floating point
  const CanType TheIEEE128Type;           /// 128-bit IEEE floating point
  const CanType ThePPC128Type;            /// 128-bit PowerPC 2xDouble
  
  /// Adds a search path to SearchPathOpts, unless it is already present.
  ///
  /// Does any proper bookkeeping to keep all module loaders up to date as well.
  void addSearchPath(StringRef searchPath, bool isFramework, bool isSystem);

  /// Adds a module loader to this AST context.
  ///
  /// \param loader The new module loader, which will be added after any
  ///               existing module loaders.
  /// \param isClang \c true if this module loader is responsible for loading
  ///                Clang modules, which are special-cased in some parts of the
  ///                compiler.
  /// \param isDWARF \c true if this module loader can load Clang modules
  ///                from DWARF.
  /// \param IsInterface \c true if this module loader can load Swift textual
  ///                interface.
  void addModuleLoader(std::unique_ptr<ModuleLoader> loader,
                       bool isClang = false, bool isDWARF = false,
                       bool IsInterface = false);

  /// Add a module interface checker to use for this AST context.
  void addModuleInterfaceChecker(std::unique_ptr<ModuleInterfaceChecker> checker);

  /// Retrieve the module interface checker associated with this AST context.
  ModuleInterfaceChecker *getModuleInterfaceChecker() const;

  /// Retrieve the module dependencies for the module with the given name.
  ///
  /// \param isUnderlyingClangModule When true, only look for a Clang module
  /// with the given name, ignoring any Swift modules.
  Optional<ModuleDependencies> getModuleDependencies(
      StringRef moduleName,
      bool isUnderlyingClangModule,
      ModuleDependenciesCache &cache,
      InterfaceSubContextDelegate &delegate);

  /// Retrieve the module dependencies for the Swift module with the given name.
  Optional<ModuleDependencies> getSwiftModuleDependencies(
      StringRef moduleName,
      ModuleDependenciesCache &cache,
      InterfaceSubContextDelegate &delegate);

  /// Load extensions to the given nominal type from the external
  /// module loaders.
  ///
  /// \param nominal The nominal type whose extensions should be loaded.
  ///
  /// \param previousGeneration The previous generation number. The AST already
  /// contains extensions loaded from any generation up to and including this
  /// one.
  void loadExtensions(NominalTypeDecl *nominal, unsigned previousGeneration);

  /// Load the methods within the given class that produce
  /// Objective-C class or instance methods with the given selector.
  ///
  /// \param classDecl The class in which we are searching for @objc methods.
  /// The search only considers this class and its extensions; not any
  /// superclasses.
  ///
  /// \param selector The selector to search for.
  ///
  /// \param isInstanceMethod Whether we are looking for an instance method
  /// (vs. a class method).
  ///
  /// \param previousGeneration The previous generation with which this
  /// callback was invoked. The list of methods will already contain all of
  /// the results from generations up and including \c previousGeneration.
  ///
  /// \param methods The list of @objc methods in this class that have this
  /// selector and are instance/class methods as requested. This list will be
  /// extended with any methods found in subsequent generations.
  ///
  /// \param swiftOnly If true, only loads methods from imported Swift modules,
  /// skipping the Clang importer.
  void loadObjCMethods(ClassDecl *classDecl, ObjCSelector selector,
                       bool isInstanceMethod, unsigned previousGeneration,
                       llvm::TinyPtrVector<AbstractFunctionDecl *> &methods,
                       bool swiftOnly = false);

  /// Load derivative function configurations for the given
  /// AbstractFunctionDecl.
  ///
  /// \param originalAFD The declaration whose derivative function
  /// configurations should be loaded.
  ///
  /// \param previousGeneration The previous generation number. The AST already
  /// contains derivative function configurations loaded from any generation up
  /// to and including this one.
  void loadDerivativeFunctionConfigurations(
      AbstractFunctionDecl *originalAFD, unsigned previousGeneration,
      llvm::SetVector<AutoDiffConfig> &results);

  /// Retrieve the Clang module loader for this ASTContext.
  ///
  /// If there is no Clang module loader, returns a null pointer.
  /// The loader is owned by the AST context.
  ClangModuleLoader *getClangModuleLoader() const;

  /// Retrieve the DWARF module loader for this ASTContext.
  ///
  /// If there is no Clang module loader, returns a null pointer.
  /// The loader is owned by the AST context.
  ClangModuleLoader *getDWARFModuleLoader() const;
public:
  namelookup::ImportCache &getImportCache() const;

  /// Returns an iterator over the modules that are known by this context
  /// to be loaded.
  ///
  /// Iteration order is guaranteed to match the order in which
  /// \c addLoadedModule was called to register the loaded module
  /// with this context.
  iterator_range<llvm::MapVector<Identifier, ModuleDecl *>::const_iterator>
  getLoadedModules() const;

  /// Returns the number of loaded modules known by this context to be loaded.
  unsigned getNumLoadedModules() const {
    auto eltRange = getLoadedModules();
    return std::distance(eltRange.begin(), eltRange.end());
  }

  /// Asks every module loader to verify the ASTs it has loaded.
  ///
  /// Does nothing in non-asserts (NDEBUG) builds.
  void verifyAllLoadedModules() const;

  /// Check whether the module with a given name can be imported without
  /// importing it.
  ///
  /// Note that even if this check succeeds, errors may still occur if the
  /// module is loaded in full.
  bool canImportModule(ImportPath::Element ModulePath);

  /// \returns a module with a given name that was already loaded.  If the
  /// module was not loaded, returns nullptr.
  ModuleDecl *getLoadedModule(
      ImportPath::Module ModulePath) const;

  ModuleDecl *getLoadedModule(Identifier ModuleName) const;

  /// Attempts to load a module into this ASTContext.
  ///
  /// If a module by this name has already been loaded, the existing module will
  /// be returned.
  ///
  /// \returns The requested module, or NULL if the module cannot be found.
  ModuleDecl *getModule(ImportPath::Module ModulePath);

  /// Attempts to load the matching overlay module for the given clang
  /// module into this ASTContext.
  ///
  /// \returns The Swift overlay module corresponding to the given Clang module,
  /// or NULL if the overlay module cannot be found.
  ModuleDecl *getOverlayModule(const FileUnit *ClangModule);

  ModuleDecl *getModuleByName(StringRef ModuleName);

  ModuleDecl *getModuleByIdentifier(Identifier ModuleID);

  /// Returns the standard library module, or null if the library isn't present.
  ///
  /// If \p loadIfAbsent is true, the ASTContext will attempt to load the module
  /// if it hasn't been set yet.
  ModuleDecl *getStdlibModule(bool loadIfAbsent = false);

  ModuleDecl *getStdlibModule() const {
    return const_cast<ASTContext *>(this)->getStdlibModule(false);
  }

  /// Insert an externally-sourced module into the set of known loaded modules
  /// in this context.
  void addLoadedModule(ModuleDecl *M);

public:
  /// Retrieve the current generation number, which reflects the
  /// number of times a module import has caused mass invalidation of
  /// lookup tables.
  ///
  /// Various places in the AST keep track of the generation numbers at which
  /// their own information is valid, such as the list of extensions associated
  /// with a nominal type.
  unsigned getCurrentGeneration() const { return CurrentGeneration; }

  /// Increase the generation number, implying that various lookup
  /// tables have been significantly altered by the introduction of a new
  /// module import.
  ///
  /// \returns the previous generation number.
  unsigned bumpGeneration() { return CurrentGeneration++; }

  /// Produce a "normal" conformance for a nominal type.
  NormalProtocolConformance *
  getConformance(Type conformingType,
                 ProtocolDecl *protocol,
                 SourceLoc loc,
                 DeclContext *dc,
                 ProtocolConformanceState state);

  /// Produce a self-conformance for the given protocol.
  SelfProtocolConformance *
  getSelfConformance(ProtocolDecl *protocol);

  /// A callback used to produce a diagnostic for an ill-formed protocol
  /// conformance that was type-checked before we're actually walking the
  /// conformance itself, along with a bit indicating whether this diagnostic
  /// produces an error.
  struct DelayedConformanceDiag {
    ValueDecl *Requirement;
    std::function<void()> Callback;
    bool IsError;
  };

  /// Check whether current context has any errors associated with
  /// ill-formed protocol conformances which haven't been produced yet.
  bool hasDelayedConformanceErrors() const;

  /// Add a delayed diagnostic produced while type-checking a
  /// particular protocol conformance.
  void addDelayedConformanceDiag(NormalProtocolConformance *conformance,
                                 DelayedConformanceDiag fn);

  /// Retrieve the delayed-conformance diagnostic callbacks for the
  /// given normal protocol conformance.
  std::vector<DelayedConformanceDiag>
  takeDelayedConformanceDiags(NormalProtocolConformance *conformance);

  /// Add delayed missing witnesses for the given normal protocol conformance.
  void addDelayedMissingWitnesses(
      NormalProtocolConformance *conformance,
      std::unique_ptr<MissingWitnessesBase> missingWitnesses);

  /// Retrieve the delayed missing witnesses for the given normal protocol
  /// conformance.
  std::unique_ptr<MissingWitnessesBase>
  takeDelayedMissingWitnesses(NormalProtocolConformance *conformance);

  /// Produce a specialized conformance, which takes a generic
  /// conformance and substitutions written in terms of the generic
  /// conformance's signature.
  ///
  /// \param type The type for which we are retrieving the conformance.
  ///
  /// \param generic The generic conformance.
  ///
  /// \param substitutions The set of substitutions required to produce the
  /// specialized conformance from the generic conformance.
  ProtocolConformance *
  getSpecializedConformance(Type type,
                            ProtocolConformance *generic,
                            SubstitutionMap substitutions);

  /// Produce an inherited conformance, for subclasses of a type
  /// that already conforms to a protocol.
  ///
  /// \param type The type for which we are retrieving the conformance.
  ///
  /// \param inherited The inherited conformance.
  InheritedProtocolConformance *
  getInheritedConformance(Type type, ProtocolConformance *inherited);

  /// Get the lazy data for the given declaration.
  ///
  /// \param lazyLoader If non-null, the lazy loader to use when creating the
  /// lazy data. The pointer must either be null or be consistent
  /// across all calls for the same \p func.
  LazyContextData *getOrCreateLazyContextData(const DeclContext *decl,
                                              LazyMemberLoader *lazyLoader);

  /// Get the lazy iterable context for the given iterable declaration context.
  ///
  /// \param lazyLoader If non-null, the lazy loader to use when creating the
  /// iterable context data. The pointer must either be null or be consistent
  /// across all calls for the same \p idc.
  LazyIterableDeclContextData *getOrCreateLazyIterableContextData(
                                              const IterableDeclContext *idc,
                                              LazyMemberLoader *lazyLoader);

  /// Access the side cache for property wrapper backing property types,
  /// used because TypeChecker::typeCheckBinding() needs somewhere to stash
  /// the backing property type.
  Type getSideCachedPropertyWrapperBackingPropertyType(VarDecl *var) const;
  void setSideCachedPropertyWrapperBackingPropertyType(VarDecl *var,
                                                        Type type);
  
  /// Returns memory usage of this ASTContext.
  size_t getTotalMemory() const;
  
  /// Returns memory used exclusively by constraint solver.
  size_t getSolverMemory() const;

  /// Retrieve the Swift name for the given Foundation entity, where
  /// "NS" prefix stripping will apply under omit-needless-words.
  StringRef getSwiftName(KnownFoundationEntity kind);

  /// Retrieve the Swift identifier for the given Foundation entity, where
  /// "NS" prefix stripping will apply under omit-needless-words.
  Identifier getSwiftId(KnownFoundationEntity kind) {
    return getIdentifier(getSwiftName(kind));
  }

  /// Populate \p names with visible top level module names.
  /// This guarantees that resulted \p names doesn't have duplicated names.
  void getVisibleTopLevelModuleNames(SmallVectorImpl<Identifier> &names) const;

  /// Whether to perform typo correction given the pre-configured correction limit.
  /// Increments \c NumTypoCorrections then checks this against the limit in
  /// the language options.
  bool shouldPerformTypoCorrection();
  
private:
  /// Register the given generic signature builder to be used as the canonical
  /// generic signature builder for the given signature, if we don't already
  /// have one.
  void registerGenericSignatureBuilder(GenericSignature sig,
                                       GenericSignatureBuilder &&builder);
  friend class GenericSignatureBuilder;

private:
  friend class IntrinsicInfo;
  /// Retrieve an LLVMContext that is used for scratch space for intrinsic lookup.
  llvm::LLVMContext &getIntrinsicScratchContext() const;

public:
  /// Retrieve or create the stored generic signature builder for the given
  /// canonical generic signature and module.
  GenericSignatureBuilder *getOrCreateGenericSignatureBuilder(
                                                     CanGenericSignature sig);

  /// Retrieve a generic signature with a single unconstrained type parameter,
  /// like `<T>`.
  CanGenericSignature getSingleGenericParameterSignature() const;

  /// Retrieve a generic signature with a single type parameter conforming
  /// to the given protocol or composition type, like <T: type>.
  CanGenericSignature getOpenedArchetypeSignature(Type type);

  GenericSignature getOverrideGenericSignature(const ValueDecl *base,
                                               const ValueDecl *derived);

  enum class OverrideGenericSignatureReqCheck {
    /// Base method's generic requirements are satisifed by derived method
    BaseReqSatisfiedByDerived,

    /// Derived method's generic requirements are satisifed by base method
    DerivedReqSatisfiedByBase
  };

  bool overrideGenericSignatureReqsSatisfied(
      const ValueDecl *base, const ValueDecl *derived,
      const OverrideGenericSignatureReqCheck direction);

  /// Whether our effective Swift version is at least 'major'.
  ///
  /// This is usually the check you want; for example, when introducing
  /// a new language feature which is only visible in Swift 5, you would
  /// check for isSwiftVersionAtLeast(5).
  bool isSwiftVersionAtLeast(unsigned major, unsigned minor = 0) const {
    return LangOpts.isSwiftVersionAtLeast(major, minor);
  }

  /// Check whether it's important to respect access control restrictions
  /// in current context.
  bool isAccessControlDisabled() const {
    return !LangOpts.EnableAccessControl;
  }

  /// Each kind and SourceFile has its own cache for a Type.
  Type &getDefaultTypeRequestCache(SourceFile *, KnownProtocolKind);

  using SILTransformCtors = ArrayRef<SILTransform *(*)(void)>;

  /// Register IRGen specific SIL passes such that the SILOptimizer can access
  /// and execute them without directly depending on IRGen.
  void registerIRGenSILTransforms(SILTransformCtors fns);

  /// Retrieve the IRGen specific SIL passes.
  SILTransformCtors getIRGenSILTransforms() const;
  
  /// Check whether a given string would be considered "pure ASCII" by the
  /// standard library's String implementation.
  bool isASCIIString(StringRef s) const;

private:
  friend Decl;
  Optional<RawComment> getRawComment(const Decl *D);
  void setRawComment(const Decl *D, RawComment RC);

  Optional<StringRef> getBriefComment(const Decl *D);
  void setBriefComment(const Decl *D, StringRef Comment);

  friend TypeBase;
  friend ArchetypeType;
  friend OpaqueTypeDecl;

  /// Provide context-level uniquing for SIL lowered type layouts and boxes.
  friend SILLayout;
  friend SILBoxType;
};

} // end namespace swift

#endif
