//===- CompilerInvocation.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
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#include "flang/Frontend/CompilerInvocation.h"
#include "flang/Frontend/CodeGenOptions.h"
#include "flang/Frontend/PreprocessorOptions.h"
#include "flang/Frontend/TargetOptions.h"
#include "flang/Optimizer/Passes/CommandLineOpts.h"
#include "flang/Semantics/semantics.h"
#include "flang/Support/Fortran-features.h"
#include "flang/Support/OpenMP-features.h"
#include "flang/Support/Version.h"
#include "flang/Tools/TargetSetup.h"
#include "flang/Version.inc"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/CommonArgs.h"
#include "clang/Driver/Driver.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Frontend/Debug/Options.h"
#include "llvm/Frontend/Driver/CodeGenOptions.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cstdlib>
#include <limits>
#include <memory>
#include <optional>

using namespace Fortran::frontend;

//===----------------------------------------------------------------------===//
// Initialization.
//===----------------------------------------------------------------------===//
CompilerInvocationBase::CompilerInvocationBase()
    : diagnosticOpts(new clang::DiagnosticOptions()),
      preprocessorOpts(new PreprocessorOptions()) {}

CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &x)
    : diagnosticOpts(new clang::DiagnosticOptions(x.getDiagnosticOpts())),
      preprocessorOpts(new PreprocessorOptions(x.getPreprocessorOpts())) {}

CompilerInvocationBase::~CompilerInvocationBase() = default;

//===----------------------------------------------------------------------===//
// Deserialization (from args)
//===----------------------------------------------------------------------===//
static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
                                bool defaultColor = true) {
  // Color diagnostics default to auto ("on" if terminal supports) in the
  // compiler driver `flang` but default to off in the frontend driver
  // `flang -fc1`, needing an explicit OPT_fdiagnostics_color.
  // Support both clang's -f[no-]color-diagnostics and gcc's
  // -f[no-]diagnostics-colors[=never|always|auto].
  enum {
    Colors_On,
    Colors_Off,
    Colors_Auto
  } showColors = defaultColor ? Colors_Auto : Colors_Off;

  for (auto *a : args) {
    const llvm::opt::Option &opt = a->getOption();
    if (opt.matches(clang::options::OPT_fcolor_diagnostics)) {
      showColors = Colors_On;
    } else if (opt.matches(clang::options::OPT_fno_color_diagnostics)) {
      showColors = Colors_Off;
    } else if (opt.matches(clang::options::OPT_fdiagnostics_color_EQ)) {
      llvm::StringRef value(a->getValue());
      if (value == "always")
        showColors = Colors_On;
      else if (value == "never")
        showColors = Colors_Off;
      else if (value == "auto")
        showColors = Colors_Auto;
    }
  }

  return showColors == Colors_On ||
         (showColors == Colors_Auto &&
          llvm::sys::Process::StandardErrHasColors());
}

/// Extracts the optimisation level from \a args.
static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
                                     clang::DiagnosticsEngine &diags) {
  unsigned defaultOpt = 0;

  if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_O_Group)) {
    if (a->getOption().matches(clang::options::OPT_O0))
      return 0;

    assert(a->getOption().matches(clang::options::OPT_O));

    return getLastArgIntValue(args, clang::options::OPT_O, defaultOpt, diags);
  }

  return defaultOpt;
}

bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
                                            llvm::opt::ArgList &args) {
  opts.setShowColors(parseShowColorsArgs(args) ? clang::ShowColorsKind::On
                                               : clang::ShowColorsKind::Off);

  return true;
}

static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
                           llvm::opt::ArgList &args,
                           clang::DiagnosticsEngine &diags) {
  using DebugInfoKind = llvm::codegenoptions::DebugInfoKind;
  if (llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_debug_info_kind_EQ)) {
    std::optional<DebugInfoKind> val =
        llvm::StringSwitch<std::optional<DebugInfoKind>>(arg->getValue())
            .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
            .Case("line-directives-only",
                  llvm::codegenoptions::DebugDirectivesOnly)
            .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)
            .Case("limited", llvm::codegenoptions::LimitedDebugInfo)
            .Case("standalone", llvm::codegenoptions::FullDebugInfo)
            .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)
            .Default(std::nullopt);
    if (!val.has_value()) {
      diags.Report(clang::diag::err_drv_invalid_value)
          << arg->getAsString(args) << arg->getValue();
      return false;
    }
    opts.setDebugInfo(val.value());
    if (val != llvm::codegenoptions::DebugLineTablesOnly &&
        val != llvm::codegenoptions::DebugDirectivesOnly &&
        val != llvm::codegenoptions::FullDebugInfo &&
        val != llvm::codegenoptions::NoDebugInfo) {
      const auto debugWarning = diags.getCustomDiagID(
          clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0");
      diags.Report(debugWarning) << arg->getValue();
    }
    opts.DwarfVersion =
        getLastArgIntValue(args, clang::options::OPT_dwarf_version_EQ,
                           /*Default=*/0, diags);
    if (const llvm::opt::Arg *a =
            args.getLastArg(clang::options::OPT_split_dwarf_file))
      opts.SplitDwarfFile = a->getValue();
    if (const llvm::opt::Arg *a =
            args.getLastArg(clang::options::OPT_split_dwarf_output))
      opts.SplitDwarfOutput = a->getValue();
  }

  if (const llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_dwarf_debug_flags))
    opts.DwarfDebugFlags = arg->getValue();

  opts.DebugInfoForProfiling =
      args.hasArg(clang::options::OPT_fdebug_info_for_profiling);

  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_compress_debug_sections_EQ)) {
    auto type = llvm::StringSwitch<std::optional<llvm::DebugCompressionType>>(
                    a->getValue())
                    .Case("none", llvm::DebugCompressionType::None)
                    .Case("zlib", llvm::DebugCompressionType::Zlib)
                    .Case("zstd", llvm::DebugCompressionType::Zstd)
                    .Default(std::nullopt);
    if (type) {
      opts.setCompressDebugSections(*type);
    } else {
      diags.Report(clang::diag::err_drv_invalid_value)
          << a->getAsString(args) << a->getValue();
      return false;
    }
  }

  return true;
}

static bool parseDoConcurrentMapping(Fortran::frontend::CodeGenOptions &opts,
                                     llvm::opt::ArgList &args,
                                     clang::DiagnosticsEngine &diags) {
  llvm::opt::Arg *arg =
      args.getLastArg(clang::options::OPT_fdo_concurrent_to_openmp_EQ);
  if (!arg)
    return true;

  using DoConcurrentMappingKind =
      Fortran::frontend::CodeGenOptions::DoConcurrentMappingKind;
  std::optional<DoConcurrentMappingKind> val =
      llvm::StringSwitch<std::optional<DoConcurrentMappingKind>>(
          arg->getValue())
          .Case("none", DoConcurrentMappingKind::DCMK_None)
          .Case("host", DoConcurrentMappingKind::DCMK_Host)
          .Case("device", DoConcurrentMappingKind::DCMK_Device)
          .Default(std::nullopt);

  if (!val.has_value()) {
    diags.Report(clang::diag::err_drv_invalid_value)
        << arg->getAsString(args) << arg->getValue();
    return false;
  }

  opts.setDoConcurrentMapping(val.value());
  return true;
}

static bool parseVectorLibArg(Fortran::frontend::CodeGenOptions &opts,
                              llvm::opt::ArgList &args,
                              clang::DiagnosticsEngine &diags) {
  llvm::opt::Arg *arg = args.getLastArg(clang::options::OPT_fveclib);
  if (!arg)
    return true;

  using VectorLibrary = llvm::driver::VectorLibrary;
  std::optional<VectorLibrary> val =
      llvm::StringSwitch<std::optional<VectorLibrary>>(arg->getValue())
          .Case("Accelerate", VectorLibrary::Accelerate)
          .Case("libmvec", VectorLibrary::LIBMVEC)
          .Case("MASSV", VectorLibrary::MASSV)
          .Case("SVML", VectorLibrary::SVML)
          .Case("SLEEF", VectorLibrary::SLEEF)
          .Case("Darwin_libsystem_m", VectorLibrary::Darwin_libsystem_m)
          .Case("ArmPL", VectorLibrary::ArmPL)
          .Case("AMDLIBM", VectorLibrary::AMDLIBM)
          .Case("NoLibrary", VectorLibrary::NoLibrary)
          .Default(std::nullopt);
  if (!val.has_value()) {
    diags.Report(clang::diag::err_drv_invalid_value)
        << arg->getAsString(args) << arg->getValue();
    return false;
  }
  opts.setVecLib(val.value());
  return true;
}

// Generate an OptRemark object containing info on if the -Rgroup
// specified is enabled or not.
static CodeGenOptions::OptRemark
parseOptimizationRemark(clang::DiagnosticsEngine &diags,
                        llvm::opt::ArgList &args, llvm::opt::OptSpecifier optEq,
                        llvm::StringRef remarkOptName) {
  assert((remarkOptName == "pass" || remarkOptName == "pass-missed" ||
          remarkOptName == "pass-analysis") &&
         "Unsupported remark option name provided.");
  CodeGenOptions::OptRemark result;

  for (llvm::opt::Arg *a : args) {
    if (a->getOption().matches(clang::options::OPT_R_Joined)) {
      llvm::StringRef value = a->getValue();

      if (value == remarkOptName) {
        result.Kind = CodeGenOptions::RemarkKind::RK_Enabled;
        // Enable everything
        result.Pattern = ".*";
        result.Regex = std::make_shared<llvm::Regex>(result.Pattern);

      } else if (value.split('-') ==
                 std::make_pair(llvm::StringRef("no"), remarkOptName)) {
        result.Kind = CodeGenOptions::RemarkKind::RK_Disabled;
        // Disable everything
        result.Pattern = "";
        result.Regex = nullptr;
      }
    } else if (a->getOption().matches(optEq)) {
      result.Kind = CodeGenOptions::RemarkKind::RK_WithPattern;
      result.Pattern = a->getValue();
      result.Regex = std::make_shared<llvm::Regex>(result.Pattern);
      std::string regexError;

      if (!result.Regex->isValid(regexError)) {
        diags.Report(clang::diag::err_drv_optimization_remark_pattern)
            << regexError << a->getAsString(args);
        return CodeGenOptions::OptRemark();
      }
    }
  }
  return result;
}

static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
                             llvm::opt::ArgList &args,
                             clang::DiagnosticsEngine &diags) {
  opts.OptimizationLevel = getOptimizationLevel(args, diags);

  if (args.hasFlag(clang::options::OPT_fdebug_pass_manager,
                   clang::options::OPT_fno_debug_pass_manager, false))
    opts.DebugPassManager = 1;

  if (!args.hasFlag(clang::options::OPT_fprotect_parens,
                    clang::options::OPT_fno_protect_parens, true))
    opts.ProtectParens = 0;

  if (args.hasFlag(clang::options::OPT_fstack_arrays,
                   clang::options::OPT_fno_stack_arrays, false))
    opts.StackArrays = 1;

  if (args.hasFlag(clang::options::OPT_fsafe_trampoline,
                   clang::options::OPT_fno_safe_trampoline, false))
    opts.EnableSafeTrampoline = 1;

  if (args.hasFlag(clang::options::OPT_ffp_sum_reassociation,
                   clang::options::OPT_fno_fp_sum_reassociation, true))
    opts.SplitSumExpressionTree = 1;

  // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
  // which enables the pass whenever the optimization pipeline runs.
  opts.InterchangeLoops =
      args.hasFlag(clang::options::OPT_floop_interchange,
                   clang::options::OPT_fno_loop_interchange, true);

  if (args.hasArg(clang::options::OPT_funique_internal_linkage_names))
    opts.UniqueInternalLinkageNames = 1;

  if (args.getLastArg(clang::options::OPT_fexperimental_loop_fusion))
    opts.FuseLoops = 1;

  if (args.getLastArg(clang::options::OPT_vectorize_loops))
    opts.VectorizeLoop = 1;

  if (args.getLastArg(clang::options::OPT_vectorize_slp))
    opts.VectorizeSLP = 1;

  if (args.hasFlag(clang::options::OPT_floop_versioning,
                   clang::options::OPT_fno_loop_versioning, false))
    opts.LoopVersioning = 1;

  opts.UnrollLoops = args.hasFlag(clang::options::OPT_funroll_loops,
                                  clang::options::OPT_fno_unroll_loops,
                                  (opts.OptimizationLevel > 1));

  opts.AliasAnalysis = opts.OptimizationLevel > 0;

  // -mframe-pointer=none/non-leaf/reserved/all option.
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_mframe_pointer_EQ)) {
    std::optional<llvm::FramePointerKind> val =
        llvm::StringSwitch<std::optional<llvm::FramePointerKind>>(a->getValue())
            .Case("none", llvm::FramePointerKind::None)
            .Case("non-leaf", llvm::FramePointerKind::NonLeaf)
            .Case("non-leaf-no-reserve",
                  llvm::FramePointerKind::NonLeafNoReserve)
            .Case("reserved", llvm::FramePointerKind::Reserved)
            .Case("all", llvm::FramePointerKind::All)
            .Default(std::nullopt);

    if (!val.has_value()) {
      diags.Report(clang::diag::err_drv_invalid_value)
          << a->getAsString(args) << a->getValue();
    } else
      opts.setFramePointer(val.value());
  }

  for (auto *a : args.filtered(clang::options::OPT_fpass_plugin_EQ))
    opts.LLVMPassPlugins.push_back(a->getValue());

  opts.Reciprocals = clang::parseMRecipOption(diags, args);

  opts.PreferVectorWidth = clang::parseMPreferVectorWidthOption(diags, args);

  // -fembed-offload-object option
  for (auto *a : args.filtered(clang::options::OPT_fembed_offload_object_EQ))
    opts.OffloadObjects.push_back(a->getValue());

  if (args.hasArg(clang::options::OPT_finstrument_functions))
    opts.InstrumentFunctions = 1;

  if (args.hasArg(clang::options::OPT_fno_optimize_sibling_calls))
    opts.DisableTailCalls = 1;

  // -fno-integrated-as: emit GNU Assembler compatible assembly.
  if (!args.hasFlag(clang::options::OPT_fintegrated_as,
                    clang::options::OPT_fno_integrated_as, true))
    opts.DisableIntegratedAS = 1;

  opts.FunctionSections =
      args.hasFlag(clang::options::OPT_ffunction_sections,
                   clang::options::OPT_fno_function_sections,
                   /*Default=*/false);
  opts.DataSections = args.hasFlag(clang::options::OPT_fdata_sections,
                                   clang::options::OPT_fno_data_sections,
                                   /*Default=*/false);

  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_mcode_object_version_EQ)) {
    llvm::StringRef s = a->getValue();
    if (s == "6")
      opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_6;
    if (s == "5")
      opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_5;
    if (s == "4")
      opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_4;
    if (s == "none")
      opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_None;
  }

  // -f[no-]save-optimization-record[=<format>]
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_opt_record_file))
    opts.OptRecordFile = a->getValue();

  // Optimization file format. Defaults to yaml
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_opt_record_format))
    opts.OptRecordFormat = a->getValue();

  // Specifies, using a regex, which successful optimization passes(middle and
  // backend), to include in the final optimization record file generated. If
  // not provided -fsave-optimization-record will include all passes.
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_opt_record_passes))
    opts.OptRecordPasses = a->getValue();

  // Create OptRemark that allows printing of all successful optimization
  // passes applied.
  opts.OptimizationRemark =
      parseOptimizationRemark(diags, args, clang::options::OPT_Rpass_EQ,
                              /*remarkOptName=*/"pass");

  // Create OptRemark that allows all missed optimization passes to be printed.
  opts.OptimizationRemarkMissed =
      parseOptimizationRemark(diags, args, clang::options::OPT_Rpass_missed_EQ,
                              /*remarkOptName=*/"pass-missed");

  // Create OptRemark that allows all optimization decisions made by LLVM
  // to be printed.
  opts.OptimizationRemarkAnalysis = parseOptimizationRemark(
      diags, args, clang::options::OPT_Rpass_analysis_EQ,
      /*remarkOptName=*/"pass-analysis");

  if (opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo) {
    // If the user requested a flag that requires source locations available in
    // the backend, make sure that the backend tracks source location
    // information.
    bool needLocTracking = !opts.OptRecordFile.empty() ||
                           !opts.OptRecordPasses.empty() ||
                           !opts.OptRecordFormat.empty() ||
                           opts.OptimizationRemark.hasValidPattern() ||
                           opts.OptimizationRemarkMissed.hasValidPattern() ||
                           opts.OptimizationRemarkAnalysis.hasValidPattern();

    if (needLocTracking)
      opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
  }

  if (auto *a = args.getLastArg(clang::options::OPT_save_temps_EQ))
    opts.SaveTempsDir = a->getValue();

  // -record-command-line option.
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_record_command_line)) {
    opts.RecordCommandLine = a->getValue();
  }

  // -mlink-builtin-bitcode
  for (auto *a : args.filtered(clang::options::OPT_mlink_builtin_bitcode))
    opts.BuiltinBCLibs.push_back(a->getValue());

  // -mrelocation-model option.
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_mrelocation_model)) {
    llvm::StringRef modelName = a->getValue();
    auto relocModel =
        llvm::StringSwitch<std::optional<llvm::Reloc::Model>>(modelName)
            .Case("static", llvm::Reloc::Static)
            .Case("pic", llvm::Reloc::PIC_)
            .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
            .Case("ropi", llvm::Reloc::ROPI)
            .Case("rwpi", llvm::Reloc::RWPI)
            .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
            .Default(std::nullopt);
    if (relocModel.has_value())
      opts.setRelocationModel(*relocModel);
    else
      diags.Report(clang::diag::err_drv_invalid_value)
          << a->getAsString(args) << modelName;
  }

  // -pic-level and -pic-is-pie option.
  if (int picLevel =
          getLastArgIntValue(args, clang::options::OPT_pic_level, 0, diags)) {
    if (picLevel > 2)
      diags.Report(clang::diag::err_drv_invalid_value)
          << args.getLastArg(clang::options::OPT_pic_level)->getAsString(args)
          << picLevel;

    opts.PICLevel = picLevel;
    if (args.hasArg(clang::options::OPT_pic_is_pie))
      opts.IsPIE = 1;
  }

  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_fprofile_generate,
                          clang::options::OPT_fprofile_generate_EQ)) {
    opts.setProfileInstr(llvm::driver::ProfileInstrKind::ProfileIRInstr);
    if (a->getOption().matches(clang::options::OPT_fprofile_generate_EQ)) {
      llvm::SmallString<128> path(a->getValue());
      llvm::sys::path::append(path, "default_%m.profraw");
      opts.InstrProfileOutput = std::string(path);
    }
  }

  if (auto A = args.getLastArg(clang::options::OPT_fprofile_use_EQ)) {
    opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileIRInstr);
    opts.ProfileInstrumentUsePath = A->getValue();
  }

  opts.SampleProfileFile =
      args.getLastArgValue(clang::options::OPT_fprofile_sample_use_EQ);

  if (args.hasFlag(clang::options::OPT_fpseudo_probe_for_profiling,
                   clang::options::OPT_fno_pseudo_probe_for_profiling, false)) {
    opts.PseudoProbeForProfiling = 1;
  }

  // -mcmodel option.
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_mcmodel_EQ)) {
    llvm::StringRef modelName = a->getValue();
    std::optional<llvm::CodeModel::Model> codeModel = getCodeModel(modelName);

    if (codeModel.has_value())
      opts.CodeModel = modelName;
    else
      diags.Report(clang::diag::err_drv_invalid_value)
          << a->getAsString(args) << modelName;
  }

  if (const llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_mlarge_data_threshold_EQ)) {
    uint64_t LDT;
    if (llvm::StringRef(arg->getValue()).getAsInteger(/*Radix=*/10, LDT)) {
      diags.Report(clang::diag::err_drv_invalid_value)
          << arg->getSpelling() << arg->getValue();
    }
    opts.LargeDataThreshold = LDT;
  }

  // This option is compatible with -f[no-]underscoring in gfortran.
  if (args.hasFlag(clang::options::OPT_fno_underscoring,
                   clang::options::OPT_funderscoring, false)) {
    opts.Underscoring = 0;
  }

  if (const llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_complex_range_EQ)) {
    llvm::StringRef argValue = llvm::StringRef(arg->getValue());
    if (argValue == "full") {
      opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Full);
    } else if (argValue == "improved") {
      opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Improved);
    } else if (argValue == "basic") {
      opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Basic);
    } else {
      diags.Report(clang::diag::err_drv_invalid_value)
          << arg->getAsString(args) << arg->getValue();
    }
  }
}

/// Parses all target input arguments and populates the target
/// options accordingly.
///
/// \param [in] opts The target options instance to update
/// \param [in] args The list of input arguments (from the compiler invocation)
static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) {
  if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_triple))
    opts.triple = a->getValue();

  opts.atomicIgnoreDenormalMode =
      args.hasFlag(clang::options::OPT_fatomic_ignore_denormal_mode,
                   clang::options::OPT_fno_atomic_ignore_denormal_mode, false);
  opts.atomicFineGrainedMemory =
      args.hasFlag(clang::options::OPT_fatomic_fine_grained_memory,
                   clang::options::OPT_fno_atomic_fine_grained_memory, false);
  opts.atomicRemoteMemory =
      args.hasFlag(clang::options::OPT_fatomic_remote_memory,
                   clang::options::OPT_fno_atomic_remote_memory, false);

  if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_target_cpu))
    opts.cpu = a->getValue();

  if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_tune_cpu))
    opts.cpuToTuneFor = a->getValue();

  for (const llvm::opt::Arg *currentArg :
       args.filtered(clang::options::OPT_target_feature))
    opts.featuresAsWritten.emplace_back(currentArg->getValue());

  if (args.hasArg(clang::options::OPT_fdisable_real_10))
    opts.disabledRealKinds.push_back(10);

  if (args.hasArg(clang::options::OPT_fdisable_real_3))
    opts.disabledRealKinds.push_back(3);

  if (args.hasArg(clang::options::OPT_fdisable_integer_2))
    opts.disabledIntegerKinds.push_back(2);

  if (args.hasArg(clang::options::OPT_fdisable_integer_16))
    opts.disabledIntegerKinds.push_back(16);

  if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_mabi_EQ)) {
    llvm::StringRef V = a->getValue();
    // Normalize "vec-default" to an empty ABI name; the AIX extended Altivec
    // ABI is carried to the backend as the "vec-extabi" target-abi module flag.
    opts.abi = V == "vec-default" ? "" : V.str();
  }

  opts.SplitMachineFunctions =
      args.hasArg(clang::options::OPT_fsplit_machine_functions);

  opts.asmVerbose = args.hasFlag(clang::options::OPT_fverbose_asm,
                                 clang::options::OPT_fno_verbose_asm, false);
}
// Tweak the frontend configuration based on the frontend action
static void setUpFrontendBasedOnAction(FrontendOptions &opts) {
  if (opts.programAction == DebugDumpParsingLog)
    opts.instrumentedParse = true;

  if (opts.programAction == DebugDumpProvenance ||
      opts.programAction == Fortran::frontend::GetDefinition)
    opts.needProvenanceRangeToCharBlockMappings = true;
}

/// Parse the argument specified for the -fconvert=<value> option
static std::optional<const char *> parseConvertArg(const char *s) {
  return llvm::StringSwitch<std::optional<const char *>>(s)
      .Case("unknown", "UNKNOWN")
      .Case("native", "NATIVE")
      .Case("little-endian", "LITTLE_ENDIAN")
      .Case("big-endian", "BIG_ENDIAN")
      .Case("swap", "SWAP")
      .Default(std::nullopt);
}

static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
                              clang::DiagnosticsEngine &diags) {
  // By default the frontend driver creates a ParseSyntaxOnly action.
  opts.programAction = ParseSyntaxOnly;

  // Treat multiple action options as an invocation error. Note that `clang
  // -cc1` does accept multiple action options, but will only consider the
  // rightmost one.
  if (args.hasMultipleArgs(clang::options::OPT_Action_Group)) {
    llvm::SmallString<32> buf;
    llvm::raw_svector_ostream os(buf);
    for (const llvm::opt::Arg *arg :
         args.filtered(clang::options::OPT_Action_Group)) {
      if (buf.size())
        os << ", ";
      os << "'" << arg->getSpelling() << "'";
    }
    diags.Report(clang::diag::err_drv_too_many_actions) << buf;
    return false;
  }

  // Identify the action (i.e. opts.ProgramAction)
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_Action_Group)) {
    switch (a->getOption().getID()) {
    default: {
      llvm_unreachable("Invalid option in group!");
    }
    case clang::options::OPT_test_io:
      opts.programAction = InputOutputTest;
      break;
    case clang::options::OPT_E:
      opts.programAction = PrintPreprocessedInput;
      break;
    case clang::options::OPT_fsyntax_only:
      opts.programAction = ParseSyntaxOnly;
      break;
    case clang::options::OPT_emit_fir:
      opts.programAction = EmitFIR;
      break;
    case clang::options::OPT_emit_hlfir:
      opts.programAction = EmitHLFIR;
      break;
    case clang::options::OPT_emit_llvm:
      opts.programAction = EmitLLVM;
      break;
    case clang::options::OPT_emit_llvm_bc:
      opts.programAction = EmitLLVMBitcode;
      break;
    case clang::options::OPT_emit_obj:
      opts.programAction = EmitObj;
      break;
    case clang::options::OPT_S:
      opts.programAction = EmitAssembly;
      break;
    case clang::options::OPT_fdebug_unparse:
      opts.programAction = DebugUnparse;
      break;
    case clang::options::OPT_fdebug_unparse_no_sema:
      opts.programAction = DebugUnparseNoSema;
      break;
    case clang::options::OPT_fdebug_unparse_with_symbols:
      opts.programAction = DebugUnparseWithSymbols;
      break;
    case clang::options::OPT_fdebug_unparse_with_modules:
      opts.programAction = DebugUnparseWithModules;
      break;
    case clang::options::OPT_fdebug_dump_symbols:
      opts.programAction = DebugDumpSymbols;
      break;
    case clang::options::OPT_fdebug_dump_parse_tree:
      opts.programAction = DebugDumpParseTree;
      break;
    case clang::options::OPT_fdebug_dump_pft:
      opts.programAction = DebugDumpPFT;
      break;
    case clang::options::OPT_fdebug_dump_all:
      opts.programAction = DebugDumpAll;
      break;
    case clang::options::OPT_fdebug_dump_parse_tree_no_sema:
      opts.programAction = DebugDumpParseTreeNoSema;
      break;
    case clang::options::OPT_fdebug_dump_provenance:
      opts.programAction = DebugDumpProvenance;
      break;
    case clang::options::OPT_fdebug_dump_parsing_log:
      opts.programAction = DebugDumpParsingLog;
      break;
    case clang::options::OPT_fdebug_measure_parse_tree:
      opts.programAction = DebugMeasureParseTree;
      break;
    case clang::options::OPT_fdebug_pre_fir_tree:
      opts.programAction = DebugPreFIRTree;
      break;
    case clang::options::OPT_fget_symbols_sources:
      opts.programAction = GetSymbolsSources;
      break;
    case clang::options::OPT_fget_definition:
      opts.programAction = GetDefinition;
      break;
    case clang::options::OPT_init_only:
      opts.programAction = InitOnly;
      break;

      // TODO:
      // case clang::options::OPT_emit_llvm:
      // case clang::options::OPT_emit_llvm_only:
      // case clang::options::OPT_emit_codegen_only:
      // case clang::options::OPT_emit_module:
      // (...)
    }

    // Parse the values provided with `-fget-definition` (there should be 3
    // integers)
    if (llvm::opt::OptSpecifier(a->getOption().getID()) ==
        clang::options::OPT_fget_definition) {
      unsigned optVals[3] = {0, 0, 0};

      for (unsigned i = 0; i < 3; i++) {
        llvm::StringRef val = a->getValue(i);

        if (val.getAsInteger(10, optVals[i])) {
          // A non-integer was encountered - that's an error.
          diags.Report(clang::diag::err_drv_invalid_value)
              << a->getOption().getName() << val;
          break;
        }
      }
      opts.getDefVals.line = optVals[0];
      opts.getDefVals.startColumn = optVals[1];
      opts.getDefVals.endColumn = optVals[2];
    }
  }

  // Parsing -load <dsopath> option and storing shared object path
  if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_load)) {
    opts.plugins.push_back(a->getValue());
  }

  // Parsing -plugin <name> option and storing plugin name and setting action
  if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_plugin)) {
    opts.programAction = PluginAction;
    opts.actionName = a->getValue();
  }

  opts.outputFile = args.getLastArgValue(clang::options::OPT_o);
  opts.dependencyOutputFile =
      args.getLastArgValue(clang::options::OPT_dependency_file);
  opts.dependencyTargets = args.getAllArgValues(clang::options::OPT_MT);
  opts.showHelp = args.hasArg(clang::options::OPT_help);
  opts.showVersion = args.hasArg(clang::options::OPT_version);
  opts.printSupportedCPUs =
      args.hasArg(clang::options::OPT_print_supported_cpus);

  // Get the input kind (from the value passed via `-x`)
  InputKind dashX(Language::Unknown);
  if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_x)) {
    llvm::StringRef xValue = a->getValue();
    // Principal languages.
    dashX = llvm::StringSwitch<InputKind>(xValue)
                // Flang does not differentiate between pre-processed and not
                // pre-processed inputs.
                .Case("f95", Language::Fortran)
                .Case("f95-cpp-input", Language::Fortran)
                // CUDA Fortran
                .Case("cuda", Language::Fortran)
                .Default(Language::Unknown);

    // Flang's intermediate representations.
    if (dashX.isUnknown())
      dashX = llvm::StringSwitch<InputKind>(xValue)
                  .Case("ir", Language::LLVM_IR)
                  .Case("fir", Language::MLIR)
                  .Case("mlir", Language::MLIR)
                  .Default(Language::Unknown);

    if (dashX.isUnknown())
      diags.Report(clang::diag::err_drv_invalid_value)
          << a->getAsString(args) << a->getValue();
  }

  // Collect the input files and save them in our instance of FrontendOptions.
  std::vector<std::string> inputs =
      args.getAllArgValues(clang::options::OPT_INPUT);
  opts.inputs.clear();
  if (inputs.empty())
    // '-' is the default input if none is given.
    inputs.push_back("-");
  for (unsigned i = 0, e = inputs.size(); i != e; ++i) {
    InputKind ik = dashX;
    if (ik.isUnknown()) {
      ik = FrontendOptions::getInputKindForExtension(
          llvm::StringRef(inputs[i]).rsplit('.').second);
      if (ik.isUnknown())
        ik = Language::Unknown;
      if (i == 0)
        dashX = ik;
    }

    opts.inputs.emplace_back(std::move(inputs[i]), ik);
  }

  // Set fortranForm based on options -ffree-form and -ffixed-form.
  if (const auto *arg = args.getLastArg(clang::options::OPT_ffixed_form,
                                        clang::options::OPT_ffree_form)) {
    opts.fortranForm = arg->getOption().matches(clang::options::OPT_ffixed_form)
                           ? FortranForm::FixedForm
                           : FortranForm::FreeForm;
  }

  // Set fixedFormColumns based on -ffixed-line-length=<value>
  if (const auto *arg =
          args.getLastArg(clang::options::OPT_ffixed_line_length_EQ)) {
    llvm::StringRef argValue = llvm::StringRef(arg->getValue());
    std::int64_t columns = -1;
    if (argValue == "none") {
      columns = 0;
    } else if (argValue.getAsInteger(/*Radix=*/10, columns)) {
      columns = -1;
    }
    if (columns < 0) {
      diags.Report(clang::diag::err_drv_negative_columns)
          << arg->getOption().getName() << arg->getValue();
    } else if (columns == 0) {
      opts.fixedFormColumns = std::nullopt;
    } else if (columns < 7) {
      diags.Report(clang::diag::err_drv_small_columns)
          << arg->getOption().getName() << arg->getValue() << "7";
    } else if (columns > std::numeric_limits<int>::max()) {
      diags.Report(clang::diag::err_drv_large_columns)
          << arg->getOption().getName() << arg->getValue()
          << std::numeric_limits<int>::max();
    } else {
      opts.fixedFormColumns = columns;
    }
  }

  // Set conversion based on -fconvert=<value>
  if (const auto *arg = args.getLastArg(clang::options::OPT_fconvert_EQ)) {
    const char *argValue = arg->getValue();
    if (auto convert = parseConvertArg(argValue))
      opts.envDefaults.push_back({"FORT_CONVERT", *convert});
    else
      diags.Report(clang::diag::err_drv_invalid_value)
          << arg->getAsString(args) << argValue;
  }

  // -f{no-}implicit-none
  opts.features.Enable(Fortran::common::LanguageFeature::ImplicitNoneTypeAlways,
                       args.hasFlag(clang::options::OPT_fimplicit_none,
                                    clang::options::OPT_fno_implicit_none,
                                    false));

  // -f{no-}implicit-none-ext
  opts.features.Enable(Fortran::common::LanguageFeature::ImplicitNoneExternal,
                       args.hasFlag(clang::options::OPT_fimplicit_none_ext,
                                    clang::options::OPT_fno_implicit_none_ext,
                                    false));

  // -f{no-}implicit-module-prefix
  opts.features.Enable(
      Fortran::common::LanguageFeature::ImplicitModulePrefix,
      args.hasFlag(clang::options::OPT_fimplicit_module_prefix,
                   clang::options::OPT_fno_implicit_module_prefix, false));

  // -f{no-}backslash
  opts.features.Enable(Fortran::common::LanguageFeature::BackslashEscapes,
                       args.hasFlag(clang::options::OPT_fbackslash,
                                    clang::options::OPT_fno_backslash, false));

  // -f{no-}logical-abbreviations
  opts.features.Enable(
      Fortran::common::LanguageFeature::LogicalAbbreviations,
      args.hasFlag(clang::options::OPT_flogical_abbreviations,
                   clang::options::OPT_fno_logical_abbreviations, false));

  // -f{no-}unsigned
  opts.features.Enable(Fortran::common::LanguageFeature::Unsigned,
                       args.hasFlag(clang::options::OPT_funsigned,
                                    clang::options::OPT_fno_unsigned, false));

  // -f{no-}out-of-bounds-subscripts
  opts.features.Enable(
      Fortran::common::LanguageFeature::OutOfBoundsSubscripts,
      args.hasFlag(clang::options::OPT_fout_of_bounds_subscripts,
                   clang::options::OPT_fno_out_of_bounds_subscripts, true));

  // -f{no-}enumeration-type (experimental; FIR lowering is incomplete)
  opts.features.Enable(Fortran::common::LanguageFeature::EnumerationType,
                       args.hasFlag(clang::options::OPT_fenumeration_type,
                                    clang::options::OPT_fno_enumeration_type,
                                    false));

  // -frelaxed-c-loc-checks
  if (args.hasArg(clang::options::OPT_relaxed_c_loc)) {
    opts.features.Enable(Fortran::common::LanguageFeature::RelaxedCLocChecks);
  }

  // -f{no-}openacc-default-none-scalars-strict
  opts.features.Enable(
      Fortran::common::LanguageFeature::OpenAccDefaultNoneScalarsStrict,
      args.hasFlag(clang::options::OPT_fopenacc_default_none_scalars_strict,
                   clang::options::OPT_fno_openacc_default_none_scalars_strict,
                   false));

  // -f{no-}openacc-multiple-names-in-routine
  opts.features.Enable(
      Fortran::common::LanguageFeature::OpenACCMultipleNamesInRoutine,
      args.hasFlag(clang::options::OPT_fopenacc_multiple_names_in_routine,
                   clang::options::OPT_fno_openacc_multiple_names_in_routine,
                   true));

  // -f{no-}prefer-intrinsic-module-use-association
  if (const auto *arg = args.getLastArg(
          clang::options::OPT_fprefer_intrinsic_module_use_association,
          clang::options::OPT_fno_prefer_intrinsic_module_use_association)) {
    opts.features.Enable(
        Fortran::common::LanguageFeature::PreferIntrinsicModuleUseAssociation,
        arg->getOption().matches(
            clang::options::OPT_fprefer_intrinsic_module_use_association));
  }

  // -f{no-}xor-operator
  opts.features.Enable(Fortran::common::LanguageFeature::XOROperator,
                       args.hasFlag(clang::options::OPT_fxor_operator,
                                    clang::options::OPT_fno_xor_operator,
                                    false));

  // -fno-automatic
  if (args.hasArg(clang::options::OPT_fno_automatic)) {
    opts.features.Enable(Fortran::common::LanguageFeature::DefaultSave);
  }

  // -f{no}-save-main-program
  opts.features.Enable(Fortran::common::LanguageFeature::SaveMainProgram,
                       args.hasFlag(clang::options::OPT_fsave_main_program,
                                    clang::options::OPT_fno_save_main_program,
                                    false));

  if (args.hasArg(clang::options::OPT_falternative_parameter_statement)) {
    opts.features.Enable(Fortran::common::LanguageFeature::OldStyleParameter);
  }
  if (const llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_finput_charset_EQ)) {
    llvm::StringRef argValue = arg->getValue();
    if (argValue == "utf-8") {
      opts.encoding = Fortran::parser::Encoding::UTF_8;
    } else if (argValue == "latin-1") {
      opts.encoding = Fortran::parser::Encoding::LATIN_1;
    } else {
      diags.Report(clang::diag::err_drv_invalid_value)
          << arg->getAsString(args) << argValue;
    }
  }

  setUpFrontendBasedOnAction(opts);
  opts.dashX = dashX;

  return !diags.hasUncompilableErrorOccurred();
}

// Generate the path to look for intrinsic modules
static std::string getIntrinsicDir(const char *argv) {
  // TODO: Find a system independent API
  llvm::SmallString<128> driverPath;
  driverPath.assign(llvm::sys::fs::getMainExecutable(argv, nullptr));
  llvm::sys::path::remove_filename(driverPath);
  driverPath.append("/../include/flang/");
  return std::string(driverPath);
}

/// Parses all preprocessor input arguments and populates the preprocessor
/// options accordingly.
///
/// \param [in] opts The preprocessor options instance
/// \param [out] args The list of input arguments
static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
                                  llvm::opt::ArgList &args) {
  // Add macros from the command line.
  for (const auto *currentArg :
       args.filtered(clang::options::OPT_D, clang::options::OPT_U)) {
    if (currentArg->getOption().matches(clang::options::OPT_D)) {
      opts.addMacroDef(currentArg->getValue());
    } else {
      opts.addMacroUndef(currentArg->getValue());
    }
  }

  // Add the ordered list of -I's.
  for (const auto *currentArg : args.filtered(clang::options::OPT_I))
    opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue());

  // Prepend the ordered list of -intrinsic-modules-path
  // to the default location to search.
  for (const auto *currentArg :
       args.filtered(clang::options::OPT_fintrinsic_modules_path))
    opts.searchDirectoriesFromIntrModPath.emplace_back(currentArg->getValue());

  // -cpp/-nocpp
  if (const auto *currentArg =
          args.getLastArg(clang::options::OPT_cpp, clang::options::OPT_nocpp))
    opts.macrosFlag = (currentArg->getOption().matches(clang::options::OPT_cpp))
                          ? PPMacrosFlag::Include
                          : PPMacrosFlag::Exclude;
  // Enable -cpp based on -x unless explicitly disabled with -nocpp
  if (opts.macrosFlag != PPMacrosFlag::Exclude)
    if (const auto *dashX = args.getLastArg(clang::options::OPT_x))
      opts.macrosFlag = llvm::StringSwitch<PPMacrosFlag>(dashX->getValue())
                            .Case("f95-cpp-input", PPMacrosFlag::Include)
                            .Default(opts.macrosFlag);

  opts.noReformat = args.hasArg(clang::options::OPT_fno_reformat);
  opts.preprocessIncludeLines =
      args.hasArg(clang::options::OPT_fpreprocess_include_lines);
  opts.noLineDirectives = args.hasArg(clang::options::OPT_P);
  opts.showMacros = args.hasArg(clang::options::OPT_dM);
}

/// Parses all semantic related arguments and populates the variables
/// options accordingly. Returns false if new errors are generated.
static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                          clang::DiagnosticsEngine &diags) {
  // -J/module-dir option
  std::vector<std::string> moduleDirList =
      args.getAllArgValues(clang::options::OPT_module_dir);
  // User can only specify one -J/-module-dir directory, but may repeat
  // -J/-module-dir as long as the directory is the same each time.
  // https://gcc.gnu.org/onlinedocs/gfortran/Directory-Options.html
  std::sort(moduleDirList.begin(), moduleDirList.end());
  moduleDirList.erase(std::unique(moduleDirList.begin(), moduleDirList.end()),
                      moduleDirList.end());
  if (moduleDirList.size() > 1) {
    const unsigned diagID =
        diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                              "Only one '-module-dir/-J' directory allowed. "
                              "'-module-dir/-J' may be given multiple times "
                              "but the directory must be the same each time.");
    diags.Report(diagID);
  }
  if (moduleDirList.size() == 1)
    res.setModuleDir(moduleDirList[0]);

  // -fdebug-module-writer option
  if (args.hasArg(clang::options::OPT_fdebug_module_writer)) {
    res.setDebugModuleDir(true);
  }

  // -fhermetic-module-files option
  if (args.hasArg(clang::options::OPT_fhermetic_module_files)) {
    res.setHermeticModuleFileOutput(true);
  }

  // -module-suffix
  if (const auto *moduleSuffix =
          args.getLastArg(clang::options::OPT_module_suffix)) {
    res.setModuleFileSuffix(moduleSuffix->getValue());
  }

  // -f{no-}analyzed-objects-for-unparse
  res.setUseAnalyzedObjectsForUnparse(
      args.hasFlag(clang::options::OPT_fanalyzed_objects_for_unparse,
                   clang::options::OPT_fno_analyzed_objects_for_unparse, true));

  return !diags.hasUncompilableErrorOccurred();
}

/// Parses all diagnostics related arguments and populates the variables
/// options accordingly. Returns false if new errors are generated.
/// FC1 driver entry point for parsing diagnostic arguments.
static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                          clang::DiagnosticsEngine &diags) {
  auto &features{res.getFrontendOpts().features};
  // The order of these flags (-pedantic -W<feature> -w) is important and is
  // chosen to match clang's behavior.

  // -pedantic
  if (args.hasArg(clang::options::OPT_pedantic)) {
    features.WarnOnAllNonstandard();
    features.WarnOnAllUsage();
    res.setEnableConformanceChecks();
    res.setEnableUsageChecks();
  }

  // -Werror option
  // TODO: Currently throws a Diagnostic for anything other than -W<error>,
  // this has to change when other -W<opt>'s are supported.
  if (args.hasArg(clang::options::OPT_W_Joined)) {
    const auto &wArgs = args.getAllArgValues(clang::options::OPT_W_Joined);
    // TODO: Consider using std::string_view instead of llvm::StringRef
    // when moving to C++20:
    for (const llvm::StringRef wArg : wArgs) {
      if (wArg == "error") {
        res.setWarnAsErr(true);
        // -Wfatal-errors
      } else if (wArg == "fatal-errors") {
        res.setMaxErrors(1);
        // -W[no-]<feature>
      } else if (features.EnableWarning(wArg)) {
        if (auto canonical{features.CheckDeprecatedSpelling(wArg)}) {
          std::string suggestion{*canonical};
          if (wArg.starts_with("no-")) {
            suggestion = "no-" + suggestion;
          }
          const unsigned diagID =
              diags.getCustomDiagID(clang::DiagnosticsEngine::Warning,
                                    "-W%0 is deprecated; use -W%1 instead");
          diags.Report(diagID) << wArg << suggestion;
        }
      } else {
        const unsigned diagID = diags.getCustomDiagID(
            clang::DiagnosticsEngine::Error, "Unknown diagnostic option: -W%0");
        diags.Report(diagID) << wArg;
      }
    }
  }

  // -w
  if (args.hasArg(clang::options::OPT_w)) {
    features.DisableAllWarnings();
    res.setDisableWarnings();
  }

  // Default to off for `flang -fc1`.
  bool showColors{parseShowColorsArgs(args, false)};
  auto colorsMode =
      showColors ? clang::ShowColorsKind::On : clang::ShowColorsKind::Off;
  diags.getDiagnosticOptions().setShowColors(colorsMode);
  res.getDiagnosticOpts().setShowColors(colorsMode);
  res.getFrontendOpts().showColors = showColors;
  return !diags.hasUncompilableErrorOccurred();
}

/// Parses all Dialect related arguments and populates the variables
/// options accordingly. Returns false if new errors are generated.
static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                             clang::DiagnosticsEngine &diags) {
  // -fd-lines-as-code
  if (args.hasArg(clang::options::OPT_fd_lines_as_code)) {
    if (res.getFrontendOpts().fortranForm == FortranForm::FreeForm) {
      const unsigned fdLinesAsWarning = diags.getCustomDiagID(
          clang::DiagnosticsEngine::Warning,
          "‘-fd-lines-as-code’ has no effect in free form.");
      diags.Report(fdLinesAsWarning);
    } else {
      res.getFrontendOpts().features.Enable(
          Fortran::common::LanguageFeature::OldDebugLines, true);
    }
  }

  // -fd-lines-as-comments
  if (args.hasArg(clang::options::OPT_fd_lines_as_comments)) {
    if (res.getFrontendOpts().fortranForm == FortranForm::FreeForm) {
      const unsigned fdLinesAsWarning = diags.getCustomDiagID(
          clang::DiagnosticsEngine::Warning,
          "‘-fd-lines-as-comments’ has no effect in free form.");
      diags.Report(fdLinesAsWarning);
    } else {
      res.getFrontendOpts().features.Enable(
          Fortran::common::LanguageFeature::OldDebugLines, false);
    }
  }

  // -fdefault* family
  if (const llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_fdefault_real_8,
                          clang::options::OPT_fdefault_real_4)) {
    const llvm::opt::Option &opt = arg->getOption();
    if (opt.matches(clang::options::OPT_fdefault_real_8)) {
      res.getDefaultKinds().set_defaultRealKind(8);
      res.getDefaultKinds().set_doublePrecisionKind(16);
    } else if (opt.matches(clang::options::OPT_fdefault_real_4)) {
      res.getDefaultKinds().set_defaultRealKind(4);
      res.getDefaultKinds().set_doublePrecisionKind(8);
    }
  }
  if (const llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_fdefault_integer_8,
                          clang::options::OPT_fdefault_integer_4)) {
    const llvm::opt::Option &opt = arg->getOption();
    if (opt.matches(clang::options::OPT_fdefault_integer_8)) {
      res.getDefaultKinds().set_defaultIntegerKind(8);
      res.getDefaultKinds().set_subscriptIntegerKind(8);
      res.getDefaultKinds().set_sizeIntegerKind(8);
      res.getDefaultKinds().set_defaultLogicalKind(8);
    } else if (opt.matches(clang::options::OPT_fdefault_integer_4)) {
      // Note that the subscript integer kind is set to 8 here. If a
      // default-integer-kind is not provided, it is also set to 8.
      res.getDefaultKinds().set_defaultIntegerKind(4);
      res.getDefaultKinds().set_subscriptIntegerKind(8);
      res.getDefaultKinds().set_sizeIntegerKind(4);
      res.getDefaultKinds().set_defaultLogicalKind(4);
    }
  }
  if (args.hasArg(clang::options::OPT_fdefault_double_8)) {
    if (!args.hasArg(clang::options::OPT_fdefault_real_8)) {
      // -fdefault-double-8 has to be used with -fdefault-real-8
      // to be compatible with gfortran
      const unsigned diagID = diags.getCustomDiagID(
          clang::DiagnosticsEngine::Error,
          "Use of `-fdefault-double-8` requires `-fdefault-real-8`");
      diags.Report(diagID);
    }
    // https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html
    res.getDefaultKinds().set_doublePrecisionKind(8);
  }
  if (args.hasArg(clang::options::OPT_flarge_sizes))
    res.getDefaultKinds().set_sizeIntegerKind(8);

  // -x cuda
  auto language = args.getLastArgValue(clang::options::OPT_x);
  if (language == "cuda") {
    res.getFrontendOpts().features.Enable(
        Fortran::common::LanguageFeature::CUDA);
  }

  // -fopenacc
  if (args.hasArg(clang::options::OPT_fopenacc)) {
    res.getFrontendOpts().features.Enable(
        Fortran::common::LanguageFeature::OpenACC);
  }

  // -std=f2018
  // TODO: Set proper options when more fortran standards
  // are supported.
  if (args.hasArg(clang::options::OPT_std_EQ)) {
    auto standard = args.getLastArgValue(clang::options::OPT_std_EQ);
    // We only allow f2018 as the given standard
    if (standard == "f2018") {
      res.setEnableConformanceChecks();
      res.getFrontendOpts().features.WarnOnAllNonstandard();
    } else {
      const unsigned diagID =
          diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                                "Only -std=f2018 is allowed currently.");
      diags.Report(diagID);
    }
  }
  // -fcoarray
  if (args.hasArg(clang::options::OPT_fcoarray)) {
    res.getFrontendOpts().features.Enable(
        Fortran::common::LanguageFeature::Coarray);
    const unsigned diagID =
        diags.getCustomDiagID(clang::DiagnosticsEngine::Warning,
                              "Support for multi image Fortran features is "
                              "still experimental and in development.");
    diags.Report(diagID);
  }

  return !diags.hasUncompilableErrorOccurred();
}

/// Parses all OpenMP related arguments if the -fopenmp option is present,
/// populating the \c res object accordingly. Returns false if new errors are
/// generated.
static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                            clang::DiagnosticsEngine &diags) {
  llvm::opt::Arg *arg = args.getLastArg(clang::options::OPT_fopenmp,
                                        clang::options::OPT_fno_openmp);
  if (!arg || arg->getOption().matches(clang::options::OPT_fno_openmp)) {
    bool isSimdSpecified =
        args.hasFlag(clang::options::OPT_fopenmp_simd,
                     clang::options::OPT_fno_openmp_simd, /*Default=*/false);
    if (!isSimdSpecified)
      return true;
    res.getLangOpts().OpenMPSimd = 1;
  }

  llvm::Triple t(res.getTargetOpts().triple);

  constexpr unsigned newestFullySupported = 31;
  constexpr unsigned latestFinalized = 60;
  // By default OpenMP is set to the most recent fully supported version
  res.getLangOpts().OpenMPVersion = newestFullySupported;
  res.getFrontendOpts().features.Enable(
      Fortran::common::LanguageFeature::OpenMP);
  if (auto *arg = args.getLastArg(clang::options::OPT_fopenmp_version_EQ)) {
    llvm::SmallVector<unsigned> ompVersions;
    for (llvm::omp::Version v : llvm::omp::getOpenMPVersions()) {
      ompVersions.push_back(static_cast<unsigned>(v));
    }
    unsigned oldVersions[] = {11, 20, 25, 30};
    unsigned version = 0;

    auto reportBadVersion = [&](llvm::StringRef value) {
      const unsigned diagID =
          diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                                "'%0' is not a valid OpenMP version in '%1', "
                                "valid versions are %2");
      std::string buffer;
      llvm::raw_string_ostream versions(buffer);
      llvm::interleaveComma(ompVersions, versions);

      diags.Report(diagID) << value << arg->getAsString(args) << versions.str();
    };

    llvm::StringRef value = arg->getValue();
    if (!value.getAsInteger(/*radix=*/10, version)) {
      if (llvm::is_contained(ompVersions, version)) {
        res.getLangOpts().OpenMPVersion = version;

        if (version > latestFinalized)
          diags.Report(clang::diag::warn_openmp_spec_incomplete) << version;
        else if (version > newestFullySupported)
          diags.Report(clang::diag::warn_openmp_impl_incomplete) << version;
      } else if (llvm::is_contained(oldVersions, version)) {
        const unsigned diagID =
            diags.getCustomDiagID(clang::DiagnosticsEngine::Warning,
                                  "OpenMP version %0 is no longer supported, "
                                  "assuming version %1");
        std::string assumed = std::to_string(res.getLangOpts().OpenMPVersion);
        diags.Report(diagID) << value << assumed;
      } else {
        reportBadVersion(value);
      }
    } else {
      reportBadVersion(value);
    }
  }

  if (args.hasFlag(clang::options::OPT_fopenmp_assume_teams_oversubscription,
                   clang::options::OPT_fno_openmp_assume_teams_oversubscription,
                   /*Default=*/false))
    res.getLangOpts().OpenMPTeamSubscription = true;
  if (args.hasFlag(
          clang::options::OPT_fopenmp_assume_threads_oversubscription,
          clang::options::OPT_fno_openmp_assume_threads_oversubscription,
          /*Default=*/false))
    res.getLangOpts().OpenMPThreadSubscription = true;

  if (args.hasArg(clang::options::OPT_fopenmp_force_usm)) {
    res.getLangOpts().OpenMPForceUSM = 1;
  }
  if (args.hasArg(clang::options::OPT_fopenmp_is_target_device)) {
    res.getLangOpts().OpenMPIsTargetDevice = 1;

    // Get OpenMP host file path if any and report if a non existent file is
    // found
    if (auto *arg =
            args.getLastArg(clang::options::OPT_fopenmp_host_ir_file_path)) {
      res.getLangOpts().OMPHostIRFile = arg->getValue();
      if (!llvm::sys::fs::exists(res.getLangOpts().OMPHostIRFile))
        diags.Report(clang::diag::err_omp_host_ir_file_not_found)
            << res.getLangOpts().OMPHostIRFile;
    }

    if (args.hasArg(clang::options::OPT_fopenmp_assume_no_thread_state))
      res.getLangOpts().OpenMPNoThreadState = 1;

    if (args.hasArg(clang::options::OPT_fopenmp_assume_no_nested_parallelism))
      res.getLangOpts().OpenMPNoNestedParallelism = 1;

    if ((args.hasArg(clang::options::OPT_fopenmp_target_debug) ||
         args.hasArg(clang::options::OPT_fopenmp_target_debug_EQ))) {
      res.getLangOpts().OpenMPTargetDebug =
          getLastArgIntValue(args, clang::options::OPT_fopenmp_target_debug_EQ,
                             res.getLangOpts().OpenMPTargetDebug, diags);

      if (!res.getLangOpts().OpenMPTargetDebug &&
          args.hasArg(clang::options::OPT_fopenmp_target_debug))
        res.getLangOpts().OpenMPTargetDebug = 1;
    }
    if (args.hasArg(clang::options::OPT_no_offloadlib))
      res.getLangOpts().NoGPULib = 1;
  }
  if (llvm::Triple(res.getTargetOpts().triple).isGPU()) {
    if (!res.getLangOpts().OpenMPIsTargetDevice) {
      const unsigned diagID = diags.getCustomDiagID(
          clang::DiagnosticsEngine::Error,
          "OpenMP GPU is only prepared to deal with device code.");
      diags.Report(diagID);
    }
    res.getLangOpts().OpenMPIsGPU = 1;
  } else {
    res.getLangOpts().OpenMPIsGPU = 0;
  }

  // Get the OpenMP target triples if any.
  if (auto *arg = args.getLastArg(clang::options::OPT_offload_targets_EQ)) {
    enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
    auto getArchPtrSize = [](const llvm::Triple &triple) {
      if (triple.isArch16Bit())
        return Arch16Bit;
      if (triple.isArch32Bit())
        return Arch32Bit;
      assert(triple.isArch64Bit() && "Expected 64-bit architecture");
      return Arch64Bit;
    };

    for (unsigned i = 0; i < arg->getNumValues(); ++i) {
      llvm::Triple tt(arg->getValue(i));

      if (tt.getArch() == llvm::Triple::UnknownArch ||
          !(tt.getArch() == llvm::Triple::aarch64 || tt.isPPC() ||
            tt.getArch() == llvm::Triple::systemz ||
            tt.getArch() == llvm::Triple::x86 ||
            tt.getArch() == llvm::Triple::x86_64 || tt.isGPU()))
        diags.Report(clang::diag::err_drv_invalid_omp_target)
            << arg->getValue(i);
      else if (getArchPtrSize(t) != getArchPtrSize(tt))
        diags.Report(clang::diag::err_drv_incompatible_omp_arch)
            << arg->getValue(i) << t.str();
      else
        res.getLangOpts().OMPTargetTriples.push_back(tt);
    }
  }
  return !diags.hasUncompilableErrorOccurred();
}

/// Parses signed integer overflow options and populates the
/// CompilerInvocation accordingly.
/// Returns false if new errors are generated.
///
/// \param [out] invoc Stores the processed arguments
/// \param [in] args The compiler invocation arguments to parse
/// \param [out] diags DiagnosticsEngine to report erros with
static bool parseIntegerOverflowArgs(CompilerInvocation &invoc,
                                     llvm::opt::ArgList &args,
                                     clang::DiagnosticsEngine &diags) {
  Fortran::common::LangOptions &opts = invoc.getLangOpts();

  if (args.getLastArg(clang::options::OPT_fwrapv))
    opts.setSignedOverflowBehavior(Fortran::common::LangOptions::SOB_Defined);

  return true;
}

/// Set the IEEE Floating point rounding modes, underflow mode and halting mode.
///
/// Initial halting mode:
/// -ffpe-trap= sets the initial floating-point exception halting mode for the
/// main program. Only the last -ffpe-trap= on the command line is effective.
/// The value is a comma-separated set of exception mnemonics: "invalid",
/// "zero", "overflow", "underflow", and "inexact" correspond to the Fortran
/// 2023 IEEE_FLAG_TYPE values (F2023 17.2), and "denormal" is a non-standard,
/// gfortran-compatible extension. "none", as well as an empty list, requests no
/// halting and resets any earlier request.
///
/// TODO:
/// Rounding modes
/// Underflow mode
///
/// The value and the target-support warnings are validated in the driver (see
/// addIEEEFPModesOptions() in clang/lib/Driver/ToolChains/Flang.cpp);
/// here we only translate the already-validated list, so an unrecognized
/// mnemonic maps to 0 and is ignored rather than re-diagnosed.
static void setIEEEFPModesArgs(Fortran::common::LangOptions &opts,
                               llvm::opt::ArgList &args) {
  const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_ffpe_trap_EQ);
  if (!a)
    return;

  using LangOptions = Fortran::common::LangOptions;
  unsigned traps = 0;
  llvm::SmallVector<llvm::StringRef> trapList;
  llvm::StringRef(a->getValue())
      .split(trapList, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
  for (llvm::StringRef trap : trapList) {
    if (trap == "none") {
      // Reset to no halting; a later mnemonic can re-enable.
      traps = 0;
      continue;
    }
    traps |= llvm::StringSwitch<unsigned>(trap)
                 .Case("invalid", LangOptions::FPE_Invalid)
                 .Case("denormal", LangOptions::FPE_Denormal)
                 .Case("zero", LangOptions::FPE_DivByZero)
                 .Case("overflow", LangOptions::FPE_Overflow)
                 .Case("underflow", LangOptions::FPE_Underflow)
                 .Case("inexact", LangOptions::FPE_Inexact)
                 .Default(0);
  }
  opts.FPExceptionTraps = traps;
}

/// Parses all floating point related arguments and populates the
/// CompilerInvocation accordingly.
/// Returns false if new errors are generated.
///
/// \param [out] invoc Stores the processed arguments
/// \param [in] args The compiler invocation arguments to parse
/// \param [out] diags DiagnosticsEngine to report erros with
static bool parseFloatingPointArgs(CompilerInvocation &invoc,
                                   llvm::opt::ArgList &args,
                                   clang::DiagnosticsEngine &diags) {
  Fortran::common::LangOptions &opts = invoc.getLangOpts();

  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_ffp_contract)) {
    const llvm::StringRef val = a->getValue();
    enum Fortran::common::LangOptions::FPModeKind fpContractMode;

    if (val == "off")
      fpContractMode = Fortran::common::LangOptions::FPM_Off;
    else if (val == "fast")
      fpContractMode = Fortran::common::LangOptions::FPM_Fast;
    else {
      diags.Report(clang::diag::err_drv_unsupported_option_argument)
          << a->getSpelling() << val;
      return false;
    }

    opts.setFPContractMode(fpContractMode);
  }

  if (args.getLastArg(clang::options::OPT_menable_no_infs)) {
    opts.NoHonorInfs = true;
  }

  if (args.getLastArg(clang::options::OPT_menable_no_nans)) {
    opts.NoHonorNaNs = true;
  }

  if (args.getLastArg(clang::options::OPT_fapprox_func)) {
    opts.ApproxFunc = true;
  }

  if (args.getLastArg(clang::options::OPT_fno_signed_zeros)) {
    opts.NoSignedZeros = true;
  }

  if (args.getLastArg(clang::options::OPT_mreassociate)) {
    opts.AssociativeMath = true;
  }

  if (args.getLastArg(clang::options::OPT_freciprocal_math)) {
    opts.ReciprocalMath = true;
  }

  if (args.getLastArg(clang::options::OPT_ffast_math)) {
    opts.NoHonorInfs = true;
    opts.NoHonorNaNs = true;
    opts.AssociativeMath = true;
    opts.ReciprocalMath = true;
    opts.ApproxFunc = true;
    opts.NoSignedZeros = true;
    opts.FastRealMod = true;
    opts.setFPContractMode(Fortran::common::LangOptions::FPM_Fast);
  }

  if (llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_ffast_real_mod,
                          clang::options::OPT_fno_fast_real_mod)) {
    if (arg->getOption().matches(clang::options::OPT_ffast_real_mod))
      opts.FastRealMod = true;
    if (arg->getOption().matches(clang::options::OPT_fno_fast_real_mod))
      opts.FastRealMod = false;
  }

  if (args.getLastArg(clang::options::OPT_fcheck_integer_mod_zero_divisor))
    opts.CheckIntegerModZeroDivisor = true;

  // Set the initial IEEE floating point modes
  setIEEEFPModesArgs(opts, args);

  return true;
}

/// Parses vscale range options and populates the CompilerInvocation
/// accordingly.
/// Returns false if new errors are generated.
///
/// \param [out] invoc Stores the processed arguments
/// \param [in] args The compiler invocation arguments to parse
/// \param [out] diags DiagnosticsEngine to report erros with
static bool parseVScaleArgs(CompilerInvocation &invoc, llvm::opt::ArgList &args,
                            clang::DiagnosticsEngine &diags) {
  const auto *vscaleMin = args.getLastArg(clang::options::OPT_mvscale_min_EQ);
  const auto *vscaleMax = args.getLastArg(clang::options::OPT_mvscale_max_EQ);

  if (!vscaleMin && !vscaleMax)
    return true;

  llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple);
  if (!triple.isAArch64() && !triple.isRISCV()) {
    const unsigned diagID =
        diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                              "`-mvscale-max` and `-mvscale-min` are not "
                              "supported for this architecture: %0");
    diags.Report(diagID) << triple.getArchName();
    return false;
  }

  Fortran::common::LangOptions &opts = invoc.getLangOpts();
  if (vscaleMin) {
    llvm::StringRef argValue = llvm::StringRef(vscaleMin->getValue());
    unsigned vscaleMinVal;
    if (argValue.getAsInteger(/*Radix=*/10, vscaleMinVal)) {
      diags.Report(clang::diag::err_drv_unsupported_option_argument)
          << vscaleMax->getSpelling() << argValue;
      return false;
    }
    opts.VScaleMin = vscaleMinVal;
  }

  if (vscaleMax) {
    llvm::StringRef argValue = llvm::StringRef(vscaleMax->getValue());
    unsigned vscaleMaxVal;
    if (argValue.getAsInteger(/*Radix=w*/ 10, vscaleMaxVal)) {
      diags.Report(clang::diag::err_drv_unsupported_option_argument)
          << vscaleMax->getSpelling() << argValue;
      return false;
    }
    opts.VScaleMax = vscaleMaxVal;
  }
  return true;
}

static bool parseLinkerOptionsArgs(CompilerInvocation &invoc,
                                   llvm::opt::ArgList &args,
                                   clang::DiagnosticsEngine &diags) {
  llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple);
  CodeGenOptions &opts = invoc.getCodeGenOpts();

  // TODO: support --dependent-lib on other platforms when MLIR supports
  //       !llvm.dependent.lib
  if (args.hasArg(clang::options::OPT_dependent_lib) && !triple.isOSWindows()) {
    const unsigned diagID =
        diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                              "--dependent-lib is only supported on Windows");
    diags.Report(diagID);
    return false;
  }

  opts.DependentLibs = args.getAllArgValues(clang::options::OPT_dependent_lib);

  // -flto=full/thin option.
  if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_flto_EQ)) {
    llvm::StringRef s = a->getValue();
    assert((s == "full" || s == "thin") && "Unknown LTO mode.");
    if (s == "full")
      opts.PrepareForFullLTO = true;
    else
      opts.PrepareForThinLTO = true;
  }

  // -fsplit-lto-unit option
  if (args.hasArg(clang::options::OPT_fsplit_lto_unit))
    opts.EnableSplitLTOUnit = true;

  // -ffat-lto-objects
  if (const llvm::opt::Arg *arg =
          args.getLastArg(clang::options::OPT_ffat_lto_objects,
                          clang::options::OPT_fno_fat_lto_objects)) {
    opts.PrepareForFatLTO =
        arg->getOption().matches(clang::options::OPT_ffat_lto_objects);
    if (opts.PrepareForFatLTO) {
      assert((opts.PrepareForFullLTO || opts.PrepareForThinLTO) &&
             "Unknown LTO mode");

      if (!triple.isOSBinFormatELF())
        diags.Report(clang::diag::err_drv_unsupported_opt_for_target)
            << arg->getAsString(args) << triple.getTriple();
    }
  }
  return true;
}

static bool parseLangOptionsArgs(CompilerInvocation &invoc,
                                 llvm::opt::ArgList &args,
                                 clang::DiagnosticsEngine &diags) {
  bool success = true;

  success &= parseIntegerOverflowArgs(invoc, args, diags);
  success &= parseFloatingPointArgs(invoc, args, diags);
  success &= parseVScaleArgs(invoc, args, diags);

  return success;
}

// Copied from clang/lib/Frontend/CompilerInvocation.cpp.
static void addDiagnosticArgs(llvm::opt::ArgList &args,
                              llvm::opt::OptSpecifier group,
                              llvm::opt::OptSpecifier groupWithValue,
                              std::vector<std::string> &diagnostics) {
  for (auto *a : args.filtered(group)) {
    if (a->getOption().getKind() == llvm::opt::Option::FlagClass) {
      // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
      // its name (minus the "W" or "R" at the beginning) to the diagnostics.
      diagnostics.push_back(
          std::string(a->getOption().getName().drop_front(1)));
    } else if (a->getOption().matches(groupWithValue)) {
      // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
      // group. Add only the group name to the diagnostics.
      diagnostics.push_back(
          std::string(a->getOption().getName().drop_front(1).rtrim("=-")));
    } else {
      // Otherwise, add its value (for OPT_W_Joined and similar).
      diagnostics.push_back(a->getValue());
    }
  }
}

bool CompilerInvocation::createFromArgs(
    CompilerInvocation &invoc, llvm::ArrayRef<const char *> commandLineArgs,
    clang::DiagnosticsEngine &diags, const char *argv0) {

  bool success = true;
  clang::DiagnosticOptions &diagOpts = diags.getDiagnosticOptions();

  // Set the default triple for this CompilerInvocation. This might be
  // overridden by users with `-triple` (see the call to `ParseTargetArgs`
  // below).
  // NOTE: Like in Clang, it would be nice to use option marshalling
  // for this so that the entire logic for setting-up the triple is in one
  // place.
  invoc.getTargetOpts().triple =
      llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());

  // Parse the arguments
  const llvm::opt::OptTable &opts = clang::getDriverOptTable();
  llvm::opt::Visibility visibilityMask(clang::options::FC1Option);
  unsigned missingArgIndex, missingArgCount;
  llvm::opt::InputArgList args = opts.ParseArgs(
      commandLineArgs, missingArgIndex, missingArgCount, visibilityMask);

  // Check for missing argument error.
  if (missingArgCount) {
    diags.Report(clang::diag::err_drv_missing_argument)
        << args.getArgString(missingArgIndex) << missingArgCount;
    success = false;
  }

  // Issue errors on unknown arguments
  for (const auto *a : args.filtered(clang::options::OPT_UNKNOWN)) {
    auto argString = a->getAsString(args);
    std::string nearest;
    if (opts.findNearest(argString, nearest, visibilityMask) > 1)
      diags.Report(clang::diag::err_drv_unknown_argument) << argString;
    else
      diags.Report(clang::diag::err_drv_unknown_argument_with_suggestion)
          << argString << nearest;
    success = false;
  }

  // Handle -Wno-<warning> flags.
  addDiagnosticArgs(args, clang::options::OPT_W_Group,
                    clang::options::OPT_W_value_Group, diagOpts.Warnings);
  auto vfs = llvm::vfs::getRealFileSystem();
  clang::ProcessWarningOptions(diags, diagOpts, *vfs, /*ReportDiags=*/false);

  // -fno-ppc-native-vector-element-order
  if (args.hasArg(clang::options::OPT_fno_ppc_native_vec_elem_order)) {
    invoc.loweringOpts.setNoPPCNativeVecElemOrder(true);
  }

  // -f[no-]init-global-zero
  if (args.hasFlag(clang::options::OPT_finit_global_zero,
                   clang::options::OPT_fno_init_global_zero,
                   /*default=*/true))
    invoc.loweringOpts.setInitGlobalZero(true);
  else
    invoc.loweringOpts.setInitGlobalZero(false);

  // -finit-local=<zero|0x<hex>>  and  -finit-local-zero
  // (-finit-local-zero is an alias that the driver already expands to
  //  -finit-local=zero, so we only need to handle OPT_finit_local_EQ here.)
  if (const llvm::opt::Arg *a =
          args.getLastArg(clang::options::OPT_finit_local_EQ)) {
    llvm::StringRef val = a->getValue();
    if (val == "zero") {
      invoc.loweringOpts.setInitLocalMode(Fortran::lower::InitLocalKind::Zero);
    } else if (val.starts_with("0x") || val.starts_with("0X")) {
      unsigned long long hexVal = 0;
      if (val.drop_front(2).getAsInteger(16, hexVal) || hexVal > 0xFF) {
        diags.Report(clang::diag::err_drv_invalid_value)
            << a->getAsString(args) << val;
      } else {
        invoc.loweringOpts.setInitLocalMode(Fortran::lower::InitLocalKind::Hex);
        invoc.loweringOpts.setInitLocalPattern(static_cast<uint8_t>(hexVal));
      }
    } else {
      diags.Report(clang::diag::err_drv_invalid_value)
          << a->getAsString(args) << val;
    }
  }

  // Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
  // -Rpass-analysis. This will be used later when processing and outputting the
  // remarks generated by LLVM in ExecuteCompilerInvocation.cpp.
  for (auto *a : args.filtered(clang::options::OPT_R_Group)) {
    if (a->getOption().matches(clang::options::OPT_R_value_Group))
      // This is -Rfoo=, where foo is the name of the diagnostic
      // group. Add only the remark option name to the diagnostics. e.g. for
      // -Rpass= we will add the string "pass".
      invoc.getDiagnosticOpts().Remarks.push_back(
          std::string(a->getOption().getName().drop_front(1).rtrim("=-")));
    else
      // If no regex was provided, add the provided value, e.g. for -Rpass add
      // the string "pass".
      invoc.getDiagnosticOpts().Remarks.push_back(a->getValue());
  }

  // -frealloc-lhs is the default.
  if (!args.hasFlag(clang::options::OPT_frealloc_lhs,
                    clang::options::OPT_fno_realloc_lhs, true)) {
    invoc.loweringOpts.setReallocateLHS(false);
    invoc.getLangOpts().NoReallocateLHS = true;
  }

  invoc.loweringOpts.setRepackArrays(args.hasFlag(
      clang::options::OPT_frepack_arrays, clang::options::OPT_fno_repack_arrays,
      /*default=*/false));
  invoc.loweringOpts.setStackRepackArrays(
      args.hasFlag(clang::options::OPT_fstack_repack_arrays,
                   clang::options::OPT_fno_stack_repack_arrays,
                   /*default=*/false));
  if (auto *arg =
          args.getLastArg(clang::options::OPT_frepack_arrays_contiguity_EQ))
    invoc.loweringOpts.setRepackArraysWhole(arg->getValue() ==
                                            llvm::StringRef{"whole"});

  // -f[no-]openacc-combined-loop-firstprivate
  invoc.loweringOpts.setOpenACCCombinedLoopFirstprivate(
      args.hasFlag(clang::options::OPT_fopenacc_combined_loop_firstprivate,
                   clang::options::OPT_fno_openacc_combined_loop_firstprivate,
                   /*default=*/true));

  // -f[no-]openacc-acc-kernels-do-concurrent-independent
  invoc.loweringOpts.setOpenACCKernelsDoConcurrentIndependent(args.hasFlag(
      clang::options::OPT_fopenacc_acc_kernels_do_concurrent_independent,
      clang::options::OPT_fno_openacc_acc_kernels_do_concurrent_independent,
      /*default=*/true));

  if (auto *arg = args.getLastArg(clang::options::OPT_ffp_maxmin_behavior_EQ)) {
    auto value = Fortran::common::parseFPMaxminBehavior(arg->getValue());
    invoc.getCodeGenOpts().setFPMaxminBehavior(value);
    invoc.loweringOpts.setFPMaxminBehavior(value);
  }

  success &= parseFrontendArgs(invoc.getFrontendOpts(), args, diags);
  parseTargetArgs(invoc.getTargetOpts(), args);
  parsePreprocessorArgs(invoc.getPreprocessorOpts(), args);
  parseCodeGenArgs(invoc.getCodeGenOpts(), args, diags);
  success &= parseDoConcurrentMapping(invoc.getCodeGenOpts(), args, diags);
  success &= parseDebugArgs(invoc.getCodeGenOpts(), args, diags);

  // Enable USE statement preservation for debug info if debug level is above
  // LineTablesOnly.
  using DebugInfoKind = llvm::codegenoptions::DebugInfoKind;
  DebugInfoKind debugLevel = invoc.getCodeGenOpts().getDebugInfo();
  invoc.loweringOpts.setPreserveUseDebugInfo(
      debugLevel > DebugInfoKind::DebugLineTablesOnly);

  success &= parseVectorLibArg(invoc.getCodeGenOpts(), args, diags);
  success &= parseSemaArgs(invoc, args, diags);
  success &= parseDialectArgs(invoc, args, diags);
  success &= parseOpenMPArgs(invoc, args, diags);
  success &= parseDiagArgs(invoc, args, diags);

  // Collect LLVM (-mllvm) and MLIR (-mmlir) options.
  // NOTE: Try to avoid adding any options directly to `llvmArgs` or
  // `mlirArgs`. Instead, you can use
  //    * `-mllvm <your-llvm-option>`, or
  //    * `-mmlir <your-mlir-option>`.
  invoc.frontendOpts.llvmArgs = args.getAllArgValues(clang::options::OPT_mllvm);
  invoc.frontendOpts.mlirArgs = args.getAllArgValues(clang::options::OPT_mmlir);

  if (args.hasArg(clang::options::OPT_foffload_device))
    invoc.getLangOpts().OffloadDevice = 1;

  success &= parseLangOptionsArgs(invoc, args, diags);

  success &= parseLinkerOptionsArgs(invoc, args, diags);

  // Set the string to be used as the return value of the COMPILER_OPTIONS
  // intrinsic of iso_fortran_env. This is either passed in from the parent
  // compiler driver invocation with an environment variable, or failing that
  // set to the command line arguments of the frontend driver invocation.
  invoc.allCompilerInvocOpts = std::string();
  llvm::raw_string_ostream os(invoc.allCompilerInvocOpts);
  char *compilerOptsEnv = std::getenv("FLANG_COMPILER_OPTIONS_STRING");
  if (compilerOptsEnv != nullptr) {
    os << compilerOptsEnv;
  } else {
    os << argv0 << ' ';
    for (auto it = commandLineArgs.begin(), e = commandLineArgs.end(); it != e;
         ++it) {
      os << ' ' << *it;
    }
  }

  // Process the timing-related options.
  if (args.hasArg(clang::options::OPT_ftime_report))
    invoc.enableTimers = true;

  invoc.setArgv0(argv0);

  return success;
}

void CompilerInvocation::collectMacroDefinitions() {
  auto &ppOpts = this->getPreprocessorOpts();

  for (unsigned i = 0, n = ppOpts.macros.size(); i != n; ++i) {
    llvm::StringRef macro = ppOpts.macros[i].first;
    bool isUndef = ppOpts.macros[i].second;

    std::pair<llvm::StringRef, llvm::StringRef> macroPair = macro.split('=');
    llvm::StringRef macroName = macroPair.first;
    llvm::StringRef macroBody = macroPair.second;

    // For an #undef'd macro, we only care about the name.
    if (isUndef) {
      parserOpts.predefinitions.emplace_back(macroName.str(),
                                             std::optional<std::string>{});
      continue;
    }

    // For a #define'd macro, figure out the actual definition.
    if (macroName.size() == macro.size())
      macroBody = "1";
    else {
      // Note: GCC drops anything following an end-of-line character.
      llvm::StringRef::size_type end = macroBody.find_first_of("\n\r");
      macroBody = macroBody.substr(0, end);
    }
    parserOpts.predefinitions.emplace_back(
        macroName, std::optional<std::string>(macroBody.str()));
  }
}

void CompilerInvocation::setDefaultFortranOpts() {
  auto &fortranOptions = getFortranOpts();

  std::vector<std::string> searchDirectories{"."s};
  fortranOptions.searchDirectories = searchDirectories;

  fortranOptions.isFixedForm = false;
}

// TODO: When expanding this method, consider creating a dedicated API for
// this. Also at some point we will need to differentiate between different
// targets and add dedicated predefines for each.
void CompilerInvocation::setDefaultPredefinitions() {
  auto &fortranOptions = getFortranOpts();
  const auto &frontendOptions = getFrontendOpts();
  // Populate the macro list with version numbers and other predefinitions.
  fortranOptions.predefinitions.emplace_back("__flang__", "1");
  fortranOptions.predefinitions.emplace_back("__flang_major__",
                                             FLANG_VERSION_MAJOR_STRING);
  fortranOptions.predefinitions.emplace_back("__flang_minor__",
                                             FLANG_VERSION_MINOR_STRING);
  fortranOptions.predefinitions.emplace_back("__flang_patchlevel__",
                                             FLANG_VERSION_PATCHLEVEL_STRING);

  // Add predefinitions based on the relocation model
  if (unsigned PICLevel = getCodeGenOpts().PICLevel) {
    fortranOptions.predefinitions.emplace_back("__PIC__",
                                               std::to_string(PICLevel));
    fortranOptions.predefinitions.emplace_back("__pic__",
                                               std::to_string(PICLevel));
    if (getCodeGenOpts().IsPIE) {
      fortranOptions.predefinitions.emplace_back("__PIE__",
                                                 std::to_string(PICLevel));
      fortranOptions.predefinitions.emplace_back("__pie__",
                                                 std::to_string(PICLevel));
    }
  }

  // Add predefinitions based on extensions enabled
  if (frontendOptions.features.IsEnabled(
          Fortran::common::LanguageFeature::OpenACC)) {
    fortranOptions.predefinitions.emplace_back("_OPENACC", "202211");
  }
  if (frontendOptions.features.IsEnabled(
          Fortran::common::LanguageFeature::OpenMP)) {
    Fortran::common::setOpenMPMacro(
        static_cast<unsigned>(getLangOpts().getOpenMPVersion()),
        fortranOptions.predefinitions);
  }

  if (frontendOptions.features.IsEnabled(
          Fortran::common::LanguageFeature::CUDA)) {
    fortranOptions.predefinitions.emplace_back("_CUDA", "1");
  }

  llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
  if (targetTriple.isOSLinux()) {
    fortranOptions.predefinitions.emplace_back("__linux__", "1");
  } else if (targetTriple.isOSAIX()) {
    fortranOptions.predefinitions.emplace_back("_AIX", "1");
  }

  switch (targetTriple.getArch()) {
  default:
    break;
  case llvm::Triple::ArchType::x86_64:
    fortranOptions.predefinitions.emplace_back("__x86_64__", "1");
    fortranOptions.predefinitions.emplace_back("__x86_64", "1");
    break;
  case llvm::Triple::ArchType::ppc:
  case llvm::Triple::ArchType::ppc64:
  case llvm::Triple::ArchType::ppcle:
  case llvm::Triple::ArchType::ppc64le:
    // '__powerpc__' is a generic macro for any PowerPC.
    fortranOptions.predefinitions.emplace_back("__powerpc__", "1");
    if (targetTriple.isOSAIX() && targetTriple.isArch64Bit()) {
      fortranOptions.predefinitions.emplace_back("__64BIT__", "1");
    }
    break;
  case llvm::Triple::ArchType::aarch64:
    fortranOptions.predefinitions.emplace_back("__aarch64__", "1");
    fortranOptions.predefinitions.emplace_back("__aarch64", "1");
    break;
  case llvm::Triple::ArchType::systemz:
    fortranOptions.predefinitions.emplace_back("__s390x__", "1");
    fortranOptions.predefinitions.emplace_back("__s390x", "1");
    break;
  }
}

void CompilerInvocation::setFortranOpts() {
  auto &fortranOptions = getFortranOpts();
  const auto &frontendOptions = getFrontendOpts();
  const auto &preprocessorOptions = getPreprocessorOpts();
  auto &moduleDirJ = getModuleDir();

  if (frontendOptions.fortranForm != FortranForm::Unknown) {
    fortranOptions.isFixedForm =
        frontendOptions.fortranForm == FortranForm::FixedForm;
  }
  fortranOptions.fixedFormColumns = frontendOptions.fixedFormColumns;

  // -E
  fortranOptions.prescanAndReformat =
      frontendOptions.programAction == PrintPreprocessedInput;

  fortranOptions.features = frontendOptions.features;
  fortranOptions.encoding = frontendOptions.encoding;

  // Adding search directories specified by -I
  fortranOptions.searchDirectories.insert(
      fortranOptions.searchDirectories.end(),
      preprocessorOptions.searchDirectoriesFromDashI.begin(),
      preprocessorOptions.searchDirectoriesFromDashI.end());

  // Add the ordered list of -intrinsic-modules-path
  fortranOptions.searchDirectories.insert(
      fortranOptions.searchDirectories.end(),
      preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
      preprocessorOptions.searchDirectoriesFromIntrModPath.end());

  // Add the ordered list of -fintrinsic-modules-path
  fortranOptions.intrinsicModuleDirectories.insert(
      fortranOptions.intrinsicModuleDirectories.end(),
      preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
      preprocessorOptions.searchDirectoriesFromIntrModPath.end());

  //  Add the default intrinsic module directory
  fortranOptions.intrinsicModuleDirectories.emplace_back(
      getIntrinsicDir(getArgv0()));

  // Add the directory supplied through -J/-module-dir to the list of search
  // directories
  if (moduleDirJ != ".")
    fortranOptions.searchDirectories.emplace_back(moduleDirJ);

  if (frontendOptions.instrumentedParse)
    fortranOptions.instrumentedParse = true;

  if (frontendOptions.showColors)
    fortranOptions.showColors = true;

  if (frontendOptions.needProvenanceRangeToCharBlockMappings)
    fortranOptions.needProvenanceRangeToCharBlockMappings = true;

  fortranOptions.features = frontendOptions.features;
}

std::unique_ptr<Fortran::semantics::SemanticsContext>
CompilerInvocation::getSemanticsCtx(
    Fortran::parser::AllCookedSources &allCookedSources,
    const llvm::TargetMachine &targetMachine) {
  auto &fortranOptions = getFortranOpts();

  auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
      getDefaultKinds(), fortranOptions.features, getLangOpts(),
      allCookedSources, getCodeGenOpts().getFPMaxminBehavior());

  semanticsContext->set_moduleDirectory(getModuleDir())
      .set_searchDirectories(fortranOptions.searchDirectories)
      .set_intrinsicModuleDirectories(fortranOptions.intrinsicModuleDirectories)
      .set_maxErrors(getMaxErrors())
      .set_warningsAreErrors(getWarnAsErr())
      .set_moduleFileSuffix(getModuleFileSuffix())
      .set_underscoring(getCodeGenOpts().Underscoring)
      .set_openAccDefaultNoneScalarsStrictDisableOption(
          clang::getDriverOptTable()
              .getOptionPrefixedName(
                  clang::options::OPT_fno_openacc_default_none_scalars_strict)
              .str())
      .set_targetTriple(targetMachine.getTargetTriple().str())
      .set_targetFeatures(targetMachine.getTargetFeatureString().str());

  std::string compilerVersion = Fortran::common::getFlangFullVersion();
  Fortran::tools::setUpTargetCharacteristics(
      semanticsContext->targetCharacteristics(), targetMachine, getTargetOpts(),
      compilerVersion, allCompilerInvocOpts);
  return semanticsContext;
}

/// Set \p loweringOptions controlling lowering behavior based
/// on the \p optimizationLevel.
void CompilerInvocation::setLoweringOptions() {
  const CodeGenOptions &codegenOpts = getCodeGenOpts();

  // Lower TRANSPOSE as a runtime call under -O0.
  loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
  loweringOpts.setUnderscoring(codegenOpts.Underscoring);
  loweringOpts.setSkipExternalRttiDefinition(skipExternalRttiDefinition);

  const Fortran::common::LangOptions &langOptions = getLangOpts();
  loweringOpts.setIntegerWrapAround(langOptions.getSignedOverflowBehavior() ==
                                    Fortran::common::LangOptions::SOB_Defined);
  loweringOpts.setProtectParens(codegenOpts.ProtectParens);
  loweringOpts.setSplitSumExpressionTree(codegenOpts.SplitSumExpressionTree);
  Fortran::common::MathOptionsBase &mathOpts = loweringOpts.getMathOptions();
  // TODO: when LangOptions are finalized, we can represent
  //       the math related options using Fortran::commmon::MathOptionsBase,
  //       so that we can just copy it into LoweringOptions.
  mathOpts
      .setFPContractEnabled(langOptions.getFPContractMode() ==
                            Fortran::common::LangOptions::FPM_Fast)
      .setNoHonorInfs(langOptions.NoHonorInfs)
      .setNoHonorNaNs(langOptions.NoHonorNaNs)
      .setApproxFunc(langOptions.ApproxFunc)
      .setNoSignedZeros(langOptions.NoSignedZeros)
      .setAssociativeMath(langOptions.AssociativeMath)
      .setReciprocalMath(langOptions.ReciprocalMath);

  if (codegenOpts.getComplexRange() ==
          CodeGenOptions::ComplexRangeKind::CX_Improved ||
      codegenOpts.getComplexRange() ==
          CodeGenOptions::ComplexRangeKind::CX_Basic)
    loweringOpts.setComplexDivisionToRuntime(false);

  loweringOpts.setFPExceptionTraps(langOptions.FPExceptionTraps);
}
