//===- 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 <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, false))
    opts.SplitSumExpressionTree = 1;

  if (args.getLastArg(clang::options::OPT_floop_interchange))
    opts.InterchangeLoops = 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;

  // -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 (args.hasArg(clang::options::OPT_fprofile_generate)) {
    opts.setProfileInstr(llvm::driver::ProfileInstrKind::ProfileIRInstr);
  }

  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)) {
    opts.abi = a->getValue();
    llvm::StringRef V = a->getValue();
    if (V == "vec-extabi") {
      opts.EnableAIXExtendedAltivecABI = true;
    } else if (V == "vec-default") {
      opts.EnableAIXExtendedAltivecABI = false;
    }
  }

  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 = 1000000;
    } else if (columns < 7) {
      diags.Report(clang::diag::err_drv_small_columns)
          << arg->getOption().getName() << arg->getValue() << "7";
    } 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-}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-}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::ArrayRef<unsigned> ompVersions = llvm::omp::getOpenMPVersions();
    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;
  }

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

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

  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(getLangOpts().OpenMPVersion,
                                    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;
  }
}

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