//===- Module.h - Describe a module -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Defines the clang::Module class, which describes a module in the
/// source code.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_MODULE_H
#define LLVM_CLANG_BASIC_MODULE_H

#include "clang/Basic/DirectoryEntry.h"
#include "clang/Basic/FileEntry.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include <array>
#include <cassert>
#include <cstdint>
#include <ctime>
#include <iterator>
#include <optional>
#include <string>
#include <utility>
#include <vector>

namespace llvm {

class raw_ostream;

} // namespace llvm

namespace clang {

class FileManager;
class LangOptions;
class TargetInfo;

/// Describes the name of a module.
using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;

/// The signature of a module, which is a hash of the AST content.
struct ASTFileSignature : std::array<uint8_t, 20> {
  using BaseT = std::array<uint8_t, 20>;

  static constexpr size_t size = std::tuple_size<BaseT>::value;

  ASTFileSignature(BaseT S = {{0}}) : BaseT(std::move(S)) {}

  explicit operator bool() const { return *this != BaseT({{0}}); }

  /// Returns the value truncated to the size of an uint64_t.
  uint64_t truncatedValue() const {
    uint64_t Value = 0;
    static_assert(sizeof(*this) >= sizeof(uint64_t), "No need to truncate.");
    for (unsigned I = 0; I < sizeof(uint64_t); ++I)
      Value |= static_cast<uint64_t>((*this)[I]) << (I * 8);
    return Value;
  }

  static ASTFileSignature create(std::array<uint8_t, 20> Bytes) {
    return ASTFileSignature(std::move(Bytes));
  }

  static ASTFileSignature createDISentinel() {
    ASTFileSignature Sentinel;
    Sentinel.fill(0xFF);
    return Sentinel;
  }

  template <typename InputIt>
  static ASTFileSignature create(InputIt First, InputIt Last) {
    assert(std::distance(First, Last) == size &&
           "Wrong amount of bytes to create an ASTFileSignature");

    ASTFileSignature Signature;
    std::copy(First, Last, Signature.begin());
    return Signature;
  }
};

/// Describes a module or submodule.
///
/// Aligned to 8 bytes to allow for llvm::PointerIntPair<Module *, 3>.
class alignas(8) Module {
public:
  /// The name of this module.
  std::string Name;

  /// The location of the module definition.
  SourceLocation DefinitionLoc;

  // FIXME: Consider if reducing the size of this enum (having Partition and
  // Named modules only) then representing interface/implementation separately
  // is more efficient.
  enum ModuleKind {
    /// This is a module that was defined by a module map and built out
    /// of header files.
    ModuleMapModule,

    /// This is a C++ 20 header unit.
    ModuleHeaderUnit,

    /// This is a C++20 module interface unit.
    ModuleInterfaceUnit,

    /// This is a C++20 module implementation unit.
    ModuleImplementationUnit,

    /// This is a C++ 20 module partition interface.
    ModulePartitionInterface,

    /// This is a C++ 20 module partition implementation.
    ModulePartitionImplementation,

    /// This is the explicit Global Module Fragment of a modular TU.
    /// As per C++ [module.global.frag].
    ExplicitGlobalModuleFragment,

    /// This is the private module fragment within some C++ module.
    PrivateModuleFragment,

    /// This is an implicit fragment of the global module which contains
    /// only language linkage declarations (made in the purview of the
    /// named module).
    ImplicitGlobalModuleFragment,
  };

  /// The kind of this module.
  ModuleKind Kind = ModuleMapModule;

  /// The parent of this module. This will be NULL for the top-level
  /// module.
  Module *Parent;

  /// The build directory of this module. This is the directory in
  /// which the module is notionally built, and relative to which its headers
  /// are found.
  const DirectoryEntry *Directory = nullptr;

  /// The presumed file name for the module map defining this module.
  /// Only non-empty when building from preprocessed source.
  std::string PresumedModuleMapFile;

  /// The umbrella header or directory.
  llvm::PointerUnion<const FileEntryRef::MapEntry *, const DirectoryEntry *>
      Umbrella;

  /// The module signature.
  ASTFileSignature Signature;

  /// The name of the umbrella entry, as written in the module map.
  std::string UmbrellaAsWritten;

  // The path to the umbrella entry relative to the root module's \c Directory.
  std::string UmbrellaRelativeToRootModuleDirectory;

  /// The module through which entities defined in this module will
  /// eventually be exposed, for use in "private" modules.
  std::string ExportAsModule;

  /// Does this Module scope describe part of the purview of a standard named
  /// C++ module?
  bool isModulePurview() const {
    switch (Kind) {
    case ModuleInterfaceUnit:
    case ModuleImplementationUnit:
    case ModulePartitionInterface:
    case ModulePartitionImplementation:
    case PrivateModuleFragment:
      return true;
    default:
      return false;
    }
  }

  /// Does this Module scope describe a fragment of the global module within
  /// some C++ module.
  bool isGlobalModule() const {
    return isExplicitGlobalModule() || isImplicitGlobalModule();
  }
  bool isExplicitGlobalModule() const {
    return Kind == ExplicitGlobalModuleFragment;
  }
  bool isImplicitGlobalModule() const {
    return Kind == ImplicitGlobalModuleFragment;
  }

  bool isPrivateModule() const { return Kind == PrivateModuleFragment; }

  bool isModuleMapModule() const { return Kind == ModuleMapModule; }

private:
  /// The submodules of this module, indexed by name.
  std::vector<Module *> SubModules;

  /// A mapping from the submodule name to the index into the
  /// \c SubModules vector at which that submodule resides.
  llvm::StringMap<unsigned> SubModuleIndex;

  /// The AST file if this is a top-level module which has a
  /// corresponding serialized AST file, or null otherwise.
  OptionalFileEntryRef ASTFile;

  /// The top-level headers associated with this module.
  llvm::SmallSetVector<const FileEntry *, 2> TopHeaders;

  /// top-level header filenames that aren't resolved to FileEntries yet.
  std::vector<std::string> TopHeaderNames;

  /// Cache of modules visible to lookup in this module.
  mutable llvm::DenseSet<const Module*> VisibleModulesCache;

  /// The ID used when referencing this module within a VisibleModuleSet.
  unsigned VisibilityID;

public:
  enum HeaderKind {
    HK_Normal,
    HK_Textual,
    HK_Private,
    HK_PrivateTextual,
    HK_Excluded
  };
  static const int NumHeaderKinds = HK_Excluded + 1;

  /// Information about a header directive as found in the module map
  /// file.
  struct Header {
    std::string NameAsWritten;
    std::string PathRelativeToRootModuleDirectory;
    OptionalFileEntryRefDegradesToFileEntryPtr Entry;

    explicit operator bool() { return Entry.has_value(); }
  };

  /// Information about a directory name as found in the module map
  /// file.
  struct DirectoryName {
    std::string NameAsWritten;
    std::string PathRelativeToRootModuleDirectory;
    const DirectoryEntry *Entry;

    explicit operator bool() { return Entry; }
  };

  /// The headers that are part of this module.
  SmallVector<Header, 2> Headers[5];

  /// Stored information about a header directive that was found in the
  /// module map file but has not been resolved to a file.
  struct UnresolvedHeaderDirective {
    HeaderKind Kind = HK_Normal;
    SourceLocation FileNameLoc;
    std::string FileName;
    bool IsUmbrella = false;
    bool HasBuiltinHeader = false;
    std::optional<off_t> Size;
    std::optional<time_t> ModTime;
  };

  /// Headers that are mentioned in the module map file but that we have not
  /// yet attempted to resolve to a file on the file system.
  SmallVector<UnresolvedHeaderDirective, 1> UnresolvedHeaders;

  /// Headers that are mentioned in the module map file but could not be
  /// found on the file system.
  SmallVector<UnresolvedHeaderDirective, 1> MissingHeaders;

  /// An individual requirement: a feature name and a flag indicating
  /// the required state of that feature.
  using Requirement = std::pair<std::string, bool>;

  /// The set of language features required to use this module.
  ///
  /// If any of these requirements are not available, the \c IsAvailable bit
  /// will be false to indicate that this (sub)module is not available.
  SmallVector<Requirement, 2> Requirements;

  /// A module with the same name that shadows this module.
  Module *ShadowingModule = nullptr;

  /// Whether this module has declared itself unimportable, either because
  /// it's missing a requirement from \p Requirements or because it's been
  /// shadowed by another module.
  unsigned IsUnimportable : 1;

  /// Whether we tried and failed to load a module file for this module.
  unsigned HasIncompatibleModuleFile : 1;

  /// Whether this module is available in the current translation unit.
  ///
  /// If the module is missing headers or does not meet all requirements then
  /// this bit will be 0.
  unsigned IsAvailable : 1;

  /// Whether this module was loaded from a module file.
  unsigned IsFromModuleFile : 1;

  /// Whether this is a framework module.
  unsigned IsFramework : 1;

  /// Whether this is an explicit submodule.
  unsigned IsExplicit : 1;

  /// Whether this is a "system" module (which assumes that all
  /// headers in it are system headers).
  unsigned IsSystem : 1;

  /// Whether this is an 'extern "C"' module (which implicitly puts all
  /// headers in it within an 'extern "C"' block, and allows the module to be
  /// imported within such a block).
  unsigned IsExternC : 1;

  /// Whether this is an inferred submodule (module * { ... }).
  unsigned IsInferred : 1;

  /// Whether we should infer submodules for this module based on
  /// the headers.
  ///
  /// Submodules can only be inferred for modules with an umbrella header.
  unsigned InferSubmodules : 1;

  /// Whether, when inferring submodules, the inferred submodules
  /// should be explicit.
  unsigned InferExplicitSubmodules : 1;

  /// Whether, when inferring submodules, the inferr submodules should
  /// export all modules they import (e.g., the equivalent of "export *").
  unsigned InferExportWildcard : 1;

  /// Whether the set of configuration macros is exhaustive.
  ///
  /// When the set of configuration macros is exhaustive, meaning
  /// that no identifier not in this list should affect how the module is
  /// built.
  unsigned ConfigMacrosExhaustive : 1;

  /// Whether files in this module can only include non-modular headers
  /// and headers from used modules.
  unsigned NoUndeclaredIncludes : 1;

  /// Whether this module came from a "private" module map, found next
  /// to a regular (public) module map.
  unsigned ModuleMapIsPrivate : 1;

  /// Describes the visibility of the various names within a
  /// particular module.
  enum NameVisibilityKind {
    /// All of the names in this module are hidden.
    Hidden,
    /// All of the names in this module are visible.
    AllVisible
  };

  /// The visibility of names within this particular module.
  NameVisibilityKind NameVisibility;

  /// The location of the inferred submodule.
  SourceLocation InferredSubmoduleLoc;

  /// The set of modules imported by this module, and on which this
  /// module depends.
  llvm::SmallSetVector<Module *, 2> Imports;

  /// The set of top-level modules that affected the compilation of this module,
  /// but were not imported.
  llvm::SmallSetVector<Module *, 2> AffectingClangModules;

  /// Describes an exported module.
  ///
  /// The pointer is the module being re-exported, while the bit will be true
  /// to indicate that this is a wildcard export.
  using ExportDecl = llvm::PointerIntPair<Module *, 1, bool>;

  /// The set of export declarations.
  SmallVector<ExportDecl, 2> Exports;

  /// Describes an exported module that has not yet been resolved
  /// (perhaps because the module it refers to has not yet been loaded).
  struct UnresolvedExportDecl {
    /// The location of the 'export' keyword in the module map file.
    SourceLocation ExportLoc;

    /// The name of the module.
    ModuleId Id;

    /// Whether this export declaration ends in a wildcard, indicating
    /// that all of its submodules should be exported (rather than the named
    /// module itself).
    bool Wildcard;
  };

  /// The set of export declarations that have yet to be resolved.
  SmallVector<UnresolvedExportDecl, 2> UnresolvedExports;

  /// The directly used modules.
  SmallVector<Module *, 2> DirectUses;

  /// The set of use declarations that have yet to be resolved.
  SmallVector<ModuleId, 2> UnresolvedDirectUses;

  /// When \c NoUndeclaredIncludes is true, the set of modules this module tried
  /// to import but didn't because they are not direct uses.
  llvm::SmallSetVector<const Module *, 2> UndeclaredUses;

  /// A library or framework to link against when an entity from this
  /// module is used.
  struct LinkLibrary {
    LinkLibrary() = default;
    LinkLibrary(const std::string &Library, bool IsFramework)
        : Library(Library), IsFramework(IsFramework) {}

    /// The library to link against.
    ///
    /// This will typically be a library or framework name, but can also
    /// be an absolute path to the library or framework.
    std::string Library;

    /// Whether this is a framework rather than a library.
    bool IsFramework = false;
  };

  /// The set of libraries or frameworks to link against when
  /// an entity from this module is used.
  llvm::SmallVector<LinkLibrary, 2> LinkLibraries;

  /// Autolinking uses the framework name for linking purposes
  /// when this is false and the export_as name otherwise.
  bool UseExportAsModuleLinkName = false;

  /// The set of "configuration macros", which are macros that
  /// (intentionally) change how this module is built.
  std::vector<std::string> ConfigMacros;

  /// An unresolved conflict with another module.
  struct UnresolvedConflict {
    /// The (unresolved) module id.
    ModuleId Id;

    /// The message provided to the user when there is a conflict.
    std::string Message;
  };

  /// The list of conflicts for which the module-id has not yet been
  /// resolved.
  std::vector<UnresolvedConflict> UnresolvedConflicts;

  /// A conflict between two modules.
  struct Conflict {
    /// The module that this module conflicts with.
    Module *Other;

    /// The message provided to the user when there is a conflict.
    std::string Message;
  };

  /// The list of conflicts.
  std::vector<Conflict> Conflicts;

  /// Construct a new module or submodule.
  Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
         bool IsFramework, bool IsExplicit, unsigned VisibilityID);

  ~Module();

  /// Determine whether this module has been declared unimportable.
  bool isUnimportable() const { return IsUnimportable; }

  /// Determine whether this module has been declared unimportable.
  ///
  /// \param LangOpts The language options used for the current
  /// translation unit.
  ///
  /// \param Target The target options used for the current translation unit.
  ///
  /// \param Req If this module is unimportable because of a missing
  /// requirement, this parameter will be set to one of the requirements that
  /// is not met for use of this module.
  ///
  /// \param ShadowingModule If this module is unimportable because it is
  /// shadowed, this parameter will be set to the shadowing module.
  bool isUnimportable(const LangOptions &LangOpts, const TargetInfo &Target,
                      Requirement &Req, Module *&ShadowingModule) const;

  /// Determine whether this module can be built in this compilation.
  bool isForBuilding(const LangOptions &LangOpts) const;

  /// Determine whether this module is available for use within the
  /// current translation unit.
  bool isAvailable() const { return IsAvailable; }

  /// Determine whether this module is available for use within the
  /// current translation unit.
  ///
  /// \param LangOpts The language options used for the current
  /// translation unit.
  ///
  /// \param Target The target options used for the current translation unit.
  ///
  /// \param Req If this module is unavailable because of a missing requirement,
  /// this parameter will be set to one of the requirements that is not met for
  /// use of this module.
  ///
  /// \param MissingHeader If this module is unavailable because of a missing
  /// header, this parameter will be set to one of the missing headers.
  ///
  /// \param ShadowingModule If this module is unavailable because it is
  /// shadowed, this parameter will be set to the shadowing module.
  bool isAvailable(const LangOptions &LangOpts,
                   const TargetInfo &Target,
                   Requirement &Req,
                   UnresolvedHeaderDirective &MissingHeader,
                   Module *&ShadowingModule) const;

  /// Determine whether this module is a submodule.
  bool isSubModule() const { return Parent != nullptr; }

  /// Check if this module is a (possibly transitive) submodule of \p Other.
  ///
  /// The 'A is a submodule of B' relation is a partial order based on the
  /// the parent-child relationship between individual modules.
  ///
  /// Returns \c false if \p Other is \c nullptr.
  bool isSubModuleOf(const Module *Other) const;

  /// Determine whether this module is a part of a framework,
  /// either because it is a framework module or because it is a submodule
  /// of a framework module.
  bool isPartOfFramework() const {
    for (const Module *Mod = this; Mod; Mod = Mod->Parent)
      if (Mod->IsFramework)
        return true;

    return false;
  }

  /// Determine whether this module is a subframework of another
  /// framework.
  bool isSubFramework() const {
    return IsFramework && Parent && Parent->isPartOfFramework();
  }

  /// Set the parent of this module. This should only be used if the parent
  /// could not be set during module creation.
  void setParent(Module *M) {
    assert(!Parent);
    Parent = M;
    Parent->SubModuleIndex[Name] = Parent->SubModules.size();
    Parent->SubModules.push_back(this);
  }

  /// Is this module have similar semantics as headers.
  bool isHeaderLikeModule() const {
    return isModuleMapModule() || isHeaderUnit();
  }

  /// Is this a module partition.
  bool isModulePartition() const {
    return Kind == ModulePartitionInterface ||
           Kind == ModulePartitionImplementation;
  }

  /// Is this a module implementation.
  bool isModuleImplementation() const {
    return Kind == ModuleImplementationUnit;
  }

  /// Is this module a header unit.
  bool isHeaderUnit() const { return Kind == ModuleHeaderUnit; }
  // Is this a C++20 module interface or a partition.
  bool isInterfaceOrPartition() const {
    return Kind == ModuleInterfaceUnit || isModulePartition();
  }

  bool isModuleInterfaceUnit() const {
    return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface;
  }

  /// Get the primary module interface name from a partition.
  StringRef getPrimaryModuleInterfaceName() const {
    // Technically, global module fragment belongs to global module. And global
    // module has no name: [module.unit]p6:
    //   The global module has no name, no module interface unit, and is not
    //   introduced by any module-declaration.
    //
    // <global> is the default name showed in module map.
    if (isGlobalModule())
      return "<global>";

    if (isModulePartition()) {
      auto pos = Name.find(':');
      return StringRef(Name.data(), pos);
    }

    if (isPrivateModule())
      return getTopLevelModuleName();

    return Name;
  }

  /// Retrieve the full name of this module, including the path from
  /// its top-level module.
  /// \param AllowStringLiterals If \c true, components that might not be
  ///        lexically valid as identifiers will be emitted as string literals.
  std::string getFullModuleName(bool AllowStringLiterals = false) const;

  /// Whether the full name of this module is equal to joining
  /// \p nameParts with "."s.
  ///
  /// This is more efficient than getFullModuleName().
  bool fullModuleNameIs(ArrayRef<StringRef> nameParts) const;

  /// Retrieve the top-level module for this (sub)module, which may
  /// be this module.
  Module *getTopLevelModule() {
    return const_cast<Module *>(
             const_cast<const Module *>(this)->getTopLevelModule());
  }

  /// Retrieve the top-level module for this (sub)module, which may
  /// be this module.
  const Module *getTopLevelModule() const;

  /// Retrieve the name of the top-level module.
  StringRef getTopLevelModuleName() const {
    return getTopLevelModule()->Name;
  }

  /// The serialized AST file for this module, if one was created.
  OptionalFileEntryRefDegradesToFileEntryPtr getASTFile() const {
    return getTopLevelModule()->ASTFile;
  }

  /// Set the serialized AST file for the top-level module of this module.
  void setASTFile(OptionalFileEntryRef File) {
    assert((!getASTFile() || getASTFile() == File) && "file path changed");
    getTopLevelModule()->ASTFile = File;
  }

  /// Retrieve the directory for which this module serves as the
  /// umbrella.
  DirectoryName getUmbrellaDir() const;

  /// Retrieve the header that serves as the umbrella header for this
  /// module.
  Header getUmbrellaHeader() const {
    if (auto *ME = Umbrella.dyn_cast<const FileEntryRef::MapEntry *>())
      return Header{UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory,
                    FileEntryRef(*ME)};
    return Header{};
  }

  /// Determine whether this module has an umbrella directory that is
  /// not based on an umbrella header.
  bool hasUmbrellaDir() const {
    return Umbrella && Umbrella.is<const DirectoryEntry *>();
  }

  /// Add a top-level header associated with this module.
  void addTopHeader(const FileEntry *File);

  /// Add a top-level header filename associated with this module.
  void addTopHeaderFilename(StringRef Filename) {
    TopHeaderNames.push_back(std::string(Filename));
  }

  /// The top-level headers associated with this module.
  ArrayRef<const FileEntry *> getTopHeaders(FileManager &FileMgr);

  /// Determine whether this module has declared its intention to
  /// directly use another module.
  bool directlyUses(const Module *Requested);

  /// Add the given feature requirement to the list of features
  /// required by this module.
  ///
  /// \param Feature The feature that is required by this module (and
  /// its submodules).
  ///
  /// \param RequiredState The required state of this feature: \c true
  /// if it must be present, \c false if it must be absent.
  ///
  /// \param LangOpts The set of language options that will be used to
  /// evaluate the availability of this feature.
  ///
  /// \param Target The target options that will be used to evaluate the
  /// availability of this feature.
  void addRequirement(StringRef Feature, bool RequiredState,
                      const LangOptions &LangOpts,
                      const TargetInfo &Target);

  /// Mark this module and all of its submodules as unavailable.
  void markUnavailable(bool Unimportable);

  /// Find the submodule with the given name.
  ///
  /// \returns The submodule if found, or NULL otherwise.
  Module *findSubmodule(StringRef Name) const;
  Module *findOrInferSubmodule(StringRef Name);

  /// Get the Global Module Fragment (sub-module) for this module, it there is
  /// one.
  ///
  /// \returns The GMF sub-module if found, or NULL otherwise.
  Module *getGlobalModuleFragment() { return findSubmodule("<global>"); }

  /// Get the Private Module Fragment (sub-module) for this module, it there is
  /// one.
  ///
  /// \returns The PMF sub-module if found, or NULL otherwise.
  Module *getPrivateModuleFragment() { return findSubmodule("<private>"); }

  /// Determine whether the specified module would be visible to
  /// a lookup at the end of this module.
  ///
  /// FIXME: This may return incorrect results for (submodules of) the
  /// module currently being built, if it's queried before we see all
  /// of its imports.
  bool isModuleVisible(const Module *M) const {
    if (VisibleModulesCache.empty())
      buildVisibleModulesCache();
    return VisibleModulesCache.count(M);
  }

  unsigned getVisibilityID() const { return VisibilityID; }

  using submodule_iterator = std::vector<Module *>::iterator;
  using submodule_const_iterator = std::vector<Module *>::const_iterator;

  llvm::iterator_range<submodule_iterator> submodules() {
    return llvm::make_range(SubModules.begin(), SubModules.end());
  }
  llvm::iterator_range<submodule_const_iterator> submodules() const {
    return llvm::make_range(SubModules.begin(), SubModules.end());
  }

  /// Appends this module's list of exported modules to \p Exported.
  ///
  /// This provides a subset of immediately imported modules (the ones that are
  /// directly exported), not the complete set of exported modules.
  void getExportedModules(SmallVectorImpl<Module *> &Exported) const;

  static StringRef getModuleInputBufferName() {
    return "<module-includes>";
  }

  /// Print the module map for this module to the given stream.
  void print(raw_ostream &OS, unsigned Indent = 0, bool Dump = false) const;

  /// Dump the contents of this module to the given output stream.
  void dump() const;

private:
  void buildVisibleModulesCache() const;
};

/// A set of visible modules.
class VisibleModuleSet {
public:
  VisibleModuleSet() = default;
  VisibleModuleSet(VisibleModuleSet &&O)
      : ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) {
    O.ImportLocs.clear();
    ++O.Generation;
  }

  /// Move from another visible modules set. Guaranteed to leave the source
  /// empty and bump the generation on both.
  VisibleModuleSet &operator=(VisibleModuleSet &&O) {
    ImportLocs = std::move(O.ImportLocs);
    O.ImportLocs.clear();
    ++O.Generation;
    ++Generation;
    return *this;
  }

  /// Get the current visibility generation. Incremented each time the
  /// set of visible modules changes in any way.
  unsigned getGeneration() const { return Generation; }

  /// Determine whether a module is visible.
  bool isVisible(const Module *M) const {
    return getImportLoc(M).isValid();
  }

  /// Get the location at which the import of a module was triggered.
  SourceLocation getImportLoc(const Module *M) const {
    return M->getVisibilityID() < ImportLocs.size()
               ? ImportLocs[M->getVisibilityID()]
               : SourceLocation();
  }

  /// A callback to call when a module is made visible (directly or
  /// indirectly) by a call to \ref setVisible.
  using VisibleCallback = llvm::function_ref<void(Module *M)>;

  /// A callback to call when a module conflict is found. \p Path
  /// consists of a sequence of modules from the conflicting module to the one
  /// made visible, where each was exported by the next.
  using ConflictCallback =
      llvm::function_ref<void(ArrayRef<Module *> Path, Module *Conflict,
                         StringRef Message)>;

  /// Make a specific module visible.
  void setVisible(Module *M, SourceLocation Loc,
                  VisibleCallback Vis = [](Module *) {},
                  ConflictCallback Cb = [](ArrayRef<Module *>, Module *,
                                           StringRef) {});

private:
  /// Import locations for each visible module. Indexed by the module's
  /// VisibilityID.
  std::vector<SourceLocation> ImportLocs;

  /// Visibility generation, bumped every time the visibility state changes.
  unsigned Generation = 0;
};

/// Abstracts clang modules and precompiled header files and holds
/// everything needed to generate debug info for an imported module
/// or PCH.
class ASTSourceDescriptor {
  StringRef PCHModuleName;
  StringRef Path;
  StringRef ASTFile;
  ASTFileSignature Signature;
  Module *ClangModule = nullptr;

public:
  ASTSourceDescriptor() = default;
  ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
                      ASTFileSignature Signature)
      : PCHModuleName(std::move(Name)), Path(std::move(Path)),
        ASTFile(std::move(ASTFile)), Signature(Signature) {}
  ASTSourceDescriptor(Module &M);

  std::string getModuleName() const;
  StringRef getPath() const { return Path; }
  StringRef getASTFile() const { return ASTFile; }
  ASTFileSignature getSignature() const { return Signature; }
  Module *getModuleOrNull() const { return ClangModule; }
};


} // namespace clang

#endif // LLVM_CLANG_BASIC_MODULE_H
