//===--- 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/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/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)) {
      // These decls cover a lot of nested declarations that might not be used,
      // reducing the granularity and making the output less useful.
      return;
    }
    if (auto *DC = D->getDeclContext(); !DC || !DC->isFileContext()) {
      // We choose to work at namespace level to reduce complexity and the
      // number of cases we care about.
      return;
    }
    PendingDecls.push_back(D);
  }

  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) {
      CharSourceRange R = SM.getExpansionRange(D->getSourceRange());
      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;
  bool IsCollectingDecls = true;
  const SourceManager &SM;
  std::unique_ptr<llvm::raw_ostream> OS;

  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";
  }
};

/// 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, FileEntryRef>, 8> Headers;
    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;

      auto Header = FileMgr.getOptionalFileRef(Dir->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;

      // 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);

      std::string RelName = RelativeHeader.c_str();
      Headers.push_back(std::make_pair(RelName, *Header));
    }

    if (EC)
      return EC;

    // Sort header paths and make the header inclusion order deterministic
    // across different OSs and filesystems.
    llvm::sort(Headers, llvm::less_first());
    for (auto &H : Headers) {
      // Include this header as part of the umbrella directory.
      Module->addTopHeader(H.second);
      addHeaderInclude(H.first, 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.getDiagnostics());

    // The AST unit populates its own diagnostics engine rather than ours.
    IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags(new 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,
        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.setFileManager(&AST->getFileManager());
    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.getDiagnostics());

    // 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, 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->getFileManager());
    CI.setSourceManager(&AST->getSourceManager());
    CI.setPreprocessor(AST->getPreprocessorPtr());
    Preprocessor &PP = CI.getPreprocessor();
    PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
                                           PP.getLangOpts());
    CI.setASTContext(&AST->getASTContext());

    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 and source managers, if needed.
  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, FinalReader;
      source = createChainedIncludesSource(CI, FinalReader);
      if (!source)
        return false;
      CI.setASTReader(static_cast<ASTReader *>(FinalReader.get()));
      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()) {
    IntrusiveRefCntPtr<ExternalASTSource>
      Override(new LayoutOverrideSource(
                     CI.getFrontendOpts().OverrideRecordLayoutsFile));
    CI.getASTContext().setExternalSource(Override);
  }

  // Setup HLSL External Sema Source
  if (CI.getLangOpts().HLSL && CI.hasASTContext()) {
    IntrusiveRefCntPtr<ExternalSemaSource> HLSLSema(
        new HLSLExternalSemaSource());
    if (auto *SemaSource = dyn_cast_if_present<ExternalSemaSource>(
            CI.getASTContext().getExternalSource())) {
      IntrusiveRefCntPtr<ExternalSemaSource> MultiSema(
          new MultiplexExternalSemaSource(SemaSource, HLSLSema.get()));
      CI.getASTContext().setExternalSource(MultiSema);
    } else
      CI.getASTContext().setExternalSource(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)) {}
