//===--- Driver.h - Clang GCC Compatible Driver -----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_DRIVER_DRIVER_H
#define LLVM_CLANG_DRIVER_DRIVER_H

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Phases.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/StringSaver.h"

#include <list>
#include <map>
#include <string>
#include <vector>

namespace llvm {
class Triple;
namespace vfs {
class FileSystem;
}
} // namespace llvm

namespace clang {

namespace driver {

typedef SmallVector<InputInfo, 4> InputInfoList;

class Command;
class Compilation;
class JobAction;
class ToolChain;

/// Describes the kind of LTO mode selected via -f(no-)?lto(=.*)? options.
enum LTOKind {
  LTOK_None,
  LTOK_Full,
  LTOK_Thin,
  LTOK_Unknown
};

/// Whether headers used to construct C++20 module units should be looked
/// up by the path supplied on the command line, or in the user or system
/// search paths.
enum ModuleHeaderMode {
  HeaderMode_None,
  HeaderMode_Default,
  HeaderMode_User,
  HeaderMode_System
};

/// Driver - Encapsulate logic for constructing compilation processes
/// from a set of gcc-driver-like command line arguments.
class Driver {
  DiagnosticsEngine &Diags;

  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;

  enum DriverMode {
    GCCMode,
    GXXMode,
    CPPMode,
    CLMode,
    FlangMode,
    DXCMode
  } Mode;

  enum SaveTempsMode {
    SaveTempsNone,
    SaveTempsCwd,
    SaveTempsObj
  } SaveTemps;

  enum BitcodeEmbedMode {
    EmbedNone,
    EmbedMarker,
    EmbedBitcode
  } BitcodeEmbed;

  enum OffloadMode {
    OffloadHostDevice,
    OffloadHost,
    OffloadDevice,
  } Offload;

  /// Header unit mode set by -fmodule-header={user,system}.
  ModuleHeaderMode CXX20HeaderType;

  /// Set if we should process inputs and jobs with C++20 module
  /// interpretation.
  bool ModulesModeCXX20;

  /// LTO mode selected via -f(no-)?lto(=.*)? options.
  LTOKind LTOMode;

  /// LTO mode selected via -f(no-offload-)?lto(=.*)? options.
  LTOKind OffloadLTOMode;

public:
  enum OpenMPRuntimeKind {
    /// An unknown OpenMP runtime. We can't generate effective OpenMP code
    /// without knowing what runtime to target.
    OMPRT_Unknown,

    /// The LLVM OpenMP runtime. When completed and integrated, this will become
    /// the default for Clang.
    OMPRT_OMP,

    /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for
    /// this runtime but can swallow the pragmas, and find and link against the
    /// runtime library itself.
    OMPRT_GOMP,

    /// The legacy name for the LLVM OpenMP runtime from when it was the Intel
    /// OpenMP runtime. We support this mode for users with existing
    /// dependencies on this runtime library name.
    OMPRT_IOMP5
  };

  // Diag - Forwarding function for diagnostics.
  DiagnosticBuilder Diag(unsigned DiagID) const {
    return Diags.Report(DiagID);
  }

  // FIXME: Privatize once interface is stable.
public:
  /// The name the driver was invoked as.
  std::string Name;

  /// The path the driver executable was in, as invoked from the
  /// command line.
  std::string Dir;

  /// The original path to the clang executable.
  std::string ClangExecutable;

  /// Target and driver mode components extracted from clang executable name.
  ParsedClangName ClangNameParts;

  /// The path to the installed clang directory, if any.
  std::string InstalledDir;

  /// The path to the compiler resource directory.
  std::string ResourceDir;

  /// System directory for config files.
  std::string SystemConfigDir;

  /// User directory for config files.
  std::string UserConfigDir;

  /// A prefix directory used to emulate a limited subset of GCC's '-Bprefix'
  /// functionality.
  /// FIXME: This type of customization should be removed in favor of the
  /// universal driver when it is ready.
  typedef SmallVector<std::string, 4> prefix_list;
  prefix_list PrefixDirs;

  /// sysroot, if present
  std::string SysRoot;

  /// Dynamic loader prefix, if present
  std::string DyldPrefix;

  /// Driver title to use with help.
  std::string DriverTitle;

  /// Information about the host which can be overridden by the user.
  std::string HostBits, HostMachine, HostSystem, HostRelease;

  /// The file to log CC_PRINT_PROC_STAT_FILE output to, if enabled.
  std::string CCPrintStatReportFilename;

  /// The file to log CC_PRINT_OPTIONS output to, if enabled.
  std::string CCPrintOptionsFilename;

  /// The file to log CC_PRINT_HEADERS output to, if enabled.
  std::string CCPrintHeadersFilename;

  /// The file to log CC_LOG_DIAGNOSTICS output to, if enabled.
  std::string CCLogDiagnosticsFilename;

  /// An input type and its arguments.
  using InputTy = std::pair<types::ID, const llvm::opt::Arg *>;

  /// A list of inputs and their types for the given arguments.
  using InputList = SmallVector<InputTy, 16>;

  /// Whether the driver should follow g++ like behavior.
  bool CCCIsCXX() const { return Mode == GXXMode; }

  /// Whether the driver is just the preprocessor.
  bool CCCIsCPP() const { return Mode == CPPMode; }

  /// Whether the driver should follow gcc like behavior.
  bool CCCIsCC() const { return Mode == GCCMode; }

  /// Whether the driver should follow cl.exe like behavior.
  bool IsCLMode() const { return Mode == CLMode; }

  /// Whether the driver should invoke flang for fortran inputs.
  /// Other modes fall back to calling gcc which in turn calls gfortran.
  bool IsFlangMode() const { return Mode == FlangMode; }

  /// Whether the driver should follow dxc.exe like behavior.
  bool IsDXCMode() const { return Mode == DXCMode; }

  /// Only print tool bindings, don't build any jobs.
  unsigned CCCPrintBindings : 1;

  /// Set CC_PRINT_OPTIONS mode, which is like -v but logs the commands to
  /// CCPrintOptionsFilename or to stderr.
  unsigned CCPrintOptions : 1;

  /// Set CC_PRINT_HEADERS mode, which causes the frontend to log header include
  /// information to CCPrintHeadersFilename or to stderr.
  unsigned CCPrintHeaders : 1;

  /// Set CC_LOG_DIAGNOSTICS mode, which causes the frontend to log diagnostics
  /// to CCLogDiagnosticsFilename or to stderr, in a stable machine readable
  /// format.
  unsigned CCLogDiagnostics : 1;

  /// Whether the driver is generating diagnostics for debugging purposes.
  unsigned CCGenDiagnostics : 1;

  /// Set CC_PRINT_PROC_STAT mode, which causes the driver to dump
  /// performance report to CC_PRINT_PROC_STAT_FILE or to stdout.
  unsigned CCPrintProcessStats : 1;

  /// Pointer to the ExecuteCC1Tool function, if available.
  /// When the clangDriver lib is used through clang.exe, this provides a
  /// shortcut for executing the -cc1 command-line directly, in the same
  /// process.
  typedef int (*CC1ToolFunc)(SmallVectorImpl<const char *> &ArgV);
  CC1ToolFunc CC1Main = nullptr;

private:
  /// Raw target triple.
  std::string TargetTriple;

  /// Name to use when invoking gcc/g++.
  std::string CCCGenericGCCName;

  /// Paths to configuration files used.
  std::vector<std::string> ConfigFiles;

  /// Allocator for string saver.
  llvm::BumpPtrAllocator Alloc;

  /// Object that stores strings read from configuration file.
  llvm::StringSaver Saver;

  /// Arguments originated from configuration file.
  std::unique_ptr<llvm::opt::InputArgList> CfgOptions;

  /// Arguments originated from command line.
  std::unique_ptr<llvm::opt::InputArgList> CLOptions;

  /// Whether to check that input files exist when constructing compilation
  /// jobs.
  unsigned CheckInputsExist : 1;
  /// Whether to probe for PCH files on disk, in order to upgrade
  /// -include foo.h to -include-pch foo.h.pch.
  unsigned ProbePrecompiled : 1;

public:
  // getFinalPhase - Determine which compilation mode we are in and record
  // which option we used to determine the final phase.
  // TODO: Much of what getFinalPhase returns are not actually true compiler
  //       modes. Fold this functionality into Types::getCompilationPhases and
  //       handleArguments.
  phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
                           llvm::opt::Arg **FinalPhaseArg = nullptr) const;

private:
  /// Certain options suppress the 'no input files' warning.
  unsigned SuppressMissingInputWarning : 1;

  /// Cache of all the ToolChains in use by the driver.
  ///
  /// This maps from the string representation of a triple to a ToolChain
  /// created targeting that triple. The driver owns all the ToolChain objects
  /// stored in it, and will clean them up when torn down.
  mutable llvm::StringMap<std::unique_ptr<ToolChain>> ToolChains;

  /// Cache of known offloading architectures for the ToolChain already derived.
  /// This should only be modified when we first initialize the offloading
  /// toolchains.
  llvm::DenseMap<const ToolChain *, llvm::DenseSet<llvm::StringRef>> KnownArchs;

private:
  /// TranslateInputArgs - Create a new derived argument list from the input
  /// arguments, after applying the standard argument translations.
  llvm::opt::DerivedArgList *
  TranslateInputArgs(const llvm::opt::InputArgList &Args) const;

  // handleArguments - All code related to claiming and printing diagnostics
  // related to arguments to the driver are done here.
  void handleArguments(Compilation &C, llvm::opt::DerivedArgList &Args,
                       const InputList &Inputs, ActionList &Actions) const;

  // Before executing jobs, sets up response files for commands that need them.
  void setUpResponseFiles(Compilation &C, Command &Cmd);

  void generatePrefixedToolNames(StringRef Tool, const ToolChain &TC,
                                 SmallVectorImpl<std::string> &Names) const;

  /// Find the appropriate .crash diagonostic file for the child crash
  /// under this driver and copy it out to a temporary destination with the
  /// other reproducer related files (.sh, .cache, etc). If not found, suggest a
  /// directory for the user to look at.
  ///
  /// \param ReproCrashFilename The file path to copy the .crash to.
  /// \param CrashDiagDir       The suggested directory for the user to look at
  ///                           in case the search or copy fails.
  ///
  /// \returns If the .crash is found and successfully copied return true,
  /// otherwise false and return the suggested directory in \p CrashDiagDir.
  bool getCrashDiagnosticFile(StringRef ReproCrashFilename,
                              SmallString<128> &CrashDiagDir);

public:

  /// Takes the path to a binary that's either in bin/ or lib/ and returns
  /// the path to clang's resource directory.
  static std::string GetResourcesPath(StringRef BinaryPath,
                                      StringRef CustomResourceDir = "");

  Driver(StringRef ClangExecutable, StringRef TargetTriple,
         DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
         IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);

  /// @name Accessors
  /// @{

  /// Name to use when invoking gcc/g++.
  const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }

  llvm::ArrayRef<std::string> getConfigFiles() const {
    return ConfigFiles;
  }

  const llvm::opt::OptTable &getOpts() const { return getDriverOptTable(); }

  DiagnosticsEngine &getDiags() const { return Diags; }

  llvm::vfs::FileSystem &getVFS() const { return *VFS; }

  bool getCheckInputsExist() const { return CheckInputsExist; }

  void setCheckInputsExist(bool Value) { CheckInputsExist = Value; }

  bool getProbePrecompiled() const { return ProbePrecompiled; }
  void setProbePrecompiled(bool Value) { ProbePrecompiled = Value; }

  void setTargetAndMode(const ParsedClangName &TM) { ClangNameParts = TM; }

  const std::string &getTitle() { return DriverTitle; }
  void setTitle(std::string Value) { DriverTitle = std::move(Value); }

  std::string getTargetTriple() const { return TargetTriple; }

  /// Get the path to the main clang executable.
  const char *getClangProgramPath() const {
    return ClangExecutable.c_str();
  }

  /// Get the path to where the clang executable was installed.
  const char *getInstalledDir() const {
    if (!InstalledDir.empty())
      return InstalledDir.c_str();
    return Dir.c_str();
  }
  void setInstalledDir(StringRef Value) { InstalledDir = std::string(Value); }

  bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; }
  bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; }

  bool embedBitcodeEnabled() const { return BitcodeEmbed != EmbedNone; }
  bool embedBitcodeInObject() const { return (BitcodeEmbed == EmbedBitcode); }
  bool embedBitcodeMarkerOnly() const { return (BitcodeEmbed == EmbedMarker); }

  bool offloadHostOnly() const { return Offload == OffloadHost; }
  bool offloadDeviceOnly() const { return Offload == OffloadDevice; }

  /// Compute the desired OpenMP runtime from the flags provided.
  OpenMPRuntimeKind getOpenMPRuntime(const llvm::opt::ArgList &Args) const;

  /// @}
  /// @name Primary Functionality
  /// @{

  /// CreateOffloadingDeviceToolChains - create all the toolchains required to
  /// support offloading devices given the programming models specified in the
  /// current compilation. Also, update the host tool chain kind accordingly.
  void CreateOffloadingDeviceToolChains(Compilation &C, InputList &Inputs);

  /// BuildCompilation - Construct a compilation object for a command
  /// line argument vector.
  ///
  /// \return A compilation, or 0 if none was built for the given
  /// argument vector. A null return value does not necessarily
  /// indicate an error condition, the diagnostics should be queried
  /// to determine if an error occurred.
  Compilation *BuildCompilation(ArrayRef<const char *> Args);

  /// ParseArgStrings - Parse the given list of strings into an
  /// ArgList.
  llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args,
                                          bool IsClCompatMode,
                                          bool &ContainsError);

  /// BuildInputs - Construct the list of inputs and their types from
  /// the given arguments.
  ///
  /// \param TC - The default host tool chain.
  /// \param Args - The input arguments.
  /// \param Inputs - The list to store the resulting compilation
  /// inputs onto.
  void BuildInputs(const ToolChain &TC, llvm::opt::DerivedArgList &Args,
                   InputList &Inputs) const;

  /// BuildActions - Construct the list of actions to perform for the
  /// given arguments, which are only done for a single architecture.
  ///
  /// \param C - The compilation that is being built.
  /// \param Args - The input arguments.
  /// \param Actions - The list to store the resulting actions onto.
  void BuildActions(Compilation &C, llvm::opt::DerivedArgList &Args,
                    const InputList &Inputs, ActionList &Actions) const;

  /// BuildUniversalActions - Construct the list of actions to perform
  /// for the given arguments, which may require a universal build.
  ///
  /// \param C - The compilation that is being built.
  /// \param TC - The default host tool chain.
  void BuildUniversalActions(Compilation &C, const ToolChain &TC,
                             const InputList &BAInputs) const;

  /// BuildOffloadingActions - Construct the list of actions to perform for the
  /// offloading toolchain that will be embedded in the host.
  ///
  /// \param C - The compilation that is being built.
  /// \param Args - The input arguments.
  /// \param Input - The input type and arguments
  /// \param HostAction - The host action used in the offloading toolchain.
  Action *BuildOffloadingActions(Compilation &C,
                                 llvm::opt::DerivedArgList &Args,
                                 const InputTy &Input,
                                 Action *HostAction) const;

  /// Returns the set of bound architectures active for this offload kind.
  /// If there are no bound architctures we return a set containing only the
  /// empty string.
  llvm::DenseSet<StringRef>
  getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
                  Action::OffloadKind Kind, const ToolChain *TC) const;

  /// Check that the file referenced by Value exists. If it doesn't,
  /// issue a diagnostic and return false.
  /// If TypoCorrect is true and the file does not exist, see if it looks
  /// like a likely typo for a flag and if so print a "did you mean" blurb.
  bool DiagnoseInputExistence(const llvm::opt::DerivedArgList &Args,
                              StringRef Value, types::ID Ty,
                              bool TypoCorrect) const;

  /// BuildJobs - Bind actions to concrete tools and translate
  /// arguments to form the list of jobs to run.
  ///
  /// \param C - The compilation that is being built.
  void BuildJobs(Compilation &C) const;

  /// ExecuteCompilation - Execute the compilation according to the command line
  /// arguments and return an appropriate exit code.
  ///
  /// This routine handles additional processing that must be done in addition
  /// to just running the subprocesses, for example reporting errors, setting
  /// up response files, removing temporary files, etc.
  int ExecuteCompilation(Compilation &C,
     SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands);

  /// Contains the files in the compilation diagnostic report generated by
  /// generateCompilationDiagnostics.
  struct CompilationDiagnosticReport {
    llvm::SmallVector<std::string, 4> TemporaryFiles;
  };

  /// generateCompilationDiagnostics - Generate diagnostics information
  /// including preprocessed source file(s).
  ///
  void generateCompilationDiagnostics(
      Compilation &C, const Command &FailingCommand,
      StringRef AdditionalInformation = "",
      CompilationDiagnosticReport *GeneratedReport = nullptr);

  enum class CommandStatus {
    Crash = 1,
    Error,
    Ok,
  };

  enum class ReproLevel {
    Off = 0,
    OnCrash = static_cast<int>(CommandStatus::Crash),
    OnError = static_cast<int>(CommandStatus::Error),
    Always = static_cast<int>(CommandStatus::Ok),
  };

  bool maybeGenerateCompilationDiagnostics(
      CommandStatus CS, ReproLevel Level, Compilation &C,
      const Command &FailingCommand, StringRef AdditionalInformation = "",
      CompilationDiagnosticReport *GeneratedReport = nullptr) {
    if (static_cast<int>(CS) > static_cast<int>(Level))
      return false;
    if (CS != CommandStatus::Crash)
      Diags.Report(diag::err_drv_force_crash)
          << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH");
    // Hack to ensure that diagnostic notes get emitted.
    Diags.setLastDiagnosticIgnored(false);
    generateCompilationDiagnostics(C, FailingCommand, AdditionalInformation,
                                   GeneratedReport);
    return true;
  }

  /// @}
  /// @name Helper Methods
  /// @{

  /// PrintActions - Print the list of actions.
  void PrintActions(const Compilation &C) const;

  /// PrintHelp - Print the help text.
  ///
  /// \param ShowHidden - Show hidden options.
  void PrintHelp(bool ShowHidden) const;

  /// PrintVersion - Print the driver version.
  void PrintVersion(const Compilation &C, raw_ostream &OS) const;

  /// GetFilePath - Lookup \p Name in the list of file search paths.
  ///
  /// \param TC - The tool chain for additional information on
  /// directories to search.
  //
  // FIXME: This should be in CompilationInfo.
  std::string GetFilePath(StringRef Name, const ToolChain &TC) const;

  /// GetProgramPath - Lookup \p Name in the list of program search paths.
  ///
  /// \param TC - The provided tool chain for additional information on
  /// directories to search.
  //
  // FIXME: This should be in CompilationInfo.
  std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;

  /// HandleAutocompletions - Handle --autocomplete by searching and printing
  /// possible flags, descriptions, and its arguments.
  void HandleAutocompletions(StringRef PassedFlags) const;

  /// HandleImmediateArgs - Handle any arguments which should be
  /// treated before building actions or binding tools.
  ///
  /// \return Whether any compilation should be built for this
  /// invocation.
  bool HandleImmediateArgs(const Compilation &C);

  /// ConstructAction - Construct the appropriate action to do for
  /// \p Phase on the \p Input, taking in to account arguments
  /// like -fsyntax-only or --analyze.
  Action *ConstructPhaseAction(
      Compilation &C, const llvm::opt::ArgList &Args, phases::ID Phase,
      Action *Input,
      Action::OffloadKind TargetDeviceOffloadKind = Action::OFK_None) const;

  /// BuildJobsForAction - Construct the jobs to perform for the action \p A and
  /// return an InputInfo for the result of running \p A.  Will only construct
  /// jobs for a given (Action, ToolChain, BoundArch, DeviceKind) tuple once.
  InputInfoList BuildJobsForAction(
      Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
      bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
      std::map<std::pair<const Action *, std::string>, InputInfoList>
          &CachedResults,
      Action::OffloadKind TargetDeviceOffloadKind) const;

  /// Returns the default name for linked images (e.g., "a.out").
  const char *getDefaultImageName() const;

  // Creates a temp file with $Prefix-%%%%%%.$Suffix
  const char *CreateTempFile(Compilation &C, StringRef Prefix, StringRef Suffix,
                             bool MultipleArchs = false,
                             StringRef BoundArch = {}) const;

  /// GetNamedOutputPath - Return the name to use for the output of
  /// the action \p JA. The result is appended to the compilation's
  /// list of temporary or result files, as appropriate.
  ///
  /// \param C - The compilation.
  /// \param JA - The action of interest.
  /// \param BaseInput - The original input file that this action was
  /// triggered by.
  /// \param BoundArch - The bound architecture.
  /// \param AtTopLevel - Whether this is a "top-level" action.
  /// \param MultipleArchs - Whether multiple -arch options were supplied.
  /// \param NormalizedTriple - The normalized triple of the relevant target.
  const char *GetNamedOutputPath(Compilation &C, const JobAction &JA,
                                 const char *BaseInput, StringRef BoundArch,
                                 bool AtTopLevel, bool MultipleArchs,
                                 StringRef NormalizedTriple) const;

  /// GetTemporaryPath - Return the pathname of a temporary file to use
  /// as part of compilation; the file will have the given prefix and suffix.
  ///
  /// GCC goes to extra lengths here to be a bit more robust.
  std::string GetTemporaryPath(StringRef Prefix, StringRef Suffix) const;

  /// GetTemporaryDirectory - Return the pathname of a temporary directory to
  /// use as part of compilation; the directory will have the given prefix.
  std::string GetTemporaryDirectory(StringRef Prefix) const;

  /// Return the pathname of the pch file in clang-cl mode.
  std::string GetClPchPath(Compilation &C, StringRef BaseName) const;

  /// ShouldUseClangCompiler - Should the clang compiler be used to
  /// handle this action.
  bool ShouldUseClangCompiler(const JobAction &JA) const;

  /// ShouldUseFlangCompiler - Should the flang compiler be used to
  /// handle this action.
  bool ShouldUseFlangCompiler(const JobAction &JA) const;

  /// ShouldEmitStaticLibrary - Should the linker emit a static library.
  bool ShouldEmitStaticLibrary(const llvm::opt::ArgList &Args) const;

  /// Returns true if the user has indicated a C++20 header unit mode.
  bool hasHeaderMode() const { return CXX20HeaderType != HeaderMode_None; }

  /// Get the mode for handling headers as set by fmodule-header{=}.
  ModuleHeaderMode getModuleHeaderMode() const { return CXX20HeaderType; }

  /// Returns true if we are performing any kind of LTO.
  bool isUsingLTO(bool IsOffload = false) const {
    return getLTOMode(IsOffload) != LTOK_None;
  }

  /// Get the specific kind of LTO being performed.
  LTOKind getLTOMode(bool IsOffload = false) const {
    return IsOffload ? OffloadLTOMode : LTOMode;
  }

private:

  /// Tries to load options from configuration files.
  ///
  /// \returns true if error occurred.
  bool loadConfigFiles();

  /// Tries to load options from default configuration files (deduced from
  /// executable filename).
  ///
  /// \returns true if error occurred.
  bool loadDefaultConfigFiles(ArrayRef<StringRef> CfgFileSearchDirs);

  /// Read options from the specified file.
  ///
  /// \param [in] FileName File to read.
  /// \returns true, if error occurred while reading.
  bool readConfigFile(StringRef FileName);

  /// Set the driver mode (cl, gcc, etc) from the value of the `--driver-mode`
  /// option.
  void setDriverMode(StringRef DriverModeValue);

  /// Parse the \p Args list for LTO options and record the type of LTO
  /// compilation based on which -f(no-)?lto(=.*)? option occurs last.
  void setLTOMode(const llvm::opt::ArgList &Args);

  /// Retrieves a ToolChain for a particular \p Target triple.
  ///
  /// Will cache ToolChains for the life of the driver object, and create them
  /// on-demand.
  const ToolChain &getToolChain(const llvm::opt::ArgList &Args,
                                const llvm::Triple &Target) const;

  /// @}

  /// Retrieves a ToolChain for a particular device \p Target triple
  ///
  /// \param[in] HostTC is the host ToolChain paired with the device
  ///
  /// \param[in] TargetDeviceOffloadKind (e.g. OFK_Cuda/OFK_OpenMP/OFK_SYCL) is
  /// an Offloading action that is optionally passed to a ToolChain (used by
  /// CUDA, to specify if it's used in conjunction with OpenMP)
  ///
  /// Will cache ToolChains for the life of the driver object, and create them
  /// on-demand.
  const ToolChain &getOffloadingDeviceToolChain(
      const llvm::opt::ArgList &Args, const llvm::Triple &Target,
      const ToolChain &HostTC,
      const Action::OffloadKind &TargetDeviceOffloadKind) const;

  /// Get bitmasks for which option flags to include and exclude based on
  /// the driver mode.
  std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const;

  /// Helper used in BuildJobsForAction.  Doesn't use the cache when building
  /// jobs specifically for the given action, but will use the cache when
  /// building jobs for the Action's inputs.
  InputInfoList BuildJobsForActionNoCache(
      Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
      bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
      std::map<std::pair<const Action *, std::string>, InputInfoList>
          &CachedResults,
      Action::OffloadKind TargetDeviceOffloadKind) const;

  /// Return the typical executable name for the specified driver \p Mode.
  static const char *getExecutableForDriverMode(DriverMode Mode);

public:
  /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
  /// return the grouped values as integers. Numbers which are not
  /// provided are set to 0.
  ///
  /// \return True if the entire string was parsed (9.2), or all
  /// groups were parsed (10.3.5extrastuff). HadExtra is true if all
  /// groups were parsed but extra characters remain at the end.
  static bool GetReleaseVersion(StringRef Str, unsigned &Major, unsigned &Minor,
                                unsigned &Micro, bool &HadExtra);

  /// Parse digits from a string \p Str and fulfill \p Digits with
  /// the parsed numbers. This method assumes that the max number of
  /// digits to look for is equal to Digits.size().
  ///
  /// \return True if the entire string was parsed and there are
  /// no extra characters remaining at the end.
  static bool GetReleaseVersion(StringRef Str,
                                MutableArrayRef<unsigned> Digits);
  /// Compute the default -fmodule-cache-path.
  /// \return True if the system provides a default cache directory.
  static bool getDefaultModuleCachePath(SmallVectorImpl<char> &Result);
};

/// \return True if the last defined optimization level is -Ofast.
/// And False otherwise.
bool isOptimizationLevelFast(const llvm::opt::ArgList &Args);

/// \return True if the argument combination will end up generating remarks.
bool willEmitRemarks(const llvm::opt::ArgList &Args);

/// Returns the driver mode option's value, i.e. `X` in `--driver-mode=X`. If \p
/// Args doesn't mention one explicitly, tries to deduce from `ProgName`.
/// Returns empty on failure.
/// Common values are "gcc", "g++", "cpp", "cl" and "flang". Returned value need
/// not be one of these.
llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef<const char *> Args);

/// Checks whether the value produced by getDriverMode is for CL mode.
bool IsClangCL(StringRef DriverMode);

} // end namespace driver
} // end namespace clang

#endif
