//===--- FrontendAction.cpp -----------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/FrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileEntry.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LangStandard.h"
#include "clang/Basic/Sarif.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Stack.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/LayoutOverrideSource.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Frontend/SARIFDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/HLSLExternalSemaSource.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <system_error>
using namespace clang;

LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)

namespace {

/// DeserializedDeclsLineRangePrinter dumps ranges of deserialized declarations
/// to aid debugging and bug minimization. It implements ASTConsumer and
/// ASTDeserializationListener, so that an object of
/// DeserializedDeclsLineRangePrinter registers as its own listener. The
/// ASTDeserializationListener interface provides the DeclRead callback that we
/// use to collect the deserialized Decls. Note that printing or otherwise
/// processing them as this point is dangerous, since that could trigger
/// additional deserialization and crash compilation. Therefore, we process the
/// collected Decls in HandleTranslationUnit method of ASTConsumer. This is a
/// safe point, since we know that by this point all the Decls needed by the
/// compiler frontend have been deserialized. In case our processing causes
/// further deserialization, DeclRead from the listener might be called again.
/// However, at that point we don't accept any more Decls for processing.
class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
                                            ASTDeserializationListener {
public:
  explicit DeserializedDeclsSourceRangePrinter(
      SourceManager &SM, std::unique_ptr<llvm::raw_fd_ostream> OS)
      : ASTDeserializationListener(), SM(SM), OS(std::move(OS)) {}

  ASTDeserializationListener *GetASTDeserializationListener() override {
    return this;
  }

  void DeclRead(GlobalDeclID ID, const Decl *D) override {
    if (!IsCollectingDecls)
      return;
    if (!D || isa<TranslationUnitDecl>(D) || isa<LinkageSpecDecl>(D) ||
        isa<NamespaceDecl>(D) || isa<ExportDecl>(D)) {
      // These decls cover a lot of nested declarations that might not be used,
      // reducing the granularity and making the output less useful.
      return;
    }
    if (isa<ParmVarDecl>(D)) {
      // Parameters are covered by their functions.
      return;
    }
    auto *DC = D->getLexicalDeclContext();
    if (!DC || !shouldIncludeDeclsIn(DC))
      return;

    PendingDecls.push_back(D);
    for (; (isa<ExportDecl>(DC) || isa<NamespaceDecl>(DC)) &&
           ProcessedDeclContexts.insert(DC).second;
         DC = DC->getLexicalParent()) {
      // Add any interesting decl contexts that we have not seen before.
      // Note that we filter them out from DeclRead as that would include all
      // redeclarations of namespaces, potentially those that do not have any
      // imported declarations.
      PendingDecls.push_back(cast<Decl>(DC));
    }
  }

  struct Position {
    unsigned Line;
    unsigned Column;

    bool operator<(const Position &other) const {
      return std::tie(Line, Column) < std::tie(other.Line, other.Column);
    }

    static Position GetBeginSpelling(const SourceManager &SM,
                                     const CharSourceRange &R) {
      SourceLocation Begin = R.getBegin();
      return {SM.getSpellingLineNumber(Begin),
              SM.getSpellingColumnNumber(Begin)};
    }

    static Position GetEndSpelling(const SourceManager &SM,
                                   const CharSourceRange &Range,
                                   const LangOptions &LangOpts) {
      // For token ranges, compute end location for end character of the range.
      CharSourceRange R = Lexer::getAsCharRange(Range, SM, LangOpts);
      SourceLocation End = R.getEnd();
      // Relex the token past the end location of the last token in the source
      // range. If it's a semicolon, advance the location by one token.
      Token PossiblySemi;
      Lexer::getRawToken(End, PossiblySemi, SM, LangOpts, true);
      if (PossiblySemi.is(tok::semi))
        End = End.getLocWithOffset(1);
      // Column number of the returned end position is exclusive.
      return {SM.getSpellingLineNumber(End), SM.getSpellingColumnNumber(End)};
    }
  };

  struct RequiredRanges {
    StringRef Filename;
    std::vector<std::pair<Position, Position>> FromTo;
  };
  void HandleTranslationUnit(ASTContext &Context) override {
    assert(IsCollectingDecls && "HandleTranslationUnit called twice?");
    IsCollectingDecls = false;

    // Merge ranges in each of the files.
    struct FileData {
      std::vector<std::pair<Position, Position>> FromTo;
      OptionalFileEntryRef Ref;
    };
    llvm::DenseMap<const FileEntry *, FileData> FileToRanges;

    for (const Decl *D : PendingDecls) {
      for (CharSourceRange R : getRangesToMark(D)) {
        if (!R.isValid())
          continue;

        auto *F = SM.getFileEntryForID(SM.getFileID(R.getBegin()));
        if (F != SM.getFileEntryForID(SM.getFileID(R.getEnd()))) {
          // Such cases are rare and difficult to handle.
          continue;
        }

        auto &Data = FileToRanges[F];
        if (!Data.Ref)
          Data.Ref = SM.getFileEntryRefForID(SM.getFileID(R.getBegin()));
        Data.FromTo.push_back(
            {Position::GetBeginSpelling(SM, R),
             Position::GetEndSpelling(SM, R, D->getLangOpts())});
      }
    }

    // To simplify output, merge consecutive and intersecting ranges.
    std::vector<RequiredRanges> Result;
    for (auto &[F, Data] : FileToRanges) {
      auto &FromTo = Data.FromTo;
      assert(!FromTo.empty());

      if (!Data.Ref)
        continue;

      llvm::sort(FromTo);

      std::vector<std::pair<Position, Position>> MergedRanges;
      MergedRanges.push_back(FromTo.front());
      for (auto It = FromTo.begin() + 1; It < FromTo.end(); ++It) {
        if (MergedRanges.back().second < It->first) {
          MergedRanges.push_back(*It);
          continue;
        }
        if (MergedRanges.back().second < It->second)
          MergedRanges.back().second = It->second;
      }
      Result.push_back({Data.Ref->getName(), std::move(MergedRanges)});
    }
    printJson(Result);
  }

private:
  std::vector<const Decl *> PendingDecls;
  llvm::SmallPtrSet<const DeclContext *, 0> ProcessedDeclContexts;
  bool IsCollectingDecls = true;
  const SourceManager &SM;
  std::unique_ptr<llvm::raw_ostream> OS;

  static bool shouldIncludeDeclsIn(const DeclContext *DC) {
    assert(DC && "DC is null");
    // We choose to work at namespace level to reduce complexity and the number
    // of cases we care about.
    // We still need to carefully handle composite declarations like
    // `ExportDecl`.
    for (; DC; DC = DC->getLexicalParent()) {
      if (DC->isFileContext())
        return true;
      if (isa<ExportDecl>(DC))
        continue; // Depends on the parent.
      return false;
    }
    llvm_unreachable("DeclContext chain must end with a translation unit");
  }

  llvm::SmallVector<CharSourceRange, 2> getRangesToMark(const Decl *D) {
    if (auto *ED = dyn_cast<ExportDecl>(D)) {
      if (!ED->hasBraces())
        return {SM.getExpansionRange(ED->getExportLoc())};

      return {SM.getExpansionRange(SourceRange(
                  ED->getExportLoc(),
                  lexForLBrace(ED->getExportLoc(), D->getLangOpts()))),
              SM.getExpansionRange(ED->getRBraceLoc())};
    }

    auto *NS = dyn_cast<NamespaceDecl>(D);
    if (!NS)
      return {SM.getExpansionRange(D->getSourceRange())};

    SourceLocation LBraceLoc;
    if (NS->isAnonymousNamespace()) {
      LBraceLoc = NS->getLocation();
    } else {
      // Start with the location of the identifier.
      SourceLocation TokenBeforeLBrace = NS->getLocation();
      if (NS->hasAttrs()) {
        for (auto *A : NS->getAttrs()) {
          // But attributes may go after it.
          if (SM.isBeforeInTranslationUnit(TokenBeforeLBrace,
                                           A->getRange().getEnd())) {
            // Give up, the attributes are often coming from macros and we
            // cannot skip them reliably.
            return {};
          }
        }
      }
      LBraceLoc = lexForLBrace(TokenBeforeLBrace, D->getLangOpts());
    }
    return {SM.getExpansionRange(SourceRange(NS->getBeginLoc(), LBraceLoc)),
            SM.getExpansionRange(NS->getRBraceLoc())};
  }

  void printJson(llvm::ArrayRef<RequiredRanges> Result) {
    *OS << "{\n";
    *OS << R"(  "required_ranges": [)" << "\n";
    for (size_t I = 0; I < Result.size(); ++I) {
      auto &F = Result[I].Filename;
      auto &MergedRanges = Result[I].FromTo;
      *OS << R"(    {)" << "\n";
      *OS << R"(      "file": ")" << F << "\"," << "\n";
      *OS << R"(      "range": [)" << "\n";
      for (size_t J = 0; J < MergedRanges.size(); ++J) {
        auto &From = MergedRanges[J].first;
        auto &To = MergedRanges[J].second;
        *OS << R"(        {)" << "\n";
        *OS << R"(          "from": {)" << "\n";
        *OS << R"(            "line": )" << From.Line << ",\n";
        *OS << R"(            "column": )" << From.Column << "\n"
            << R"(          },)" << "\n";
        *OS << R"(          "to": {)" << "\n";
        *OS << R"(            "line": )" << To.Line << ",\n";
        *OS << R"(            "column": )" << To.Column << "\n"
            << R"(          })" << "\n";
        *OS << R"(        })";
        if (J < MergedRanges.size() - 1) {
          *OS << ",";
        }
        *OS << "\n";
      }
      *OS << "      ]" << "\n" << "    }";
      if (I < Result.size() - 1)
        *OS << ",";
      *OS << "\n";
    }
    *OS << "  ]\n";
    *OS << "}\n";

    OS->flush();
  }

  SourceLocation lexForLBrace(SourceLocation TokenBeforeLBrace,
                              const LangOptions &LangOpts) {
    // Now skip one token, the next should be the lbrace.
    Token Tok;
    if (Lexer::getRawToken(TokenBeforeLBrace, Tok, SM, LangOpts, true) ||
        Lexer::getRawToken(Tok.getEndLoc(), Tok, SM, LangOpts, true) ||
        Tok.getKind() != tok::l_brace) {
      // On error or if we did not find the token we expected, avoid marking
      // everything inside the namespace as used.
      return SourceLocation();
    }
    return Tok.getLocation();
  }
};

/// Dumps deserialized declarations.
class DeserializedDeclsDumper : public DelegatingDeserializationListener {
public:
  explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous,
                                   bool DeletePrevious)
      : DelegatingDeserializationListener(Previous, DeletePrevious) {}

  void DeclRead(GlobalDeclID ID, const Decl *D) override {
    llvm::outs() << "PCH DECL: " << D->getDeclKindName();
    if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
      llvm::outs() << " - ";
      ND->printQualifiedName(llvm::outs());
    }
    llvm::outs() << "\n";

    DelegatingDeserializationListener::DeclRead(ID, D);
  }
};

/// Checks deserialized declarations and emits error if a name
/// matches one given in command-line using -error-on-deserialized-decl.
class DeserializedDeclsChecker : public DelegatingDeserializationListener {
  ASTContext &Ctx;
  std::set<std::string> NamesToCheck;

public:
  DeserializedDeclsChecker(ASTContext &Ctx,
                           const std::set<std::string> &NamesToCheck,
                           ASTDeserializationListener *Previous,
                           bool DeletePrevious)
      : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx),
        NamesToCheck(NamesToCheck) {}

  void DeclRead(GlobalDeclID ID, const Decl *D) override {
    if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
      if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {
        unsigned DiagID
          = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,
                                                 "%0 was deserialized");
        Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)
            << ND;
      }

    DelegatingDeserializationListener::DeclRead(ID, D);
  }
};

} // end anonymous namespace

FrontendAction::FrontendAction() : Instance(nullptr) {}

FrontendAction::~FrontendAction() {}

void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,
                                     std::unique_ptr<ASTUnit> AST) {
  this->CurrentInput = CurrentInput;
  CurrentASTUnit = std::move(AST);
}

Module *FrontendAction::getCurrentModule() const {
  CompilerInstance &CI = getCompilerInstance();
  return CI.getPreprocessor().getHeaderSearchInfo().lookupModule(
      CI.getLangOpts().CurrentModule, SourceLocation(), /*AllowSearch*/false);
}

std::unique_ptr<ASTConsumer>
FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
                                         StringRef InFile) {
  std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile);
  if (!Consumer)
    return nullptr;

  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
  llvm::StringRef DumpDeserializedDeclarationRangesPath =
      CI.getFrontendOpts().DumpMinimizationHintsPath;
  if (!DumpDeserializedDeclarationRangesPath.empty()) {
    std::error_code ErrorCode;
    auto FileStream = std::make_unique<llvm::raw_fd_ostream>(
        DumpDeserializedDeclarationRangesPath, ErrorCode,
        llvm::sys::fs::OF_TextWithCRLF);
    if (!ErrorCode) {
      Consumers.push_back(std::make_unique<DeserializedDeclsSourceRangePrinter>(
          CI.getSourceManager(), std::move(FileStream)));
    } else {
      llvm::errs() << "Failed to create output file for "
                      "-dump-minimization-hints flag, file path: "
                   << DumpDeserializedDeclarationRangesPath
                   << ", error: " << ErrorCode.message() << "\n";
    }
  }

  // Validate -add-plugin args.
  bool FoundAllPlugins = true;
  for (const std::string &Arg : CI.getFrontendOpts().AddPluginActions) {
    bool Found = false;
    for (const FrontendPluginRegistry::entry &Plugin :
         FrontendPluginRegistry::entries()) {
      if (Plugin.getName() == Arg)
        Found = true;
    }
    if (!Found) {
      CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << Arg;
      FoundAllPlugins = false;
    }
  }
  if (!FoundAllPlugins)
    return nullptr;

  // If this is a code completion run, avoid invoking the plugin consumers
  if (CI.hasCodeCompletionConsumer())
    return Consumer;

  // Collect the list of plugins that go before the main action (in Consumers)
  // or after it (in AfterConsumers)
  std::vector<std::unique_ptr<ASTConsumer>> AfterConsumers;
  for (const FrontendPluginRegistry::entry &Plugin :
       FrontendPluginRegistry::entries()) {
    std::unique_ptr<PluginASTAction> P = Plugin.instantiate();
    PluginASTAction::ActionType ActionType = P->getActionType();
    if (ActionType == PluginASTAction::CmdlineAfterMainAction ||
        ActionType == PluginASTAction::CmdlineBeforeMainAction) {
      // This is O(|plugins| * |add_plugins|), but since both numbers are
      // way below 50 in practice, that's ok.
      if (llvm::is_contained(CI.getFrontendOpts().AddPluginActions,
                             Plugin.getName())) {
        if (ActionType == PluginASTAction::CmdlineBeforeMainAction)
          ActionType = PluginASTAction::AddBeforeMainAction;
        else
          ActionType = PluginASTAction::AddAfterMainAction;
      }
    }
    if ((ActionType == PluginASTAction::AddBeforeMainAction ||
         ActionType == PluginASTAction::AddAfterMainAction) &&
        P->ParseArgs(
            CI,
            CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) {
      std::unique_ptr<ASTConsumer> PluginConsumer = P->CreateASTConsumer(CI, InFile);
      if (ActionType == PluginASTAction::AddBeforeMainAction) {
        Consumers.push_back(std::move(PluginConsumer));
      } else {
        AfterConsumers.push_back(std::move(PluginConsumer));
      }
    }
  }

  // Add to Consumers the main consumer, then all the plugins that go after it
  Consumers.push_back(std::move(Consumer));
  if (!AfterConsumers.empty()) {
    // If we have plugins after the main consumer, which may be the codegen
    // action, they likely will need the ASTContext, so don't clear it in the
    // codegen action.
    CI.getCodeGenOpts().ClearASTBeforeBackend = false;
    for (auto &C : AfterConsumers)
      Consumers.push_back(std::move(C));
  }

  assert(Consumers.size() >= 1 && "should have added the main consumer");
  if (Consumers.size() == 1)
    return std::move(Consumers.front());
  return std::make_unique<MultiplexConsumer>(std::move(Consumers));
}

/// For preprocessed files, if the first line is the linemarker and specifies
/// the original source file name, use that name as the input file name.
/// Returns the location of the first token after the line marker directive.
///
/// \param CI The compiler instance.
/// \param InputFile Populated with the filename from the line marker.
/// \param IsModuleMap If \c true, add a line note corresponding to this line
///        directive. (We need to do this because the directive will not be
///        visited by the preprocessor.)
static SourceLocation ReadOriginalFileName(CompilerInstance &CI,
                                           std::string &InputFile,
                                           bool IsModuleMap = false) {
  auto &SourceMgr = CI.getSourceManager();
  auto MainFileID = SourceMgr.getMainFileID();

  auto MainFileBuf = SourceMgr.getBufferOrNone(MainFileID);
  if (!MainFileBuf)
    return SourceLocation();

  std::unique_ptr<Lexer> RawLexer(
      new Lexer(MainFileID, *MainFileBuf, SourceMgr, CI.getLangOpts()));

  // If the first line has the syntax of
  //
  // # NUM "FILENAME"
  //
  // we use FILENAME as the input file name.
  Token T;
  if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash)
    return SourceLocation();
  if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() ||
      T.getKind() != tok::numeric_constant)
    return SourceLocation();

  unsigned LineNo;
  SourceLocation LineNoLoc = T.getLocation();
  if (IsModuleMap) {
    llvm::SmallString<16> Buffer;
    if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts())
            .getAsInteger(10, LineNo))
      return SourceLocation();
  }

  RawLexer->LexFromRawLexer(T);
  if (T.isAtStartOfLine() || T.getKind() != tok::string_literal)
    return SourceLocation();

  StringLiteralParser Literal(T, CI.getPreprocessor());
  if (Literal.hadError)
    return SourceLocation();
  RawLexer->LexFromRawLexer(T);
  if (T.isNot(tok::eof) && !T.isAtStartOfLine())
    return SourceLocation();
  InputFile = Literal.GetString().str();

  if (IsModuleMap)
    CI.getSourceManager().AddLineNote(
        LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false,
        false, SrcMgr::C_User_ModuleMap);

  return T.getLocation();
}

static SmallVectorImpl<char> &
operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
  Includes.append(RHS.begin(), RHS.end());
  return Includes;
}

static void addHeaderInclude(StringRef HeaderName,
                             SmallVectorImpl<char> &Includes,
                             const LangOptions &LangOpts,
                             bool IsExternC) {
  if (IsExternC && LangOpts.CPlusPlus)
    Includes += "extern \"C\" {\n";
  if (LangOpts.ObjC)
    Includes += "#import \"";
  else
    Includes += "#include \"";

  Includes += HeaderName;

  Includes += "\"\n";
  if (IsExternC && LangOpts.CPlusPlus)
    Includes += "}\n";
}

/// Collect the set of header includes needed to construct the given
/// module and update the TopHeaders file set of the module.
///
/// \param Module The module we're collecting includes from.
///
/// \param Includes Will be augmented with the set of \#includes or \#imports
/// needed to load all of the named headers.
static std::error_code collectModuleHeaderIncludes(
    const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag,
    ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) {
  // Don't collect any headers for unavailable modules.
  if (!Module->isAvailable())
    return std::error_code();

  // Resolve all lazy header directives to header files.
  ModMap.resolveHeaderDirectives(Module, /*File=*/std::nullopt);

  // If any headers are missing, we can't build this module. In most cases,
  // diagnostics for this should have already been produced; we only get here
  // if explicit stat information was provided.
  // FIXME: If the name resolves to a file with different stat information,
  // produce a better diagnostic.
  if (!Module->MissingHeaders.empty()) {
    auto &MissingHeader = Module->MissingHeaders.front();
    Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
      << MissingHeader.IsUmbrella << MissingHeader.FileName;
    return std::error_code();
  }

  // Add includes for each of these headers.
  for (auto HK : {Module::HK_Normal, Module::HK_Private}) {
    for (const Module::Header &H : Module->getHeaders(HK)) {
      Module->addTopHeader(H.Entry);
      // Use the path as specified in the module map file. We'll look for this
      // file relative to the module build directory (the directory containing
      // the module map file) so this will find the same file that we found
      // while parsing the module map.
      addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,
                       Module->IsExternC);
    }
  }
  // Note that Module->PrivateHeaders will not be a TopHeader.

  if (std::optional<Module::Header> UmbrellaHeader =
          Module->getUmbrellaHeaderAsWritten()) {
    Module->addTopHeader(UmbrellaHeader->Entry);
    if (Module->Parent)
      // Include the umbrella header for submodules.
      addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,
                       Includes, LangOpts, Module->IsExternC);
  } else if (std::optional<Module::DirectoryName> UmbrellaDir =
                 Module->getUmbrellaDirAsWritten()) {
    // Add all of the headers we find in this subdirectory.
    std::error_code EC;
    SmallString<128> DirNative;
    llvm::sys::path::native(UmbrellaDir->Entry.getName(), DirNative);

    llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
    SmallVector<std::pair<std::string, std::string>, 8> HeaderPaths;
    for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;
         Dir != End && !EC; Dir.increment(EC)) {
      // Check whether this entry has an extension typically associated with
      // headers.
      if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
               .Cases(".h", ".H", ".hh", ".hpp", true)
               .Default(false))
        continue;

      // Compute the relative path from the directory to this file.
      SmallVector<StringRef, 16> Components;
      auto PathIt = llvm::sys::path::rbegin(Dir->path());
      for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
        Components.push_back(*PathIt);
      SmallString<128> RelativeHeader(
          UmbrellaDir->PathRelativeToRootModuleDirectory);
      for (auto It = Components.rbegin(), End = Components.rend(); It != End;
           ++It)
        llvm::sys::path::append(RelativeHeader, *It);

      HeaderPaths.push_back(
          std::make_pair(Dir->path().str(), RelativeHeader.c_str()));
    }

    if (EC)
      return EC;

    // Sort header paths and make the header inclusion order deterministic
    // across different OSs and filesystems. As the header search table
    // serialization order depends on the file reference UID, we need to create
    // file references in deterministic order too.
    llvm::sort(HeaderPaths, llvm::less_first());
    for (auto &[Path, RelPath] : HeaderPaths) {
      auto Header = FileMgr.getOptionalFileRef(Path);
      // FIXME: This shouldn't happen unless there is a file system race. Is
      // that worth diagnosing?
      if (!Header)
        continue;

      // If this header is marked 'unavailable' in this module, don't include
      // it.
      if (ModMap.isHeaderUnavailableInModule(*Header, Module))
        continue;

      // Include this header as part of the umbrella directory.
      Module->addTopHeader(*Header);
      addHeaderInclude(RelPath, Includes, LangOpts, Module->IsExternC);
    }
  }

  // Recurse into submodules.
  for (auto *Submodule : Module->submodules())
    if (std::error_code Err = collectModuleHeaderIncludes(
            LangOpts, FileMgr, Diag, ModMap, Submodule, Includes))
      return Err;

  return std::error_code();
}

static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem,
                                        bool IsPreprocessed,
                                        std::string &PresumedModuleMapFile,
                                        unsigned &Offset) {
  auto &SrcMgr = CI.getSourceManager();
  HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();

  // Map the current input to a file.
  FileID ModuleMapID = SrcMgr.getMainFileID();
  OptionalFileEntryRef ModuleMap = SrcMgr.getFileEntryRefForID(ModuleMapID);
  assert(ModuleMap && "MainFileID without FileEntry");

  // If the module map is preprocessed, handle the initial line marker;
  // line directives are not part of the module map syntax in general.
  Offset = 0;
  if (IsPreprocessed) {
    SourceLocation EndOfLineMarker =
        ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true);
    if (EndOfLineMarker.isValid())
      Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;
  }

  // Load the module map file.
  if (HS.parseAndLoadModuleMapFile(*ModuleMap, IsSystem, ModuleMapID, &Offset,
                                   PresumedModuleMapFile))
    return true;

  if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset)
    Offset = 0;

  // Infer framework module if possible.
  if (HS.getModuleMap().canInferFrameworkModule(ModuleMap->getDir())) {
    SmallString<128> InferredFrameworkPath = ModuleMap->getDir().getName();
    llvm::sys::path::append(InferredFrameworkPath,
                            CI.getLangOpts().ModuleName + ".framework");
    if (auto Dir =
            CI.getFileManager().getOptionalDirectoryRef(InferredFrameworkPath))
      (void)HS.getModuleMap().inferFrameworkModule(*Dir, IsSystem, nullptr);
  }

  return false;
}

static Module *prepareToBuildModule(CompilerInstance &CI,
                                    StringRef ModuleMapFilename) {
  if (CI.getLangOpts().CurrentModule.empty()) {
    CI.getDiagnostics().Report(diag::err_missing_module_name);

    // FIXME: Eventually, we could consider asking whether there was just
    // a single module described in the module map, and use that as a
    // default. Then it would be fairly trivial to just "compile" a module
    // map with a single module (the common case).
    return nullptr;
  }

  // Dig out the module definition.
  HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
  Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, SourceLocation(),
                              /*AllowSearch=*/true);
  if (!M) {
    CI.getDiagnostics().Report(diag::err_missing_module)
      << CI.getLangOpts().CurrentModule << ModuleMapFilename;

    return nullptr;
  }

  // Check whether we can build this module at all.
  if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), *M,
                                           CI.getDiagnostics()))
    return nullptr;

  // Inform the preprocessor that includes from within the input buffer should
  // be resolved relative to the build directory of the module map file.
  CI.getPreprocessor().setMainFileDir(*M->Directory);

  // If the module was inferred from a different module map (via an expanded
  // umbrella module definition), track that fact.
  // FIXME: It would be preferable to fill this in as part of processing
  // the module map, rather than adding it after the fact.
  StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap;
  if (!OriginalModuleMapName.empty()) {
    auto OriginalModuleMap =
        CI.getFileManager().getOptionalFileRef(OriginalModuleMapName,
                                               /*openFile*/ true);
    if (!OriginalModuleMap) {
      CI.getDiagnostics().Report(diag::err_module_map_not_found)
        << OriginalModuleMapName;
      return nullptr;
    }
    if (*OriginalModuleMap != CI.getSourceManager().getFileEntryRefForID(
                                  CI.getSourceManager().getMainFileID())) {
      auto FileCharacter =
          M->IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
      FileID OriginalModuleMapFID = CI.getSourceManager().getOrCreateFileID(
          *OriginalModuleMap, FileCharacter);
      CI.getPreprocessor()
          .getHeaderSearchInfo()
          .getModuleMap()
          .setInferredModuleAllowedBy(M, OriginalModuleMapFID);
    }
  }

  // If we're being run from the command-line, the module build stack will not
  // have been filled in yet, so complete it now in order to allow us to detect
  // module cycles.
  SourceManager &SourceMgr = CI.getSourceManager();
  if (SourceMgr.getModuleBuildStack().empty())
    SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,
                                   FullSourceLoc(SourceLocation(), SourceMgr));
  return M;
}

/// Compute the input buffer that should be used to build the specified module.
static std::unique_ptr<llvm::MemoryBuffer>
getInputBufferForModule(CompilerInstance &CI, Module *M) {
  FileManager &FileMgr = CI.getFileManager();

  // Collect the set of #includes we need to build the module.
  SmallString<256> HeaderContents;
  std::error_code Err = std::error_code();
  if (std::optional<Module::Header> UmbrellaHeader =
          M->getUmbrellaHeaderAsWritten())
    addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,
                     HeaderContents, CI.getLangOpts(), M->IsExternC);
  Err = collectModuleHeaderIncludes(
      CI.getLangOpts(), FileMgr, CI.getDiagnostics(),
      CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,
      HeaderContents);

  if (Err) {
    CI.getDiagnostics().Report(diag::err_module_cannot_create_includes)
      << M->getFullModuleName() << Err.message();
    return nullptr;
  }

  return llvm::MemoryBuffer::getMemBufferCopy(
      HeaderContents, Module::getModuleInputBufferName());
}

bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
                                     const FrontendInputFile &RealInput) {
  FrontendInputFile Input(RealInput);
  assert(!Instance && "Already processing a source file!");
  assert(!Input.isEmpty() && "Unexpected empty filename!");
  setCurrentInput(Input);
  setCompilerInstance(&CI);

  bool HasBegunSourceFile = false;
  bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&
                       usesPreprocessorOnly();

  // If we fail, reset state since the client will not end up calling the
  // matching EndSourceFile(). All paths that return true should release this.
  auto FailureCleanup = llvm::make_scope_exit([&]() {
    if (HasBegunSourceFile)
      CI.getDiagnosticClient().EndSourceFile();
    CI.setASTConsumer(nullptr);
    CI.clearOutputFiles(/*EraseFiles=*/true);
    CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
    setCurrentInput(FrontendInputFile());
    setCompilerInstance(nullptr);
  });

  if (!BeginInvocation(CI))
    return false;

  // If we're replaying the build of an AST file, import it and set up
  // the initial state from its build.
  if (ReplayASTFile) {
    IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();

    // The AST unit populates its own diagnostics engine rather than ours.
    auto ASTDiags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(
        Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions());
    ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);

    // FIXME: What if the input is a memory buffer?
    StringRef InputFile = Input.getFile();

    std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
        InputFile, CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly,
        CI.getVirtualFileSystemPtr(), nullptr, ASTDiags, CI.getFileSystemOpts(),
        CI.getHeaderSearchOpts());
    if (!AST)
      return false;

    // Options relating to how we treat the input (but not what we do with it)
    // are inherited from the AST unit.
    CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts();
    CI.getPreprocessorOpts() = AST->getPreprocessorOpts();
    CI.getLangOpts() = AST->getLangOpts();

    // Set the shared objects, these are reset when we finish processing the
    // file, otherwise the CompilerInstance will happily destroy them.
    CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr());
    CI.setFileManager(AST->getFileManagerPtr());
    CI.createSourceManager(CI.getFileManager());
    CI.getSourceManager().initializeForReplay(AST->getSourceManager());

    // Preload all the module files loaded transitively by the AST unit. Also
    // load all module map files that were parsed as part of building the AST
    // unit.
    if (auto ASTReader = AST->getASTReader()) {
      auto &MM = ASTReader->getModuleManager();
      auto &PrimaryModule = MM.getPrimaryModule();

      for (serialization::ModuleFile &MF : MM)
        if (&MF != &PrimaryModule)
          CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);

      ASTReader->visitTopLevelModuleMaps(PrimaryModule, [&](FileEntryRef FE) {
        CI.getFrontendOpts().ModuleMapFiles.push_back(
            std::string(FE.getName()));
      });
    }

    // Set up the input file for replay purposes.
    auto Kind = AST->getInputKind();
    if (Kind.getFormat() == InputKind::ModuleMap) {
      Module *ASTModule =
          AST->getPreprocessor().getHeaderSearchInfo().lookupModule(
              AST->getLangOpts().CurrentModule, SourceLocation(),
              /*AllowSearch*/ false);
      assert(ASTModule && "module file does not define its own module");
      Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);
    } else {
      auto &OldSM = AST->getSourceManager();
      FileID ID = OldSM.getMainFileID();
      if (auto File = OldSM.getFileEntryRefForID(ID))
        Input = FrontendInputFile(File->getName(), Kind);
      else
        Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind);
    }
    setCurrentInput(Input, std::move(AST));
  }

  // AST files follow a very different path, since they share objects via the
  // AST unit.
  if (Input.getKind().getFormat() == InputKind::Precompiled) {
    assert(!usesPreprocessorOnly() && "this case was handled above");
    assert(hasASTFileSupport() &&
           "This action does not have AST file support!");

    IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();

    // FIXME: What if the input is a memory buffer?
    StringRef InputFile = Input.getFile();

    std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
        InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything,
        CI.getVirtualFileSystemPtr(), nullptr, Diags, CI.getFileSystemOpts(),
        CI.getHeaderSearchOpts(), &CI.getLangOpts());

    if (!AST)
      return false;

    // Inform the diagnostic client we are processing a source file.
    CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
    HasBegunSourceFile = true;

    // Set the shared objects, these are reset when we finish processing the
    // file, otherwise the CompilerInstance will happily destroy them.
    CI.setFileManager(AST->getFileManagerPtr());
    CI.setSourceManager(AST->getSourceManagerPtr());
    CI.setPreprocessor(AST->getPreprocessorPtr());
    Preprocessor &PP = CI.getPreprocessor();
    PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
                                           PP.getLangOpts());
    CI.setASTContext(AST->getASTContextPtr());

    setCurrentInput(Input, std::move(AST));

    // Initialize the action.
    if (!BeginSourceFileAction(CI))
      return false;

    // Create the AST consumer.
    CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile));
    if (!CI.hasASTConsumer())
      return false;

    FailureCleanup.release();
    return true;
  }

  // Set up the file system, file and source managers, if needed.
  if (!CI.hasVirtualFileSystem())
    CI.createVirtualFileSystem();
  if (!CI.hasFileManager()) {
    if (!CI.createFileManager()) {
      return false;
    }
  }
  if (!CI.hasSourceManager()) {
    CI.createSourceManager(CI.getFileManager());
    if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) {
      static_cast<SARIFDiagnosticPrinter *>(&CI.getDiagnosticClient())
          ->setSarifWriter(
              std::make_unique<SarifDocumentWriter>(CI.getSourceManager()));
    }
  }

  // Set up embedding for any specified files. Do this before we load any
  // source files, including the primary module map for the compilation.
  for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
    if (auto FE = CI.getFileManager().getOptionalFileRef(F, /*openFile*/true))
      CI.getSourceManager().setFileIsTransient(*FE);
    else
      CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
  }
  if (CI.getFrontendOpts().ModulesEmbedAllFiles)
    CI.getSourceManager().setAllFilesAreTransient(true);

  // IR files bypass the rest of initialization.
  if (Input.getKind().getLanguage() == Language::LLVM_IR) {
    if (!hasIRSupport()) {
      CI.getDiagnostics().Report(diag::err_ast_action_on_llvm_ir)
          << Input.getFile();
      return false;
    }

    // Inform the diagnostic client we are processing a source file.
    CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
    HasBegunSourceFile = true;

    // Initialize the action.
    if (!BeginSourceFileAction(CI))
      return false;

    // Initialize the main file entry.
    if (!CI.InitializeSourceManager(CurrentInput))
      return false;

    FailureCleanup.release();
    return true;
  }

  // If the implicit PCH include is actually a directory, rather than
  // a single file, search for a suitable PCH file in that directory.
  if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
    FileManager &FileMgr = CI.getFileManager();
    PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
    StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
    std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();
    if (auto PCHDir = FileMgr.getOptionalDirectoryRef(PCHInclude)) {
      std::error_code EC;
      SmallString<128> DirNative;
      llvm::sys::path::native(PCHDir->getName(), DirNative);
      bool Found = false;
      llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
      for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
                                         DirEnd;
           Dir != DirEnd && !EC; Dir.increment(EC)) {
        // Check whether this is an acceptable AST file.
        if (ASTReader::isAcceptableASTFile(
                Dir->path(), FileMgr, CI.getModuleCache(),
                CI.getPCHContainerReader(), CI.getLangOpts(),
                CI.getCodeGenOpts(), CI.getTargetOpts(),
                CI.getPreprocessorOpts(), SpecificModuleCachePath,
                /*RequireStrictOptionMatches=*/true)) {
          PPOpts.ImplicitPCHInclude = std::string(Dir->path());
          Found = true;
          break;
        }
      }

      if (!Found) {
        CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude;
        return false;
      }
    }
  }

  // Set up the preprocessor if needed. When parsing model files the
  // preprocessor of the original source is reused.
  if (!isModelParsingAction())
    CI.createPreprocessor(getTranslationUnitKind());

  // Inform the diagnostic client we are processing a source file.
  CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
                                           &CI.getPreprocessor());
  HasBegunSourceFile = true;

  // Handle C++20 header units.
  // Here, the user has the option to specify that the header name should be
  // looked up in the pre-processor search paths (and the main filename as
  // passed by the driver might therefore be incomplete until that look-up).
  if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&
      !Input.getKind().isPreprocessed()) {
    StringRef FileName = Input.getFile();
    InputKind Kind = Input.getKind();
    if (Kind.getHeaderUnitKind() != InputKind::HeaderUnit_Abs) {
      assert(CI.hasPreprocessor() &&
             "trying to build a header unit without a Pre-processor?");
      HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
      // Relative searches begin from CWD.
      auto Dir = CI.getFileManager().getOptionalDirectoryRef(".");
      SmallVector<std::pair<OptionalFileEntryRef, DirectoryEntryRef>, 1> CWD;
      CWD.push_back({std::nullopt, *Dir});
      OptionalFileEntryRef FE =
          HS.LookupFile(FileName, SourceLocation(),
                        /*Angled*/ Input.getKind().getHeaderUnitKind() ==
                            InputKind::HeaderUnit_System,
                        nullptr, nullptr, CWD, nullptr, nullptr, nullptr,
                        nullptr, nullptr, nullptr);
      if (!FE) {
        CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
            << FileName;
        return false;
      }
      // We now have the filename...
      FileName = FE->getName();
      // ... still a header unit, but now use the path as written.
      Kind = Input.getKind().withHeaderUnit(InputKind::HeaderUnit_Abs);
      Input = FrontendInputFile(FileName, Kind, Input.isSystem());
    }
    // Unless the user has overridden the name, the header unit module name is
    // the pathname for the file.
    if (CI.getLangOpts().ModuleName.empty())
      CI.getLangOpts().ModuleName = std::string(FileName);
    CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;
  }

  if (!CI.InitializeSourceManager(Input))
    return false;

  if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&
      Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) {
    // We have an input filename like foo.iih, but we want to find the right
    // module name (and original file, to build the map entry).
    // Check if the first line specifies the original source file name with a
    // linemarker.
    std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());
    ReadOriginalFileName(CI, PresumedInputFile);
    // Unless the user overrides this, the module name is the name by which the
    // original file was known.
    if (CI.getLangOpts().ModuleName.empty())
      CI.getLangOpts().ModuleName = std::string(PresumedInputFile);
    CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;
  }

  // For module map files, we first parse the module map and synthesize a
  // "<module-includes>" buffer before more conventional processing.
  if (Input.getKind().getFormat() == InputKind::ModuleMap) {
    CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);

    std::string PresumedModuleMapFile;
    unsigned OffsetToContents;
    if (loadModuleMapForModuleBuild(CI, Input.isSystem(),
                                    Input.isPreprocessed(),
                                    PresumedModuleMapFile, OffsetToContents))
      return false;

    auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());
    if (!CurrentModule)
      return false;

    CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile;

    if (OffsetToContents)
      // If the module contents are in the same file, skip to them.
      CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true);
    else {
      // Otherwise, convert the module description to a suitable input buffer.
      auto Buffer = getInputBufferForModule(CI, CurrentModule);
      if (!Buffer)
        return false;

      // Reinitialize the main file entry to refer to the new input.
      auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
      auto &SourceMgr = CI.getSourceManager();
      auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind);
      assert(BufferID.isValid() && "couldn't create module buffer ID");
      SourceMgr.setMainFileID(BufferID);
    }
  }

  // Initialize the action.
  if (!BeginSourceFileAction(CI))
    return false;

  // If we were asked to load any module map files, do so now.
  for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) {
    if (auto File = CI.getFileManager().getOptionalFileRef(Filename))
      CI.getPreprocessor().getHeaderSearchInfo().parseAndLoadModuleMapFile(
          *File, /*IsSystem*/ false);
    else
      CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
  }

  // If compiling implementation of a module, load its module map file now.
  (void)CI.getPreprocessor().getCurrentModuleImplementation();

  // Add a module declaration scope so that modules from -fmodule-map-file
  // arguments may shadow modules found implicitly in search paths.
  CI.getPreprocessor()
      .getHeaderSearchInfo()
      .getModuleMap()
      .finishModuleDeclarationScope();

  // Create the AST context and consumer unless this is a preprocessor only
  // action.
  if (!usesPreprocessorOnly()) {
    // Parsing a model file should reuse the existing ASTContext.
    if (!isModelParsingAction())
      CI.createASTContext();

    // For preprocessed files, check if the first line specifies the original
    // source file name with a linemarker.
    std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());
    if (Input.isPreprocessed())
      ReadOriginalFileName(CI, PresumedInputFile);

    std::unique_ptr<ASTConsumer> Consumer =
        CreateWrappedASTConsumer(CI, PresumedInputFile);
    if (!Consumer)
      return false;

    // FIXME: should not overwrite ASTMutationListener when parsing model files?
    if (!isModelParsingAction())
      CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());

    if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
      // Convert headers to PCH and chain them.
      IntrusiveRefCntPtr<ExternalSemaSource> source;
      IntrusiveRefCntPtr<ASTReader> FinalReader;
      source = createChainedIncludesSource(CI, FinalReader);
      if (!source)
        return false;
      CI.setASTReader(FinalReader);
      CI.getASTContext().setExternalSource(source);
    } else if (CI.getLangOpts().Modules ||
               !CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
      // Use PCM or PCH.
      assert(hasPCHSupport() && "This action does not have PCH support!");
      ASTDeserializationListener *DeserialListener =
          Consumer->GetASTDeserializationListener();
      bool DeleteDeserialListener = false;
      if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) {
        DeserialListener = new DeserializedDeclsDumper(DeserialListener,
                                                       DeleteDeserialListener);
        DeleteDeserialListener = true;
      }
      if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) {
        DeserialListener = new DeserializedDeclsChecker(
            CI.getASTContext(),
            CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,
            DeserialListener, DeleteDeserialListener);
        DeleteDeserialListener = true;
      }
      if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
        CI.createPCHExternalASTSource(
            CI.getPreprocessorOpts().ImplicitPCHInclude,
            CI.getPreprocessorOpts().DisablePCHOrModuleValidation,
            CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
            DeserialListener, DeleteDeserialListener);
        if (!CI.getASTContext().getExternalSource())
          return false;
      }
      // If modules are enabled, create the AST reader before creating
      // any builtins, so that all declarations know that they might be
      // extended by an external source.
      if (CI.getLangOpts().Modules || !CI.hasASTContext() ||
          !CI.getASTContext().getExternalSource()) {
        CI.createASTReader();
        CI.getASTReader()->setDeserializationListener(DeserialListener,
                                                      DeleteDeserialListener);
      }
    }

    CI.setASTConsumer(std::move(Consumer));
    if (!CI.hasASTConsumer())
      return false;
  }

  // Initialize built-in info as long as we aren't using an external AST
  // source.
  if (CI.getLangOpts().Modules || !CI.hasASTContext() ||
      !CI.getASTContext().getExternalSource()) {
    Preprocessor &PP = CI.getPreprocessor();
    PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
                                           PP.getLangOpts());
  } else {
    // FIXME: If this is a problem, recover from it by creating a multiplex
    // source.
    assert((!CI.getLangOpts().Modules || CI.getASTReader()) &&
           "modules enabled but created an external source that "
           "doesn't support modules");
  }

  // If we were asked to load any module files, do so now.
  for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) {
    serialization::ModuleFile *Loaded = nullptr;
    if (!CI.loadModuleFile(ModuleFile, Loaded))
      return false;

    if (Loaded && Loaded->StandardCXXModule)
      CI.getDiagnostics().Report(
          diag::warn_eagerly_load_for_standard_cplusplus_modules);
  }

  // If there is a layout overrides file, attach an external AST source that
  // provides the layouts from that file.
  if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&
      CI.hasASTContext() && !CI.getASTContext().getExternalSource()) {
    auto Override = llvm::makeIntrusiveRefCnt<LayoutOverrideSource>(
        CI.getFrontendOpts().OverrideRecordLayoutsFile);
    CI.getASTContext().setExternalSource(Override);
  }

  // Setup HLSL External Sema Source
  if (CI.getLangOpts().HLSL && CI.hasASTContext()) {
    auto HLSLSema = llvm::makeIntrusiveRefCnt<HLSLExternalSemaSource>();
    if (auto SemaSource = dyn_cast_if_present<ExternalSemaSource>(
            CI.getASTContext().getExternalSourcePtr())) {
      auto MultiSema = llvm::makeIntrusiveRefCnt<MultiplexExternalSemaSource>(
          std::move(SemaSource), std::move(HLSLSema));
      CI.getASTContext().setExternalSource(std::move(MultiSema));
    } else
      CI.getASTContext().setExternalSource(std::move(HLSLSema));
  }

  FailureCleanup.release();
  return true;
}

llvm::Error FrontendAction::Execute() {
  CompilerInstance &CI = getCompilerInstance();
  ExecuteAction();

  // If we are supposed to rebuild the global module index, do so now unless
  // there were any module-build failures.
  if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() &&
      CI.hasPreprocessor()) {
    StringRef Cache =
        CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath();
    if (!Cache.empty()) {
      if (llvm::Error Err = GlobalModuleIndex::writeIndex(
              CI.getFileManager(), CI.getPCHContainerReader(), Cache)) {
        // FIXME this drops the error on the floor, but
        // Index/pch-from-libclang.c seems to rely on dropping at least some of
        // the error conditions!
        consumeError(std::move(Err));
      }
    }
  }

  return llvm::Error::success();
}

void FrontendAction::EndSourceFile() {
  CompilerInstance &CI = getCompilerInstance();

  // Inform the preprocessor we are done.
  if (CI.hasPreprocessor())
    CI.getPreprocessor().EndSourceFile();

  // Inform the diagnostic client we are done with this source file.
  // Do this after notifying the preprocessor, so that end-of-file preprocessor
  // callbacks can report diagnostics.
  CI.getDiagnosticClient().EndSourceFile();

  // Finalize the action.
  EndSourceFileAction();

  // Sema references the ast consumer, so reset sema first.
  //
  // FIXME: There is more per-file stuff we could just drop here?
  bool DisableFree = CI.getFrontendOpts().DisableFree;
  if (DisableFree) {
    CI.resetAndLeakSema();
    CI.resetAndLeakASTContext();
    llvm::BuryPointer(CI.takeASTConsumer().get());
  } else {
    CI.setSema(nullptr);
    CI.setASTContext(nullptr);
    CI.setASTConsumer(nullptr);
  }

  if (CI.getFrontendOpts().ShowStats) {
    llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFileOrBufferName() << "':\n";
    if (CI.hasPreprocessor()) {
      CI.getPreprocessor().PrintStats();
      CI.getPreprocessor().getIdentifierTable().PrintStats();
      CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
    }
    if (CI.hasSourceManager()) {
      CI.getSourceManager().PrintStats();
    }
    llvm::errs() << "\n";
  }

  // Cleanup the output streams, and erase the output files if instructed by the
  // FrontendAction.
  CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());

  // The resources are owned by AST when the current file is AST.
  // So we reset the resources here to avoid users accessing it
  // accidently.
  if (isCurrentFileAST()) {
    if (DisableFree) {
      CI.resetAndLeakPreprocessor();
      CI.resetAndLeakSourceManager();
      CI.resetAndLeakFileManager();
      llvm::BuryPointer(std::move(CurrentASTUnit));
    } else {
      CI.setPreprocessor(nullptr);
      CI.setSourceManager(nullptr);
      CI.setFileManager(nullptr);
    }
  }

  setCompilerInstance(nullptr);
  setCurrentInput(FrontendInputFile());
  CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
}

bool FrontendAction::shouldEraseOutputFiles() {
  return getCompilerInstance().getDiagnostics().hasErrorOccurred();
}

//===----------------------------------------------------------------------===//
// Utility Actions
//===----------------------------------------------------------------------===//

void ASTFrontendAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  if (!CI.hasPreprocessor())
    return;
  // This is a fallback: If the client forgets to invoke this, we mark the
  // current stack as the bottom. Though not optimal, this could help prevent
  // stack overflow during deep recursion.
  clang::noteBottomOfStack();

  // FIXME: Move the truncation aspect of this into Sema, we delayed this till
  // here so the source manager would be initialized.
  if (hasCodeCompletionSupport() &&
      !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
    CI.createCodeCompletionConsumer();

  // Use a code completion consumer?
  CodeCompleteConsumer *CompletionConsumer = nullptr;
  if (CI.hasCodeCompletionConsumer())
    CompletionConsumer = &CI.getCodeCompletionConsumer();

  if (!CI.hasSema())
    CI.createSema(getTranslationUnitKind(), CompletionConsumer);

  ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
           CI.getFrontendOpts().SkipFunctionBodies);
}

void PluginASTAction::anchor() { }

std::unique_ptr<ASTConsumer>
PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
                                              StringRef InFile) {
  llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
}

bool WrapperFrontendAction::PrepareToExecuteAction(CompilerInstance &CI) {
  return WrappedAction->PrepareToExecuteAction(CI);
}
std::unique_ptr<ASTConsumer>
WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,
                                         StringRef InFile) {
  return WrappedAction->CreateASTConsumer(CI, InFile);
}
bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {
  return WrappedAction->BeginInvocation(CI);
}
bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) {
  WrappedAction->setCurrentInput(getCurrentInput());
  WrappedAction->setCompilerInstance(&CI);
  auto Ret = WrappedAction->BeginSourceFileAction(CI);
  // BeginSourceFileAction may change CurrentInput, e.g. during module builds.
  setCurrentInput(WrappedAction->getCurrentInput());
  return Ret;
}
void WrapperFrontendAction::ExecuteAction() {
  WrappedAction->ExecuteAction();
}
void WrapperFrontendAction::EndSourceFile() { WrappedAction->EndSourceFile(); }
void WrapperFrontendAction::EndSourceFileAction() {
  WrappedAction->EndSourceFileAction();
}
bool WrapperFrontendAction::shouldEraseOutputFiles() {
  return WrappedAction->shouldEraseOutputFiles();
}

bool WrapperFrontendAction::usesPreprocessorOnly() const {
  return WrappedAction->usesPreprocessorOnly();
}
TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() {
  return WrappedAction->getTranslationUnitKind();
}
bool WrapperFrontendAction::hasPCHSupport() const {
  return WrappedAction->hasPCHSupport();
}
bool WrapperFrontendAction::hasASTFileSupport() const {
  return WrappedAction->hasASTFileSupport();
}
bool WrapperFrontendAction::hasIRSupport() const {
  return WrappedAction->hasIRSupport();
}
bool WrapperFrontendAction::hasCodeCompletionSupport() const {
  return WrappedAction->hasCodeCompletionSupport();
}

WrapperFrontendAction::WrapperFrontendAction(
    std::unique_ptr<FrontendAction> WrappedAction)
  : WrappedAction(std::move(WrappedAction)) {}
