//===--- 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/LangStandard.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/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/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.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 <system_error>
using namespace clang;

LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)

namespace {

class DelegatingDeserializationListener : public ASTDeserializationListener {
  ASTDeserializationListener *Previous;
  bool DeletePrevious;

public:
  explicit DelegatingDeserializationListener(
      ASTDeserializationListener *Previous, bool DeletePrevious)
      : Previous(Previous), DeletePrevious(DeletePrevious) {}
  ~DelegatingDeserializationListener() override {
    if (DeletePrevious)
      delete Previous;
  }

  void ReaderInitialized(ASTReader *Reader) override {
    if (Previous)
      Previous->ReaderInitialized(Reader);
  }
  void IdentifierRead(serialization::IdentID ID,
                      IdentifierInfo *II) override {
    if (Previous)
      Previous->IdentifierRead(ID, II);
  }
  void TypeRead(serialization::TypeIdx Idx, QualType T) override {
    if (Previous)
      Previous->TypeRead(Idx, T);
  }
  void DeclRead(serialization::DeclID ID, const Decl *D) override {
    if (Previous)
      Previous->DeclRead(ID, D);
  }
  void SelectorRead(serialization::SelectorID ID, Selector Sel) override {
    if (Previous)
      Previous->SelectorRead(ID, Sel);
  }
  void MacroDefinitionRead(serialization::PreprocessedEntityID PPID,
                           MacroDefinitionRecord *MD) override {
    if (Previous)
      Previous->MacroDefinitionRead(PPID, MD);
  }
};

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

  void DeclRead(serialization::DeclID 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(serialization::DeclID 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->getNameAsString();
      }

    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, /*AllowSearch*/false);
}

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

  // 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 there are no registered plugins we don't need to wrap the consumer
  if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end())
    return Consumer;

  // 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>> Consumers;
  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::Cmdline) {
      // This is O(|plugins| * |add_plugins|), but since both numbers are
      // way below 50 in practice, that's ok.
      if (llvm::any_of(CI.getFrontendOpts().AddPluginActions,
                       [&](const std::string &PluginAction) {
                         return PluginAction == Plugin.getName();
                       }))
        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));
  for (auto &C : AfterConsumers) {
    Consumers.push_back(std::move(C));
  }

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

  bool Invalid = false;
  const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid);
  if (Invalid)
    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);

  // 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 (Module::Header &H : Module->Headers[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.NameAsWritten, Includes, LangOpts, Module->IsExternC);
    }
  }
  // Note that Module->PrivateHeaders will not be a TopHeader.

  if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) {
    Module->addTopHeader(UmbrellaHeader.Entry);
    if (Module->Parent)
      // Include the umbrella header for submodules.
      addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts,
                       Module->IsExternC);
  } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) {
    // 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, const FileEntry *>, 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.getFile(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.NameAsWritten);
      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.begin(), Headers.end(), [](
      const std::pair<std::string, const FileEntry *> &LHS,
      const std::pair<std::string, const FileEntry *> &RHS) {
        return LHS.first < RHS.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 (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
                                      SubEnd = Module->submodule_end();
       Sub != SubEnd; ++Sub)
    if (std::error_code Err = collectModuleHeaderIncludes(
            LangOpts, FileMgr, Diag, ModMap, *Sub, 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();
  const FileEntry *ModuleMap = SrcMgr.getFileEntryForID(ModuleMapID);

  // 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.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset,
                           PresumedModuleMapFile))
    return true;

  if (SrcMgr.getBuffer(ModuleMapID)->getBufferSize() == Offset)
    Offset = 0;

  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,
                              /*AllowSearch=*/false);
  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(),
                                           CI.getDiagnostics(), M))
    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().getFile(OriginalModuleMapName,
                                    /*openFile*/ true);
    if (!OriginalModuleMap) {
      CI.getDiagnostics().Report(diag::err_module_map_not_found)
        << OriginalModuleMapName;
      return nullptr;
    }
    if (*OriginalModuleMap != CI.getSourceManager().getFileEntryForID(
                                 CI.getSourceManager().getMainFileID())) {
      M->IsInferred = true;
      CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()
        .setInferredModuleAllowedBy(M, *OriginalModuleMap);
    }
  }

  // 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 (Module::Header UmbrellaHeader = M->getUmbrellaHeader())
    addHeaderInclude(UmbrellaHeader.NameAsWritten, 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 (!BeginInvocation(CI))
    goto failure;

  // 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(
        std::string(InputFile), CI.getPCHContainerReader(),
        ASTUnit::LoadPreprocessorOnly, ASTDiags, CI.getFileSystemOpts(),
        CI.getCodeGenOpts().DebugTypeExtRefs);
    if (!AST)
      goto failure;

    // 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, [&](const FileEntry *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, /*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.getFileEntryForID(ID))
        Input = FrontendInputFile(File->getName(), Kind);
      else
        Input = FrontendInputFile(OldSM.getBuffer(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(
        std::string(InputFile), CI.getPCHContainerReader(),
        ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts(),
        CI.getCodeGenOpts().DebugTypeExtRefs);

    if (!AST)
      goto failure;

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

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

    return true;
  }

  // Set up the file and source managers, if needed.
  if (!CI.hasFileManager()) {
    if (!CI.createFileManager()) {
      goto failure;
    }
  }
  if (!CI.hasSourceManager())
    CI.createSourceManager(CI.getFileManager());

  // 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().getFile(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) {
    assert(hasIRSupport() &&
           "This action does not have IR file support!");

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

    // Initialize the action.
    if (!BeginSourceFileAction(CI))
      goto failure;

    // Initialize the main file entry.
    if (!CI.InitializeSourceManager(CurrentInput))
      goto failure;

    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.getDirectory(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.getPCHContainerReader(),
                CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(),
                SpecificModuleCachePath)) {
          PPOpts.ImplicitPCHInclude = std::string(Dir->path());
          Found = true;
          break;
        }
      }

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

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

  // Initialize the main file entry.
  if (!CI.InitializeSourceManager(Input))
    goto failure;

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

    auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());
    if (!CurrentModule)
      goto failure;

    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)
        goto failure;

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

  // 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().getFile(Filename))
      CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile(
          *File, /*IsSystem*/false);
    else
      CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
  }

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

    // 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)
        goto failure;
      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().DisablePCHValidation,
          CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener,
            DeleteDeserialListener);
        if (!CI.getASTContext().getExternalSource())
          goto failure;
      }
      // 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())
      goto failure;
  }

  // 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)
    if (!CI.loadModuleFile(ModuleFile))
      goto failure;

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

  return true;

  // If we failed, reset state since the client will not end up calling the
  // matching EndSourceFile().
failure:
  if (HasBegunSourceFile)
    CI.getDiagnosticClient().EndSourceFile();
  CI.clearOutputFiles(/*EraseFiles=*/true);
  CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
  setCurrentInput(FrontendInputFile());
  setCompilerInstance(nullptr);
  return false;
}

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

  if (CI.hasFrontendTimer()) {
    llvm::TimeRegion Timer(CI.getFrontendTimer());
    ExecuteAction();
  }
  else 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 diagnostic client we are done with this source file.
  CI.getDiagnosticClient().EndSourceFile();

  // Inform the preprocessor we are done.
  if (CI.hasPreprocessor())
    CI.getPreprocessor().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 '" << getCurrentFile() << "':\n";
    CI.getPreprocessor().PrintStats();
    CI.getPreprocessor().getIdentifierTable().PrintStats();
    CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
    CI.getSourceManager().PrintStats();
    llvm::errs() << "\n";
  }

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

  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;

  // 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::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)) {}

