[flang-commits] [flang] [flang] Fix compiler invocation issue (#232487) (PR #235472)

via flang-commits flang-commits at lists.llvm.org
Sun Oct 25 08:40:00 PDT 2026


https://github.com/Harshit2906 created https://github.com/llvm/llvm-project/pull/235472

Fixes #232487

>From 06e60c6471d0ef8ccc795e95bd35d9b5b65aaa77 Mon Sep 17 00:00:00 2001
From: Harshit <harshitjhiraparaharshit at gmail.com>
Date: Sun, 25 Oct 2026 21:04:57 +0530
Subject: [PATCH] [flang] Fix compiler invocation issue (#232487)

---
 flang/lib/Frontend/CompilerInvocation.cpp | 1751 +++++----------------
 1 file changed, 365 insertions(+), 1386 deletions(-)

diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 38e66aad693cbc..46c6c87f534811 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -11,44 +11,34 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Frontend/CompilerInvocation.h"
+#include "flang/Common/Fortran-features.h"
+#include "flang/Common/OpenMP-features.h"
+#include "flang/Common/Version.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/AllDiagnostics.h"
 #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/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/OptionUtils.h"
+#include "clang/Driver/Options.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/FileUtilities.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>
 
@@ -73,8 +63,8 @@ CompilerInvocationBase::~CompilerInvocationBase() = default;
 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.
+  // compiler driver `flang-new` but default to off in the frontend driver
+  // `flang-new -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 {
@@ -85,11 +75,11 @@ static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
 
   for (auto *a : args) {
     const llvm::opt::Option &opt = a->getOption();
-    if (opt.matches(clang::options::OPT_fcolor_diagnostics)) {
+    if (opt.matches(clang::driver::options::OPT_fcolor_diagnostics)) {
       showColors = Colors_On;
-    } else if (opt.matches(clang::options::OPT_fno_color_diagnostics)) {
+    } else if (opt.matches(clang::driver::options::OPT_fno_color_diagnostics)) {
       showColors = Colors_Off;
-    } else if (opt.matches(clang::options::OPT_fdiagnostics_color_EQ)) {
+    } else if (opt.matches(clang::driver::options::OPT_fdiagnostics_color_EQ)) {
       llvm::StringRef value(a->getValue());
       if (value == "always")
         showColors = Colors_On;
@@ -108,15 +98,17 @@ static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
 /// Extracts the optimisation level from \a args.
 static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
                                      clang::DiagnosticsEngine &diags) {
-  unsigned defaultOpt = 0;
+  unsigned defaultOpt = llvm::CodeGenOpt::None;
 
-  if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_O_Group)) {
-    if (a->getOption().matches(clang::options::OPT_O0))
-      return 0;
+  if (llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::options::OPT_O_Group)) {
+    if (a->getOption().matches(clang::driver::options::OPT_O0))
+      return llvm::CodeGenOpt::None;
 
-    assert(a->getOption().matches(clang::options::OPT_O));
+    assert(a->getOption().matches(clang::driver::options::OPT_O));
 
-    return getLastArgIntValue(args, clang::options::OPT_O, defaultOpt, diags);
+    return getLastArgIntValue(args, clang::driver::options::OPT_O, defaultOpt,
+                              diags);
   }
 
   return defaultOpt;
@@ -124,8 +116,7 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
 
 bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
                                             llvm::opt::ArgList &args) {
-  opts.setShowColors(parseShowColorsArgs(args) ? clang::ShowColorsKind::On
-                                               : clang::ShowColorsKind::Off);
+  opts.ShowColors = parseShowColorsArgs(args);
 
   return true;
 }
@@ -135,7 +126,7 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
                            clang::DiagnosticsEngine &diags) {
   using DebugInfoKind = llvm::codegenoptions::DebugInfoKind;
   if (llvm::opt::Arg *arg =
-          args.getLastArg(clang::options::OPT_debug_info_kind_EQ)) {
+          args.getLastArg(clang::driver::options::OPT_debug_info_kind_EQ)) {
     std::optional<DebugInfoKind> val =
         llvm::StringSwitch<std::optional<DebugInfoKind>>(arg->getValue())
             .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
@@ -153,337 +144,58 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
     }
     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))
+  if (args.hasFlag(clang::driver::options::OPT_fdebug_pass_manager,
+                   clang::driver::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))
+  if (args.hasFlag(clang::driver::options::OPT_fstack_arrays,
+                   clang::driver::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))
+  }
+  if (args.hasFlag(clang::driver::options::OPT_floop_versioning,
+                   clang::driver::options::OPT_fno_loop_versioning, false)) {
     opts.LoopVersioning = 1;
-
-  if (args.hasFlag(clang::options::OPT_floop_tripcount_versioning,
-                   clang::options::OPT_fno_loop_tripcount_versioning, false))
-    opts.LoopTripCountVersioning = 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))
+  for (auto *a : args.filtered(clang::driver::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))
+  for (auto *a :
+       args.filtered(clang::driver::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);
-
+  // -flto=full/thin option.
   if (const llvm::opt::Arg *a =
-          args.getLastArg(clang::options::OPT_mcode_object_version_EQ)) {
+          args.getLastArg(clang::driver::options::OPT_flto_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);
+    assert((s == "full" || s == "thin") && "Unknown LTO mode.");
+    if (s == "full")
+      opts.PrepareForFullLTO = true;
+    else
+      opts.PrepareForThinLTO = true;
   }
 
-  if (auto *a = args.getLastArg(clang::options::OPT_save_temps_EQ))
+  if (auto *a = args.getLastArg(clang::driver::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)) {
+          args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
     llvm::StringRef modelName = a->getValue();
     auto relocModel =
         llvm::StringSwitch<std::optional<llvm::Reloc::Model>>(modelName)
@@ -502,85 +214,24 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
   }
 
   // -pic-level and -pic-is-pie option.
-  if (int picLevel =
-          getLastArgIntValue(args, clang::options::OPT_pic_level, 0, diags)) {
+  if (int picLevel = getLastArgIntValue(
+          args, clang::driver::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)
+          << args.getLastArg(clang::driver::options::OPT_pic_level)
+                 ->getAsString(args)
           << picLevel;
 
     opts.PICLevel = picLevel;
-    if (args.hasArg(clang::options::OPT_pic_is_pie))
+    if (args.hasArg(clang::driver::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)) {
+  if (args.hasFlag(clang::driver::options::OPT_fno_underscoring,
+                   clang::driver::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
@@ -589,54 +240,19 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
 /// \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))
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::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))
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::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))
+       args.filtered(clang::driver::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)
@@ -660,120 +276,113 @@ static std::optional<const char *> parseConvertArg(const char *s) {
 
 static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
                               clang::DiagnosticsEngine &diags) {
+  unsigned numErrorsBefore = diags.getNumErrors();
+
   // 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;
+  if (args.hasMultipleArgs(clang::driver::options::OPT_Action_Group)) {
+    const unsigned diagID = diags.getCustomDiagID(
+        clang::DiagnosticsEngine::Error, "Only one action option is allowed");
+    diags.Report(diagID);
     return false;
   }
 
   // Identify the action (i.e. opts.ProgramAction)
   if (const llvm::opt::Arg *a =
-          args.getLastArg(clang::options::OPT_Action_Group)) {
+          args.getLastArg(clang::driver::options::OPT_Action_Group)) {
     switch (a->getOption().getID()) {
     default: {
       llvm_unreachable("Invalid option in group!");
     }
-    case clang::options::OPT_test_io:
+    case clang::driver::options::OPT_test_io:
       opts.programAction = InputOutputTest;
       break;
-    case clang::options::OPT_E:
+    case clang::driver::options::OPT_E:
       opts.programAction = PrintPreprocessedInput;
       break;
-    case clang::options::OPT_fsyntax_only:
+    case clang::driver::options::OPT_fsyntax_only:
       opts.programAction = ParseSyntaxOnly;
       break;
-    case clang::options::OPT_emit_fir:
+    case clang::driver::options::OPT_emit_fir:
       opts.programAction = EmitFIR;
       break;
-    case clang::options::OPT_emit_hlfir:
+    case clang::driver::options::OPT_emit_hlfir:
       opts.programAction = EmitHLFIR;
       break;
-    case clang::options::OPT_emit_llvm:
+    case clang::driver::options::OPT_emit_llvm:
       opts.programAction = EmitLLVM;
       break;
-    case clang::options::OPT_emit_llvm_bc:
+    case clang::driver::options::OPT_emit_llvm_bc:
       opts.programAction = EmitLLVMBitcode;
       break;
-    case clang::options::OPT_emit_obj:
+    case clang::driver::options::OPT_emit_obj:
       opts.programAction = EmitObj;
       break;
-    case clang::options::OPT_S:
+    case clang::driver::options::OPT_S:
       opts.programAction = EmitAssembly;
       break;
-    case clang::options::OPT_fdebug_unparse:
+    case clang::driver::options::OPT_fdebug_unparse:
       opts.programAction = DebugUnparse;
       break;
-    case clang::options::OPT_fdebug_unparse_no_sema:
+    case clang::driver::options::OPT_fdebug_unparse_no_sema:
       opts.programAction = DebugUnparseNoSema;
       break;
-    case clang::options::OPT_fdebug_unparse_with_symbols:
+    case clang::driver::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:
+    case clang::driver::options::OPT_fdebug_dump_symbols:
       opts.programAction = DebugDumpSymbols;
       break;
-    case clang::options::OPT_fdebug_dump_parse_tree:
+    case clang::driver::options::OPT_fdebug_dump_parse_tree:
       opts.programAction = DebugDumpParseTree;
       break;
-    case clang::options::OPT_fdebug_dump_pft:
+    case clang::driver::options::OPT_fdebug_dump_pft:
       opts.programAction = DebugDumpPFT;
       break;
-    case clang::options::OPT_fdebug_dump_all:
+    case clang::driver::options::OPT_fdebug_dump_all:
       opts.programAction = DebugDumpAll;
       break;
-    case clang::options::OPT_fdebug_dump_parse_tree_no_sema:
+    case clang::driver::options::OPT_fdebug_dump_parse_tree_no_sema:
       opts.programAction = DebugDumpParseTreeNoSema;
       break;
-    case clang::options::OPT_fdebug_dump_provenance:
+    case clang::driver::options::OPT_fdebug_dump_provenance:
       opts.programAction = DebugDumpProvenance;
       break;
-    case clang::options::OPT_fdebug_dump_parsing_log:
+    case clang::driver::options::OPT_fdebug_dump_parsing_log:
       opts.programAction = DebugDumpParsingLog;
       break;
-    case clang::options::OPT_fdebug_measure_parse_tree:
+    case clang::driver::options::OPT_fdebug_measure_parse_tree:
       opts.programAction = DebugMeasureParseTree;
       break;
-    case clang::options::OPT_fdebug_pre_fir_tree:
+    case clang::driver::options::OPT_fdebug_pre_fir_tree:
       opts.programAction = DebugPreFIRTree;
       break;
-    case clang::options::OPT_fget_symbols_sources:
+    case clang::driver::options::OPT_fget_symbols_sources:
       opts.programAction = GetSymbolsSources;
       break;
-    case clang::options::OPT_fget_definition:
+    case clang::driver::options::OPT_fget_definition:
       opts.programAction = GetDefinition;
       break;
-    case clang::options::OPT_init_only:
+    case clang::driver::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:
+      // case clang::driver::options::OPT_emit_llvm:
+      // case clang::driver::options::OPT_emit_llvm_only:
+      // case clang::driver::options::OPT_emit_codegen_only:
+      // case clang::driver::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) {
+        clang::driver::options::OPT_fget_definition) {
       unsigned optVals[3] = {0, 0, 0};
 
       for (unsigned i = 0; i < 3; i++) {
@@ -793,28 +402,25 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
   }
 
   // Parsing -load <dsopath> option and storing shared object path
-  if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_load)) {
+  if (llvm::opt::Arg *a = args.getLastArg(clang::driver::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)) {
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::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);
+  opts.outputFile = args.getLastArgValue(clang::driver::options::OPT_o);
+  opts.showHelp = args.hasArg(clang::driver::options::OPT_help);
+  opts.showVersion = args.hasArg(clang::driver::options::OPT_version);
 
   // 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)) {
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::options::OPT_x)) {
     llvm::StringRef xValue = a->getValue();
     // Principal languages.
     dashX = llvm::StringSwitch<InputKind>(xValue)
@@ -822,8 +428,6 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
                 // 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.
@@ -841,7 +445,7 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
 
   // Collect the input files and save them in our instance of FrontendOptions.
   std::vector<std::string> inputs =
-      args.getAllArgValues(clang::options::OPT_INPUT);
+      args.getAllArgValues(clang::driver::options::OPT_INPUT);
   opts.inputs.clear();
   if (inputs.empty())
     // '-' is the default input if none is given.
@@ -861,47 +465,53 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
   }
 
   // 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;
+  if (const auto *arg =
+          args.getLastArg(clang::driver::options::OPT_ffixed_form,
+                          clang::driver::options::OPT_ffree_form)) {
+    opts.fortranForm =
+        arg->getOption().matches(clang::driver::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)) {
+          args.getLastArg(clang::driver::options::OPT_ffixed_line_length_EQ)) {
     llvm::StringRef argValue = llvm::StringRef(arg->getValue());
+    bool correctness_of_input = !argValue.empty();
+    for(auto char_in_string: argValue) {
+      if(char_in_string>='0' && char_in_string<='9') {
+        continue;
+      } else {
+        correctness_of_input=false;
+        break;
+      }
+    }
     std::int64_t columns = -1;
     if (argValue == "none") {
       columns = 0;
     } else if (argValue.getAsInteger(/*Radix=*/10, columns)) {
-      if (!argValue.empty() && llvm::all_of(argValue, llvm::isDigit)) {
-        // Route oversized positive decimals to the large-columns diagnostic.
-        columns = std::numeric_limits<std::int64_t>::max();
-      } else {
-        columns = -1;
-      }
+      columns = -1;
     }
-    if (columns < 0) {
+    if(correctness_of_input && columns==-1) {
+      diags.Report(clang::diag::err_drv_large_columns)
+      << arg->getOption().getName() << arg->getValue();
+    } else if (columns < 0) {
       diags.Report(clang::diag::err_drv_negative_columns)
           << arg->getOption().getName() << arg->getValue();
     } else if (columns == 0) {
-      opts.fixedFormColumns = std::nullopt;
+      opts.fixedFormColumns = 1000000;
     } 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)) {
+  if (const auto *arg =
+          args.getLastArg(clang::driver::options::OPT_fconvert_EQ)) {
     const char *argValue = arg->getValue();
     if (auto convert = parseConvertArg(argValue))
       opts.envDefaults.push_back({"FORT_CONVERT", *convert});
@@ -911,96 +521,41 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
   }
 
   // -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));
+      Fortran::common::LanguageFeature::ImplicitNoneTypeAlways,
+      args.hasFlag(clang::driver::options::OPT_fimplicit_none,
+                   clang::driver::options::OPT_fno_implicit_none, false));
 
   // -f{no-}backslash
   opts.features.Enable(Fortran::common::LanguageFeature::BackslashEscapes,
-                       args.hasFlag(clang::options::OPT_fbackslash,
-                                    clang::options::OPT_fno_backslash, false));
+                       args.hasFlag(clang::driver::options::OPT_fbackslash,
+                                    clang::driver::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));
-
-  // -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,
+      args.hasFlag(clang::driver::options::OPT_flogical_abbreviations,
+                   clang::driver::options::OPT_fno_logical_abbreviations,
                    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));
+  opts.features.Enable(
+      Fortran::common::LanguageFeature::XOROperator,
+      args.hasFlag(clang::driver::options::OPT_fxor_operator,
+                   clang::driver::options::OPT_fno_xor_operator, false));
 
   // -fno-automatic
-  if (args.hasArg(clang::options::OPT_fno_automatic)) {
+  if (args.hasArg(clang::driver::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)) {
+  if (args.hasArg(
+          clang::driver::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)) {
+          args.getLastArg(clang::driver::options::OPT_finput_charset_EQ)) {
     llvm::StringRef argValue = arg->getValue();
     if (argValue == "utf-8") {
       opts.encoding = Fortran::parser::Encoding::UTF_8;
@@ -1015,19 +570,28 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
   setUpFrontendBasedOnAction(opts);
   opts.dashX = dashX;
 
-  return !diags.hasUncompilableErrorOccurred();
+  return diags.getNumErrors() == numErrorsBefore;
 }
 
 // Generate the path to look for intrinsic modules
-static std::string getIntrinsicDir(const char *argv) {
+static std::string getIntrinsicDir() {
   // TODO: Find a system independent API
   llvm::SmallString<128> driverPath;
-  driverPath.assign(llvm::sys::fs::getMainExecutable(argv, nullptr));
+  driverPath.assign(llvm::sys::fs::getMainExecutable(nullptr, nullptr));
   llvm::sys::path::remove_filename(driverPath);
   driverPath.append("/../include/flang/");
   return std::string(driverPath);
 }
 
+// Generate the path to look for OpenMP headers
+static std::string getOpenMPHeadersDir() {
+  llvm::SmallString<128> includePath;
+  includePath.assign(llvm::sys::fs::getMainExecutable(nullptr, nullptr));
+  llvm::sys::path::remove_filename(includePath);
+  includePath.append("/../include/flang/OpenMP/");
+  return std::string(includePath);
+}
+
 /// Parses all preprocessor input arguments and populates the preprocessor
 /// options accordingly.
 ///
@@ -1036,9 +600,9 @@ static std::string getIntrinsicDir(const char *argv) {
 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)) {
+  for (const auto *currentArg : args.filtered(clang::driver::options::OPT_D,
+                                              clang::driver::options::OPT_U)) {
+    if (currentArg->getOption().matches(clang::driver::options::OPT_D)) {
       opts.addMacroDef(currentArg->getValue());
     } else {
       opts.addMacroUndef(currentArg->getValue());
@@ -1046,212 +610,116 @@ static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
   }
 
   // Add the ordered list of -I's.
-  for (const auto *currentArg : args.filtered(clang::options::OPT_I))
+  for (const auto *currentArg : args.filtered(clang::driver::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))
+       args.filtered(clang::driver::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);
+  if (const auto *currentArg = args.getLastArg(
+          clang::driver::options::OPT_cpp, clang::driver::options::OPT_nocpp))
+    opts.macrosFlag =
+        (currentArg->getOption().matches(clang::driver::options::OPT_cpp))
+            ? PPMacrosFlag::Include
+            : PPMacrosFlag::Exclude;
+
+  opts.noReformat = args.hasArg(clang::driver::options::OPT_fno_reformat);
+  opts.noLineDirectives = args.hasArg(clang::driver::options::OPT_P);
 }
 
 /// 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) {
+  unsigned numErrorsBefore = diags.getNumErrors();
+
   // -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.
+  auto moduleDirList =
+      args.getAllArgValues(clang::driver::options::OPT_module_dir);
+  // User can only specify -J/-module-dir once
   // 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.");
+                              "Only one '-module-dir/-J' option allowed");
     diags.Report(diagID);
   }
   if (moduleDirList.size() == 1)
     res.setModuleDir(moduleDirList[0]);
 
   // -fdebug-module-writer option
-  if (args.hasArg(clang::options::OPT_fdebug_module_writer)) {
+  if (args.hasArg(clang::driver::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)) {
+          args.getLastArg(clang::driver::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));
+  res.setUseAnalyzedObjectsForUnparse(args.hasFlag(
+      clang::driver::options::OPT_fanalyzed_objects_for_unparse,
+      clang::driver::options::OPT_fno_analyzed_objects_for_unparse, true));
 
-  return !diags.hasUncompilableErrorOccurred();
+  return diags.getNumErrors() == numErrorsBefore;
 }
 
 /// 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();
-  }
+  unsigned numErrorsBefore = diags.getNumErrors();
 
   // -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 (args.hasArg(clang::driver::options::OPT_W_Joined)) {
+    const auto &wArgs =
+        args.getAllArgValues(clang::driver::options::OPT_W_Joined);
+    for (const auto &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;
+        const unsigned diagID =
+            diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
+                                  "Only `-Werror` is supported currently.");
+        diags.Report(diagID);
       }
     }
   }
 
-  // -w
-  if (args.hasArg(clang::options::OPT_w)) {
-    features.DisableAllWarnings();
-    res.setDisableWarnings();
-  }
+  // Default to off for `flang-new -fc1`.
+  res.getFrontendOpts().showColors =
+      parseShowColorsArgs(args, /*defaultDiagColor=*/false);
 
-  // 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();
+  return diags.getNumErrors() == numErrorsBefore;
 }
 
 /// 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);
-    }
-  }
+  unsigned numErrorsBefore = diags.getNumErrors();
 
   // -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 (args.hasArg(clang::driver::options::OPT_fdefault_real_8)) {
+    res.getDefaultKinds().set_defaultRealKind(8);
+    res.getDefaultKinds().set_doublePrecisionKind(16);
   }
-  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::driver::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);
   }
-  if (args.hasArg(clang::options::OPT_fdefault_double_8)) {
-    if (!args.hasArg(clang::options::OPT_fdefault_real_8)) {
+  if (args.hasArg(clang::driver::options::OPT_fdefault_double_8)) {
+    if (!args.hasArg(clang::driver::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(
@@ -1262,31 +730,102 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     // https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html
     res.getDefaultKinds().set_doublePrecisionKind(8);
   }
-  if (args.hasArg(clang::options::OPT_flarge_sizes))
+  if (args.hasArg(clang::driver::options::OPT_flarge_sizes))
     res.getDefaultKinds().set_sizeIntegerKind(8);
 
-  // -x cuda
-  auto language = args.getLastArgValue(clang::options::OPT_x);
-  if (language == "cuda") {
+  // -fopenmp and -fopenacc
+  if (args.hasArg(clang::driver::options::OPT_fopenacc)) {
     res.getFrontendOpts().features.Enable(
-        Fortran::common::LanguageFeature::CUDA);
+        Fortran::common::LanguageFeature::OpenACC);
   }
-
-  // -fopenacc
-  if (args.hasArg(clang::options::OPT_fopenacc)) {
+  if (args.hasArg(clang::driver::options::OPT_fopenmp)) {
+    // By default OpenMP is set to 1.1 version
+    res.getLangOpts().OpenMPVersion = 11;
     res.getFrontendOpts().features.Enable(
-        Fortran::common::LanguageFeature::OpenACC);
+        Fortran::common::LanguageFeature::OpenMP);
+    if (int Version = getLastArgIntValue(
+            args, clang::driver::options::OPT_fopenmp_version_EQ,
+            res.getLangOpts().OpenMPVersion, diags)) {
+      res.getLangOpts().OpenMPVersion = Version;
+    }
+    if (args.hasArg(clang::driver::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::driver::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_drv_omp_host_ir_file_not_found)
+              << res.getLangOpts().OMPHostIRFile;
+      }
+
+      if (args.hasFlag(
+              clang::driver::options::OPT_fopenmp_assume_teams_oversubscription,
+              clang::driver::options::
+                  OPT_fno_openmp_assume_teams_oversubscription,
+              /*Default=*/false))
+        res.getLangOpts().OpenMPTeamSubscription = true;
+
+      if (args.hasArg(
+              clang::driver::options::OPT_fopenmp_assume_no_thread_state))
+        res.getLangOpts().OpenMPNoThreadState = 1;
+
+      if (args.hasArg(
+              clang::driver::options::OPT_fopenmp_assume_no_nested_parallelism))
+        res.getLangOpts().OpenMPNoNestedParallelism = 1;
+
+      if (args.hasFlag(clang::driver::options::
+                           OPT_fopenmp_assume_threads_oversubscription,
+                       clang::driver::options::
+                           OPT_fno_openmp_assume_threads_oversubscription,
+                       /*Default=*/false))
+        res.getLangOpts().OpenMPThreadSubscription = true;
+
+      if ((args.hasArg(clang::driver::options::OPT_fopenmp_target_debug) ||
+           args.hasArg(clang::driver::options::OPT_fopenmp_target_debug_EQ))) {
+        res.getLangOpts().OpenMPTargetDebug = getLastArgIntValue(
+            args, clang::driver::options::OPT_fopenmp_target_debug_EQ,
+            res.getLangOpts().OpenMPTargetDebug, diags);
+
+        if (!res.getLangOpts().OpenMPTargetDebug &&
+            args.hasArg(clang::driver::options::OPT_fopenmp_target_debug))
+          res.getLangOpts().OpenMPTargetDebug = 1;
+      }
+    }
+
+    switch (llvm::Triple(res.getTargetOpts().triple).getArch()) {
+    case llvm::Triple::nvptx:
+    case llvm::Triple::nvptx64:
+    case llvm::Triple::amdgcn:
+      if (!res.getLangOpts().OpenMPIsTargetDevice) {
+        const unsigned diagID = diags.getCustomDiagID(
+            clang::DiagnosticsEngine::Error,
+            "OpenMP AMDGPU/NVPTX is only prepared to deal with device code.");
+        diags.Report(diagID);
+      }
+      res.getLangOpts().OpenMPIsGPU = 1;
+      break;
+    default:
+      res.getLangOpts().OpenMPIsGPU = 0;
+      break;
+    }
   }
 
+  // -pedantic
+  if (args.hasArg(clang::driver::options::OPT_pedantic)) {
+    res.setEnableConformanceChecks();
+    res.setEnableUsageChecks();
+  }
   // -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);
+  if (args.hasArg(clang::driver::options::OPT_std_EQ)) {
+    auto standard = args.getLastArgValue(clang::driver::options::OPT_std_EQ);
     // We only allow f2018 as the given standard
-    if (standard == "f2018") {
+    if (standard.equals("f2018")) {
       res.setEnableConformanceChecks();
-      res.getFrontendOpts().features.WarnOnAllNonstandard();
     } else {
       const unsigned diagID =
           diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
@@ -1294,241 +833,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
       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;
+  return diags.getNumErrors() == numErrorsBefore;
 }
 
 /// Parses all floating point related arguments and populates the
@@ -1541,17 +846,17 @@ static void setIEEEFPModesArgs(Fortran::common::LangOptions &opts,
 static bool parseFloatingPointArgs(CompilerInvocation &invoc,
                                    llvm::opt::ArgList &args,
                                    clang::DiagnosticsEngine &diags) {
-  Fortran::common::LangOptions &opts = invoc.getLangOpts();
+  LangOptions &opts = invoc.getLangOpts();
 
   if (const llvm::opt::Arg *a =
-          args.getLastArg(clang::options::OPT_ffp_contract)) {
+          args.getLastArg(clang::driver::options::OPT_ffp_contract)) {
     const llvm::StringRef val = a->getValue();
-    enum Fortran::common::LangOptions::FPModeKind fpContractMode;
+    enum LangOptions::FPModeKind fpContractMode;
 
     if (val == "off")
-      fpContractMode = Fortran::common::LangOptions::FPM_Off;
+      fpContractMode = LangOptions::FPM_Off;
     else if (val == "fast")
-      fpContractMode = Fortran::common::LangOptions::FPM_Fast;
+      fpContractMode = LangOptions::FPM_Fast;
     else {
       diags.Report(clang::diag::err_drv_unsupported_option_argument)
           << a->getSpelling() << val;
@@ -1561,200 +866,48 @@ static bool parseFloatingPointArgs(CompilerInvocation &invoc,
     opts.setFPContractMode(fpContractMode);
   }
 
-  if (args.getLastArg(clang::options::OPT_menable_no_infs)) {
+  if (args.getLastArg(clang::driver::options::OPT_menable_no_infinities)) {
     opts.NoHonorInfs = true;
   }
 
-  if (args.getLastArg(clang::options::OPT_menable_no_nans)) {
+  if (args.getLastArg(clang::driver::options::OPT_menable_no_nans)) {
     opts.NoHonorNaNs = true;
   }
 
-  if (args.getLastArg(clang::options::OPT_fapprox_func)) {
+  if (args.getLastArg(clang::driver::options::OPT_fapprox_func)) {
     opts.ApproxFunc = true;
   }
 
-  if (args.getLastArg(clang::options::OPT_fno_signed_zeros)) {
+  if (args.getLastArg(clang::driver::options::OPT_fno_signed_zeros)) {
     opts.NoSignedZeros = true;
   }
 
-  if (args.getLastArg(clang::options::OPT_mreassociate)) {
+  if (args.getLastArg(clang::driver::options::OPT_mreassociate)) {
     opts.AssociativeMath = true;
   }
 
-  if (args.getLastArg(clang::options::OPT_freciprocal_math)) {
+  if (args.getLastArg(clang::driver::options::OPT_freciprocal_math)) {
     opts.ReciprocalMath = true;
   }
 
-  if (args.getLastArg(clang::options::OPT_ffast_math)) {
+  if (args.getLastArg(clang::driver::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;
+    opts.setFPContractMode(LangOptions::FPM_Fast);
   }
 
-  // -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,
+    CompilerInvocation &res, 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`
@@ -1762,15 +915,15 @@ bool CompilerInvocation::createFromArgs(
   // 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 =
+  res.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);
+  const llvm::opt::OptTable &opts = clang::driver::getDriverOptTable();
+  const unsigned includedFlagsBitmask = clang::driver::options::FC1Option;
   unsigned missingArgIndex, missingArgCount;
   llvm::opt::InputArgList args = opts.ParseArgs(
-      commandLineArgs, missingArgIndex, missingArgCount, visibilityMask);
+      commandLineArgs, missingArgIndex, missingArgCount, includedFlagsBitmask);
 
   // Check for missing argument error.
   if (missingArgCount) {
@@ -1780,10 +933,10 @@ bool CompilerInvocation::createFromArgs(
   }
 
   // Issue errors on unknown arguments
-  for (const auto *a : args.filtered(clang::options::OPT_UNKNOWN)) {
+  for (const auto *a : args.filtered(clang::driver::options::OPT_UNKNOWN)) {
     auto argString = a->getAsString(args);
     std::string nearest;
-    if (opts.findNearest(argString, nearest, visibilityMask) > 1)
+    if (opts.findNearest(argString, nearest, includedFlagsBitmask) > 1)
       diags.Report(clang::diag::err_drv_unknown_argument) << argString;
     else
       diags.Report(clang::diag::err_drv_unknown_argument_with_suggestion)
@@ -1791,142 +944,43 @@ bool CompilerInvocation::createFromArgs(
     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);
+  // -flang-experimental-hlfir
+  if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir) ||
+      args.hasArg(clang::driver::options::OPT_emit_hlfir)) {
+    res.loweringOpts.setLowerToHighLevelFIR(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;
-    }
+  if (args.hasArg(clang::driver::options::OPT_flang_experimental_polymorphism)) {
+    res.loweringOpts.setPolymorphicTypeImpl(true);
   }
 
-  // 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);
+  success &= parseFrontendArgs(res.getFrontendOpts(), args, diags);
+  parseTargetArgs(res.getTargetOpts(), args);
+  parsePreprocessorArgs(res.getPreprocessorOpts(), args);
+  parseCodeGenArgs(res.getCodeGenOpts(), args, diags);
+  success &= parseDebugArgs(res.getCodeGenOpts(), args, diags);
+  success &= parseSemaArgs(res, args, diags);
+  success &= parseDialectArgs(res, args, diags);
+  success &= parseDiagArgs(res, 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);
+  res.frontendOpts.llvmArgs =
+      args.getAllArgValues(clang::driver::options::OPT_mllvm);
+  res.frontendOpts.mlirArgs =
+      args.getAllArgValues(clang::driver::options::OPT_mmlir);
 
-  success &= parseLinkerOptionsArgs(invoc, args, diags);
+  success &= parseFloatingPointArgs(res, 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);
+  res.allCompilerInvocOpts = std::string();
+  llvm::raw_string_ostream os(res.allCompilerInvocOpts);
   char *compilerOptsEnv = std::getenv("FLANG_COMPILER_OPTIONS_STRING");
   if (compilerOptsEnv != nullptr) {
     os << compilerOptsEnv;
@@ -1938,12 +992,6 @@ bool CompilerInvocation::createFromArgs(
     }
   }
 
-  // Process the timing-related options.
-  if (args.hasArg(clang::options::OPT_ftime_report))
-    invoc.enableTimers = true;
-
-  invoc.setArgv0(argv0);
-
   return success;
 }
 
@@ -1984,6 +1032,10 @@ void CompilerInvocation::setDefaultFortranOpts() {
   std::vector<std::string> searchDirectories{"."s};
   fortranOptions.searchDirectories = searchDirectories;
 
+  // Add the location of omp_lib.h to the search directories. Currently this is
+  // identical to the modules' directory.
+  fortranOptions.searchDirectories.emplace_back(getOpenMPHeadersDir());
+
   fortranOptions.isFixedForm = false;
 }
 
@@ -2002,20 +1054,6 @@ void CompilerInvocation::setDefaultPredefinitions() {
   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)) {
@@ -2023,48 +1061,13 @@ void CompilerInvocation::setDefaultPredefinitions() {
   }
   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");
+    Fortran::common::setOpenMPMacro(getLangOpts().OpenMPVersion,
+                                    fortranOptions.predefinitions);
   }
-
   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:
+  if (targetTriple.getArch() == 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;
   }
 }
 
@@ -2080,10 +1083,6 @@ void CompilerInvocation::setFortranOpts() {
   }
   fortranOptions.fixedFormColumns = frontendOptions.fixedFormColumns;
 
-  // -E
-  fortranOptions.prescanAndReformat =
-      frontendOptions.programAction == PrintPreprocessedInput;
-
   fortranOptions.features = frontendOptions.features;
   fortranOptions.encoding = frontendOptions.encoding;
 
@@ -2099,15 +1098,8 @@ void CompilerInvocation::setFortranOpts() {
       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()));
+  fortranOptions.intrinsicModuleDirectories.emplace_back(getIntrinsicDir());
 
   // Add the directory supplied through -J/-module-dir to the list of search
   // directories
@@ -2123,39 +1115,40 @@ void CompilerInvocation::setFortranOpts() {
   if (frontendOptions.needProvenanceRangeToCharBlockMappings)
     fortranOptions.needProvenanceRangeToCharBlockMappings = true;
 
-  fortranOptions.features = frontendOptions.features;
+  if (getEnableConformanceChecks())
+    fortranOptions.features.WarnOnAllNonstandard();
+
+  if (getEnableUsageChecks())
+    fortranOptions.features.WarnOnAllUsage();
 }
 
-std::unique_ptr<Fortran::semantics::SemanticsContext>
-CompilerInvocation::getSemanticsCtx(
-    Fortran::parser::AllCookedSources &allCookedSources,
-    const llvm::TargetMachine &targetMachine) {
+void CompilerInvocation::setSemanticsOpts(
+    Fortran::parser::AllCookedSources &allCookedSources) {
   auto &fortranOptions = getFortranOpts();
 
-  auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
-      getDefaultKinds(), fortranOptions.features, getLangOpts(),
-      allCookedSources, getCodeGenOpts().getFPMaxminBehavior());
+  semanticsContext = std::make_unique<semantics::SemanticsContext>(
+      getDefaultKinds(), fortranOptions.features, allCookedSources);
 
   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_moduleFileSuffix(getModuleFileSuffix());
+
+  llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
+  // FIXME: Handle real(3) ?
+  if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
+    semanticsContext->targetCharacteristics().DisableType(
+        Fortran::common::TypeCategory::Real, /*kind=*/10);
+  }
+
+  std::string version = Fortran::common::getFlangFullVersion();
+  semanticsContext->targetCharacteristics()
+      .set_compilerOptionsString(allCompilerInvocOpts)
+      .set_compilerVersionString(version);
+
+  if (targetTriple.isPPC())
+    semanticsContext->targetCharacteristics().set_isPPC(true);
 }
 
 /// Set \p loweringOptions controlling lowering behavior based
@@ -2165,33 +1158,19 @@ void CompilerInvocation::setLoweringOptions() {
 
   // 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);
+
+  const LangOptions &langOptions = getLangOpts();
   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)
+                            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);
 }



More information about the flang-commits mailing list