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

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


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

Fixes #232487

>From 00c96d9f2ad2cf9ef6337a922ec6b54fe8939fb0 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)

---
 .../clang/Basic/DiagnosticDriverKinds.td      |  357 +---
 flang/lib/Frontend/CompilerInvocation.cpp     | 1751 ++++-------------
 2 files changed, 416 insertions(+), 1692 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 79859e724a8179..f04e199b46fe17 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -20,8 +20,6 @@ def err_drv_unsupported_opt_for_language_mode : Error<
   "unsupported option '%0' for language mode '%1'">;
 def err_drv_unsupported_option_argument : Error<
   "unsupported argument '%1' to option '%0'">;
-def err_drv_unsupported_option_argument_for_target : Error<
-  "unsupported argument '%1' to option '%0' for target '%2'">;
 def err_drv_unknown_stdin_type : Error<
   "-E or -x required when input is from standard input">;
 def err_drv_unknown_stdin_type_clang_cl : Error<
@@ -33,13 +31,12 @@ def err_drv_invalid_riscv_arch_name : Error<
   "invalid arch name '%0', %1">;
 def err_drv_invalid_riscv_cpu_name_for_target : Error<
   "cpu '%0' does not support rv%select{32|64}1">;
-def err_drv_invalid_riscv_mtune_string : Error<
-  "invalid %select{-mtune|tune feature}0 string '%1': %2">;
 def warn_drv_invalid_arch_name_with_suggestion : Warning<
   "ignoring invalid /arch: argument '%0'; for %select{64|32}1-bit expected one of %2">,
   InGroup<UnusedCommandLineArgument>;
 def warn_drv_avr_mcu_not_specified : Warning<
-  "no target microcontroller specified, please pass -mmcu=<mcu name>">,
+  "no target microcontroller specified on command line, cannot "
+  "link standard libraries, please pass -mmcu=<mcu name>">,
   InGroup<AVRRtlibLinkingQuirks>;
 def warn_drv_avr_libc_not_found: Warning<
   "no avr-libc installation can be found on the system, "
@@ -58,8 +55,6 @@ def warn_drv_avr_stdlib_not_linked: Warning<
   InGroup<AVRRtlibLinkingQuirks>;
 def err_drv_cuda_bad_gpu_arch : Error<"unsupported CUDA gpu architecture: %0">;
 def err_drv_offload_bad_gpu_arch : Error<"unsupported %0 gpu architecture: %1">;
-def err_drv_offload_missing_gpu_arch : Error<
-  "must pass in an explicit %0 gpu architecture to '%1'">;
 def err_drv_no_cuda_installation : Error<
   "cannot find CUDA installation; provide its path via '--cuda-path', or pass "
   "'-nocudainc' to build without CUDA includes">;
@@ -69,51 +64,24 @@ def err_drv_no_cuda_libdevice : Error<
   "libdevice">;
 
 def err_drv_no_rocm_device_lib : Error<
-  "cannot find ROCm device library%select{| for %1| for ABI version %1"
-  "%select{|, which requires ROCm %3 or higher}2}0; provide its path via "
+  "cannot find ROCm device library%select{| for %1|for ABI version %1}0; provide its path via "
   "'--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to build "
   "without ROCm device library">;
 def err_drv_no_hip_runtime : Error<
   "cannot find HIP runtime; provide its path via '--rocm-path', or pass "
   "'-nogpuinc' to build without HIP runtime">;
-def err_drv_no_hipstdpar_lib : Error<
-  "cannot find HIP Standard Parallelism Acceleration library; provide it via "
-  "'--hipstdpar-path'">;
-def err_drv_no_hipstdpar_thrust_lib : Error<
-  "cannot find rocThrust, which is required by the HIP Standard Parallelism "
-  "Acceleration library; provide it via "
-  "'--hipstdpar-thrust-path'">;
-def err_drv_no_hipstdpar_prim_lib : Error<
-  "cannot find rocPrim, which is required by the HIP Standard Parallelism "
-  "Acceleration library; provide it via '--hipstdpar-prim-path'">;
 
 def err_drv_no_hipspv_device_lib : Error<
   "cannot find HIP device library%select{| for %1}0; provide its path via "
   "'--hip-path' or '--hip-device-lib-path', or pass '-nogpulib' to build "
   "without HIP device library">;
 def err_drv_hipspv_no_hip_path : Error<
-  "'--hip-path' must be specified when offloading to SPIR-V unless '-nogpuinc' "
-  "is given">;
-
-def err_drv_sycl_no_rdc_multiple_targets : Error<
-  "'%0' is not supported with multiple SYCL offloading targets">;
-
-// SYCL Windows-specific diagnostics
-def err_drv_sycl_requires_dynamic_crt : Error<
-  "SYCL requires dynamic C++ runtime (/MD or /MDd); "
-  "static C++ runtime (/MT or /MTd) is not supported">;
-
-def err_drv_no_spv_tools : Error<"cannot find SPIR-V Tools binary '%0', which "
-                                 "is required for SPIR-V compilation. "
-                                 "It can be obtained from your system package "
-                                 "manager or from KhronosGroup/SPIRV-Tools "
-                                 "on GitHub">;
+  "'--hip-path' must be specified when offloading to "
+  "SPIR-V%select{| unless %1 is given}0.">;
 
 def err_drv_undetermined_gpu_arch : Error<
-  "cannot determine %0 architecture: %1; consider passing it via '%2'; "
-  "environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool "
-  "timeout (integer secs, <=0 is infinite)">;
-
+  "cannot determine %0 architecture: %1; consider passing it via "
+  "'%2'">;
 def warn_drv_multi_gpu_arch : Warning<
   "multiple %0 architectures are detected: %1; only the first one is used for "
   "'%2'">, InGroup<MultiGPU>;
@@ -132,8 +100,6 @@ def err_drv_cuda_host_arch : Error<
   "unsupported architecture '%0' for host compilation">;
 def err_drv_mix_cuda_hip : Error<
   "mixed CUDA and HIP compilation is not supported">;
-def err_drv_mix_offload : Error<
-  "mixed %0 and %1 offloading compilation is not supported">;
 def err_drv_bad_target_id : Error<
   "invalid target ID '%0'; format is a processor name followed by an optional "
   "colon-delimited list of features followed by an enable/disable sign (e.g., "
@@ -142,9 +108,6 @@ def err_drv_bad_offload_arch_combo : Error<
   "invalid offload arch combinations: '%0' and '%1' (for a specific processor, "
   "a feature should either exist in all offload archs, or not exist in any "
   "offload archs)">;
-def err_drv_unsupported_option_for_offload_arch_req_feature : Error<
-  "'%0' option for offload arch '%1' is not currently supported "
-  "there. Use it with an offload arch containing '%2' instead">;
 def warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
   "ignoring '%0' option for offload arch '%1' as it is not currently supported "
   "there. Use it with an offload arch containing '%2' instead">,
@@ -152,43 +115,16 @@ def warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
 def warn_drv_unsupported_option_for_target : Warning<
   "ignoring '%0' option as it is not currently supported for target '%1'">,
   InGroup<OptionIgnored>;
-def err_drv_unsupported_option_for_target : Error<
-  "'%0' option is not currently supported for target '%1'">;
-def warn_drv_unsupported_option_part_for_target : Warning<
-  "ignoring '%0' in '%1' option as it is not currently supported for target '%2'">,
-  InGroup<OptionIgnored>;
-def err_drv_unsupported_option_part_for_target : Error<
-  "'%0' in '%1' option is not currently supported for target '%2'">;
-def warn_drv_invalid_argument_for_flang : Warning<
-  "'%0' is not valid for Fortran">,
-  InGroup<OptionIgnored>;
 def warn_drv_unsupported_option_for_flang : Warning<
   "the argument '%0' is not supported for option '%1'. Mapping to '%1%2'">,
   InGroup<OptionIgnored>;
 def warn_drv_unsupported_diag_option_for_flang : Warning<
-  "the warning option '-%0' is not supported">,
+  "The warning option '-%0' is not supported">,
   InGroup<OptionIgnored>;
 def warn_drv_unsupported_option_for_processor : Warning<
   "ignoring '%0' option as it is not currently supported for processor '%1'">,
   InGroup<OptionIgnored>;
-def warn_drv_unsupported_option_for_runtime : Warning<
-  "ignoring '%0' option as it is not currently supported for runtime '%1'">,
-  InGroup<OptionIgnored>;
-def warn_drv_hexagon_reserved_caller_saved_reg : Warning<
-  "reserving the caller-saved register '%0' may lead to incorrect code if it "
-  "is not also reserved in all other translation units and libraries; you are "
-  "responsible for ensuring the register is managed consistently">,
-  InGroup<DiagGroup<"hexagon-reserved-caller-saved">>;
-def warn_drv_unsupported_openmp_library : Warning<
-  "the library '%0=%1' is not supported, OpenMP will not be enabled">,
-  InGroup<OptionIgnored>;
-def warn_openmp_impl_incomplete : Warning<
-  "OpenMP support for version %0 in flang is still incomplete">,
-  InGroup<ExperimentalOption>;
-def warn_openmp_spec_incomplete : Warning<
-  "the specification for OpenMP version %0 is still under development; "
-  "the syntax and semantics of new features may be subject to change">,
-  InGroup<ExperimentalOption>;
+
 def err_drv_invalid_thread_model_for_target : Error<
   "invalid thread model '%0' in '%1' for this target">;
 def err_drv_invalid_linker_name : Error<
@@ -199,14 +135,10 @@ def err_drv_unsupported_rtlib_for_platform : Error<
   "unsupported runtime library '%0' for platform '%1'">;
 def err_drv_invalid_unwindlib_name : Error<
   "invalid unwind library name in argument '%0'">;
-def err_drv_unsupported_unwind_for_platform : Error<
-  "unsupported unwind library '%0' for platform '%1'">;
 def err_drv_incompatible_unwindlib : Error<
   "--rtlib=libgcc requires --unwindlib=libgcc">;
 def err_drv_incompatible_options : Error<
   "the combination of '%0' and '%1' is incompatible">;
-def err_drv_invalid_cstdlib_name : Error<
-  "invalid C library name in argument '%0'">;
 def err_drv_invalid_stdlib_name : Error<
   "invalid library name in argument '%0'">;
 def err_drv_invalid_output_with_multiple_archs : Error<
@@ -240,26 +172,16 @@ def err_drv_invalid_Xopenmp_target_with_args : Error<
   "invalid -Xopenmp-target argument: '%0', options requiring arguments are unsupported">;
 def err_drv_argument_only_allowed_with : Error<
   "invalid argument '%0' only allowed with '%1'">;
-def err_drv_opt_unsupported_input_type : Error<
-  "'%0' invalid for input of type %1">;
+def err_drv_minws_unsupported_input_type : Error<
+  "'-fminimize-whitespace' invalid for input of type %0">;
 def err_drv_amdgpu_ieee_without_no_honor_nans : Error<
   "invalid argument '-mno-amdgpu-ieee' only allowed with relaxed NaN handling">;
 def err_drv_argument_not_allowed_with : Error<
   "invalid argument '%0' not allowed with '%1'">;
-def warn_drv_argument_not_allowed_with : Warning<
-  "invalid argument '%0' not allowed with '%1'">,
-  InGroup<OptionIgnored>;
-def err_drv_sycl_requires_cxx17 : Error<
-  "SYCL requires C++17 or later; '%0' is not supported">;
 def err_drv_cannot_open_randomize_layout_seed_file : Error<
   "cannot read randomize layout seed file '%0'">;
 def err_drv_invalid_version_number : Error<
   "invalid version number in '%0'">;
-def err_drv_invalid_version_number_inferred
-    : Error<"invalid version number '%0' inferred from '%1'">;
-def err_drv_missing_version_number : Error<"missing version number in '%0'">;
-def err_drv_kcfi_arity_unsupported_target : Error<
-  "target '%0' is unsupported by -fsanitize-kcfi-arity">;
 def err_drv_no_linker_llvm_support : Error<
   "'%0': unable to pass LLVM bit-code files to linker">;
 def err_drv_no_ast_support : Error<
@@ -328,11 +250,6 @@ def err_cpu_unsupported_isa
 def err_arch_unsupported_isa
   : Error<"architecture '%0' does not support '%1' execution mode">;
 
-def err_zos_target_release_discontinued
-  : Error<"z/OS target level \"%0\" is discontinued">;
-def err_zos_target_unrecognized_release
-  : Error<"z/OS target level \"%0\" is invalid">;
-
 def err_drv_I_dash_not_supported : Error<
   "'%0' not supported, please use -iquote instead">;
 def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
@@ -356,12 +273,8 @@ def warn_drv_yc_multiple_inputs_clang_cl : Warning<
 def warn_drv_potentially_misspelled_joined_argument : Warning<
   "joined argument treated as '%0'; did you mean '%1'?">, InGroup<UnknownArgument>;
 
-def err_drv_too_many_actions: Error<
-    "only one action option is allowed. Got %0">;
 def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
 def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
-def err_drv_invalid_escaped_command_line
-    : Error<"invalid escaped command line: %0">;
 def err_drv_invalid_value_with_suggestion : Error<
     "invalid value '%1' in '%0', expected one of: %2">;
 def err_drv_alignment_not_power_of_two : Error<"alignment is not a power of 2 in '%0'">;
@@ -412,11 +325,9 @@ def err_drv_optimization_remark_format : Error<
 def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">;
 def err_drv_invalid_omp_target : Error<"OpenMP target is invalid: '%0'">;
 def err_drv_incompatible_omp_arch : Error<"OpenMP target architecture '%0' pointer size is incompatible with host '%1'">;
-def err_drv_dyndbg_lto : Error<"'-fdynamic-debugging' incompatible with '-flto'">;
-def err_drv_dyndbg_incompatible : Error<"'-fdynamic-debugging' incompatible with '%0'">;
-def err_drv_dyndbg_ir : Error<"'-fdynamic-debugging' incompatible with IR input">;
-def warn_drv_dyndbg_req_debug : Warning<"'-fdynamic-debugging' ignored: requires debug info">,
-    InGroup<DynamicDebugging>;
+def err_drv_omp_host_ir_file_not_found : Error<
+  "provided host compiler IR file '%0' is required to generate code for OpenMP "
+  "target regions but cannot be found">;
 def err_drv_omp_host_target_not_supported : Error<
   "target '%0' is not a supported OpenMP host target">;
 def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
@@ -424,7 +335,7 @@ def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
   "compatible with offloading; e.g., '-fopenmp=libomp' or '-fopenmp=libiomp5'">;
 def err_drv_failed_to_deduce_target_from_arch : Error<
   "failed to deduce triple for target architecture '%0'; specify the triple "
-  "using '-fopenmp-targets' and '-Xopenmp-target' instead">;
+  "using '-fopenmp-targets' and '-Xopenmp-target' instead.">;
 def err_drv_omp_offload_target_missingbcruntime : Error<
   "no library '%0' found in the default clang lib directory or in LIBRARY_PATH"
   "; use '--libomptarget-%1-bc-path' to specify %1 bitcode library">;
@@ -444,13 +355,8 @@ def err_drv_negative_columns : Error<
 def err_drv_small_columns : Error<
   "invalid value '%1' in '%0', value must be '%2' or greater">;
 def err_drv_large_columns : Error<
-  "invalid value '%1' in '%0', value must be '%2' or smaller">;
-def warn_drv_fraw_string_literals_in_cxx11 : Warning<
-  "ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C and C++ standards before C++11">,
-  InGroup<UnusedCommandLineArgument>;
-
-def err_drv_libclc_not_found : Error<"no libclc library '%0' found in the clang resource directory">;
-
+  "invalid value '%1' in '%0', value must be '2147483647' or smaller">;
+  
 def err_drv_invalid_malign_branch_EQ : Error<
   "invalid argument '%0' to -malign-branch=; each element must be one of: %1">;
 
@@ -458,14 +364,8 @@ def err_drv_print_header_env_var : Error<
   "environment variable CC_PRINT_HEADERS_%select{FORMAT|FILTERING}0 has invalid value %1">;
 def err_drv_print_header_env_var_combination : Error<
   "unsupported combination: CC_PRINT_HEADERS_FORMAT=%0 and CC_PRINT_HEADERS_FILTERING=%1">;
-def err_drv_print_header_env_var_invalid_format : Error<
-  "environment variable CC_PRINT_HEADERS_FORMAT=%0 requires a compatible value for CC_PRINT_HEADERS_FILTERING">;
-def err_drv_print_header_cc1_invalid_combination : Error<
+def err_drv_print_header_env_var_combination_cc1 : Error<
   "unsupported combination: -header-include-format=%0 and -header-include-filtering=%1">;
-def err_drv_print_header_cc1_invalid_filtering : Error<
-  "-header-include-filtering=%0 requires a compatible value for -header-include-format">;
-def err_drv_print_header_cc1_invalid_format : Error<
-  "-header-include-format=%0 requires a compatible value for -header-include-filtering">;
 
 def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
 def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">,
@@ -477,9 +377,6 @@ def warn_ignored_clang_option : Warning<"the flag '%0' has been deprecated and w
 def warn_drv_unsupported_opt_for_target : Warning<
   "optimization flag '%0' is not supported for target '%1'">,
   InGroup<IgnoredOptimizationArgument>;
-def warn_drv_riscv_be_experimental : Warning<
-  "big-endian RISC-V target support is experimental">,
-  InGroup<RISCVBEExperimental>;
 def warn_drv_unsupported_debug_info_opt_for_target : Warning<
   "debug information option '%0' is not supported for target '%1'">,
   InGroup<UnsupportedTargetOpt>;
@@ -489,6 +386,9 @@ def warn_drv_dwarf_version_limited_by_target : Warning<
   InGroup<UnsupportedTargetOpt>;
 def warn_c_kext : Warning<
   "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
+def warn_ignoring_fdiscard_for_bitcode : Warning<
+  "ignoring -fdiscard-value-names for LLVM Bitcode">,
+  InGroup<UnusedCommandLineArgument>;
 def warn_drv_input_file_unused : Warning<
   "%0: '%1' input unused%select{ when '%3' is present|}2">,
   InGroup<UnusedCommandLineArgument>;
@@ -516,17 +416,7 @@ def warn_drv_diagnostics_misexpect_requires_pgo : Warning<
 def warn_drv_clang_unsupported : Warning<
   "the clang compiler does not support '%0'">;
 def warn_drv_deprecated_arg : Warning<
-  "argument '%0' is deprecated%select{|, use '%2' instead}1">, InGroup<Deprecated>;
-def warn_drv_deprecated_arg_ofast : Warning<
-  "argument '-Ofast' is deprecated; use '-O3' to enable only conforming optimizations, "
-  "or consult the documentation for the same behavior">,
-  InGroup<DeprecatedOFast>;
-def warn_drv_deprecated_arg_ofast_for_flang : Warning<
-  "argument '-Ofast' is deprecated; use '-O3 -ffast-math -fstack-arrays -fno-protect-parens' for the same behavior,"
-  " or '-O3 -fstack-arrays' to enable only conforming optimizations">,
-  InGroup<DeprecatedOFast>;
-def warn_drv_deprecated_custom : Warning<
-  "argument '%0' is deprecated, %1">, InGroup<Deprecated>;
+  "argument '%0' is deprecated, use '%1' instead">, InGroup<Deprecated>;
 def warn_drv_assuming_mfloat_abi_is : Warning<
   "unknown platform, assuming -mfloat-abi=%0">;
 def warn_drv_unsupported_float_abi_by_lib : Warning<
@@ -537,34 +427,20 @@ def warn_drv_no_floating_point_registers: Warning<
   InGroup<UnsupportedABI>;
 def warn_ignoring_ftabstop_value : Warning<
   "ignoring invalid -ftabstop value '%0', using default value %1">;
-def warn_drv_overriding_option : Warning<
+def warn_drv_overriding_flag_option : Warning<
   "overriding '%0' option with '%1'">,
-  InGroup<DiagGroup<"overriding-option">>;
-def warn_drv_overriding_deployment_version
-    : Warning<"overriding deployment version from '%0' to '%1'">,
-      InGroup<DiagGroup<"overriding-deployment-version">>;
-def warn_drv_overriding_complex_range : Warning<
-  "'%1' sets complex range to \"%3\" overriding the setting of \"%2\" that was implied by '%0'">,
-  InGroup<DiagGroup<"overriding-complex-range">>;
+  InGroup<DiagGroup<"overriding-t-option">>;
 def warn_drv_treating_input_as_cxx : Warning<
   "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
   InGroup<Deprecated>;
 def warn_drv_pch_not_first_include : Warning<
   "precompiled header '%0' was ignored because '%1' is not first '-include'">;
-def warn_drv_pch_ignoring_gch_file : Warning<
-  "precompiled header '%0' was ignored because it is not a clang PCH file">,
-  InGroup<IgnoredGCH>;
-def warn_drv_pch_ignoring_gch_dir : Warning<
-  "precompiled header directory '%0' was ignored because it contains no clang PCH files">,
-  InGroup<IgnoredGCH>;
 def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">,
   InGroup<DiagGroup<"missing-sysroot">>;
 def warn_incompatible_sysroot : Warning<"using sysroot for '%0' but targeting '%1'">,
   InGroup<DiagGroup<"incompatible-sysroot">>;
 def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (%0 not enabled)">,
   InGroup<DiagGroup<"debug-compression-unavailable">>;
-def err_drv_time_trace_compression_unavailable
-    : Error<"cannot compress time trace (%0 not enabled)">;
 def warn_drv_disabling_vptr_no_rtti_default : Warning<
   "implicitly disabling vptr sanitizer because rtti wasn't enabled">,
   InGroup<AutoDisableVptrSanitizer>;
@@ -577,17 +453,8 @@ def warn_ignoring_verify_debuginfo_preserve_export : Warning<
   InGroup<UnusedCommandLineArgument>;
 def warn_unsupported_branch_protection: Warning <
   "invalid branch protection option '%0' in '%1'">, InGroup<BranchProtection>;
-def warn_harden_pac_ret_requires_pac_ret: Warning<
-  "ignoring '-mharden-pac-ret' as it requires return address signing">, InGroup<UnusedCommandLineArgument>;
 def err_sls_hardening_arm_not_supported : Error<
   "-mharden-sls is only supported on armv7-a or later">;
-def warn_drv_large_data_threshold_invalid_code_model: Warning<
-  "'%0' only applies to medium and large code models">,
-  InGroup<UnusedCommandLineArgument>;
-def warn_drv_math_errno_enabled_after_veclib: Warning<
-  "math errno enabled by '%0' after it was implicitly disabled by '%1',"
-  " this may limit the utilization of the vector library">,
-  InGroup<MathErrnoEnabledWithVecLib>;
 
 def note_drv_command_failed_diag_msg : Note<
   "diagnostic msg: %0">;
@@ -613,8 +480,16 @@ def err_analyzer_checker_option_invalid_input : Error<
 def err_analyzer_checker_incompatible_analyzer_option : Error<
   "checker cannot be enabled with analyzer option '%0' == %1">;
 def err_analyzer_not_built_with_z3 : Error<
-  "analyzer constraint manager 'unsupported-z3' is only available if LLVM was "
-  "built with -DLLVM_ENABLE_Z3_SOLVER=ON">;
+  "analyzer constraint manager 'z3' is only available if LLVM was built with "
+  "-DLLVM_ENABLE_Z3_SOLVER=ON">;
+def warn_analyzer_deprecated_option : Warning<
+  "analyzer option '%0' is deprecated. This flag will be removed in %1, and "
+  "passing this option will be an error.">,
+  InGroup<DeprecatedStaticAnalyzerFlag>;
+def warn_analyzer_deprecated_option_with_alternative : Warning<
+  "analyzer option '%0' is deprecated. This flag will be removed in %1, and "
+  "passing this option will be an error. Use '%2' instead.">,
+  InGroup<DeprecatedStaticAnalyzerFlag>;
 
 def warn_drv_needs_hvx : Warning<
   "%0 requires HVX, use -mhvx/-mhvx= to enable it">,
@@ -636,63 +511,12 @@ def err_test_module_file_extension_format : Error<
   "'blockname:major:minor:hashed:user info'">;
 
 def err_drv_module_output_with_multiple_arch : Error<
-  "option '-fmodule-output' cannot be used with multiple arch options">;
-
-def err_drv_reduced_module_output_overrided : Warning<
-  "the implicit output of reduced BMI may be overrided by the output file specified by '--precompile'. "
-  "please consider use '-fmodule-output=' to specify the output file for reduced BMI explicitly">,
-  InGroup<DiagGroup<"reduced-bmi-output-overrided">>;
-
-def err_drv_modules_driver_requires_reduced_bmi : Error<
-  "'-fmodules-driver' is currently incompatible with '-fno-modules-reduced-bmi'">;
-def remark_performing_driver_managed_module_build : Remark<
-  "performing driver managed module build">, InGroup<ModulesDriver>;
-def remark_modules_manifest_not_found : Remark<
-  "standard modules manifest file not found; import of standard library "
-  "modules not supported">,
-  InGroup<ModulesDriver>;
-def remark_using_modules_manifest : Remark<
-  "using standard modules manifest file '%0'">,
-  InGroup<ModulesDriver>;
-def err_modules_manifest_failed_parse : Error<
-  "failure while parsing standard modules manifest: '%0'">;
-def err_default_modules_cache_not_available : Error<
-  "unable to determine the default -fmodules-cache-path. Please specify it "
-  "explicitly using -fmodules-cache-path or the CLANG_MODULE_CACHE_PATH "
-  "environment variable">;
-def err_dependency_scan_failed : Error<
-  "failed to perform dependency scan">;
-def err_modules_driver_named_module_redefinition : Error<
-  "duplicate definitions of C++20 named module '%0' in '%1' and '%2'">;
-def remark_printing_module_graph : Remark<
-  "printing module dependency graph">,
-  InGroup<ModulesDriver>;
-def err_module_defined_outside_of_module_source : Error<
-  "module '%0' is defined in file '%1', but module declarations are only "
-  "allowed in C++ module inputs; use the '.cppm' extension or '-x c++module'">;
-def err_drv_depscan_log_path_empty : Error<
-  "'-fdepscan-log-path=' requires a non-empty file path">;
-def err_drv_depscan_log_path_inconsistent : Error<
-  "'-fdepscan-log-path' set inconsistently within a dependency scan: "
-  "%select{no log path|log path '%1'}0 conflicts with "
-  "%select{no log path|log path '%3'}2 requested earlier">;
-
-def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
-  "-fdelayed-template-parsing is deprecated after C++20">,
-  InGroup<DiagGroup<"delayed-template-parsing-in-cxx20">>;
+  "option '-fmodule-output' can't be used with multiple arch options">;
 
 def err_drv_extract_api_wrong_kind : Error<
   "header file '%0' input '%1' does not match the type of prior input "
   "in api extraction; use '-x %2' to override">;
 
-def err_drv_missing_symbol_graph_dir: Error<
-  "must provide a symbol graph output directory using "
-  "'--symbol-graph-dir=<directory>'">;
-
-def err_drv_unexpected_symbol_graph_output : Error<
-  "unexpected output symbol graph '%1'; please provide "
-  "'--symbol-graph-dir=<directory>' instead">;
-
 def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">,
   InGroup<DiagGroup<"slash-u-filename">>;
 def note_use_dashdash : Note<
@@ -732,6 +556,9 @@ def warn_drv_unsupported_gpopt : Warning<
   "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit"
   " usage of }0-mabicalls">,
   InGroup<UnsupportedGPOpt>;
+def warn_drv_unsupported_sdata : Warning<
+  "ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">,
+  InGroup<OptionIgnored>;
 def warn_drv_unsupported_longcalls : Warning<
   "ignoring '-mlong-calls' option as it is not currently supported with "
   "%select{|the implicit usage of }0-mabicalls">,
@@ -772,17 +599,10 @@ def warn_drv_fine_grained_bitfield_accesses_ignored : Warning<
   "option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored">,
   InGroup<OptionIgnored>;
 
-def err_drv_profile_instrument_use_path_with_no_kind : Error<
-  "option '-fprofile-instrument-use-path=' requires -fprofile-instrument-use=<kind>">;
-
 def note_drv_verify_prefix_spelling : Note<
   "-verify prefixes must start with a letter and contain only alphanumeric"
   " characters, hyphens, and underscores">;
 
-def note_command_line_code_loc_requirement
-    : Note<"-code-completion-at=<file>:<line>:<column> requires <line> and "
-           "<column> to be integers greater than zero">;
-
 def warn_drv_global_isel_incomplete : Warning<
   "-fglobal-isel support for the '%0' architecture is incomplete">,
   InGroup<GlobalISel>;
@@ -803,7 +623,6 @@ def warn_drv_darwin_sdk_invalid_settings : Warning<
   "SDK settings were ignored as 'SDKSettings.json' could not be parsed">,
   InGroup<DiagGroup<"darwin-sdk-settings">>;
 
-def err_missing_sysroot : Error<"no such sysroot directory: '%0'">;
 def err_drv_darwin_sdk_missing_arclite : Error<
   "SDK does not contain 'libarclite' at the path '%0'; try increasing the minimum deployment target">;
 
@@ -814,13 +633,6 @@ def err_drv_trivial_auto_var_init_stop_after_missing_dependency : Error<
 def err_drv_trivial_auto_var_init_stop_after_invalid_value : Error<
   "'-ftrivial-auto-var-init-stop-after=*' only accepts positive integers">;
 
-def err_drv_trivial_auto_var_init_max_size_missing_dependency : Error<
-  "'-ftrivial-auto-var-init-max-size=*' is used without "
-  "'-ftrivial-auto-var-init=zero' or '-ftrivial-auto-var-init=pattern'">;
-
-def err_drv_trivial_auto_var_init_max_size_invalid_value : Error<
-  "'-ftrivial-auto-var-init-max-size=*' only accepts positive integers (in bytes)">;
-
 def warn_drv_msp430_hwmult_unsupported : Warning<
   "the given MCU does not support hardware multiply, but '-mhwmult' is set to "
   "%0">, InGroup<InvalidCommandLineArgument>;
@@ -843,9 +655,7 @@ def err_drv_cannot_mix_options : Error<"cannot specify '%1' along with '%0'">;
 def err_drv_invalid_object_mode : Error<
   "OBJECT_MODE setting %0 is not recognized and is not a valid setting">;
 
-def err_drv_compile_mode_unsupported_aix : Error<
-  "32-bit compile mode is not supported. Use OBJECT_MODE=64, -maix64 or -m64">;
-
+def err_aix_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">;
 def err_roptr_requires_data_sections: Error<"-mxcoff-roptr is supported only with -fdata-sections">;
 def err_roptr_cannot_build_shared: Error<"-mxcoff-roptr is not supported with -shared">;
 
@@ -866,12 +676,6 @@ def err_cc1_round_trip_mismatch : Error<
 def err_cc1_unbounded_vscale_min : Error<
   "minimum vscale must be an unsigned integer greater than 0">;
 
-def err_conflicting_matrix_layout_flags: Error<
-  "-fmatrix-memory-layout=%0 conflicts with -mllvm -matrix-default-layout=%1">;
-
-def err_drv_using_omit_rtti_component_without_no_rtti : Error<
-  "-fexperimental-omit-vtable-rtti call only be used with -fno-rtti">;
-
 def err_drv_ssp_missing_offset_argument : Error<
   "'%0' is used without '-mstack-protector-guard-offset', and there is no default">;
 
@@ -900,54 +704,36 @@ def err_drv_target_variant_invalid : Error<
 
 def err_drv_invalid_directx_shader_module : Error<
   "invalid profile : %0">;
-def err_drv_dxc_invalid_matrix_layout : Error<
-  "cannot specify /Zpr and /Zpc together">;
 def err_drv_dxc_missing_target_profile : Error<
   "target profile option (-T) is missing">;
-def err_drv_dxc_Fre_requires_Fo_metal
-    : Error<"-Fre option requires -Fo option when targeting Metal">;
-def err_drv_dxc_invalid_shader_hash
-    : Error<"cannot specify both /Zss and /Zsb">;
 def err_drv_hlsl_unsupported_target : Error<
   "HLSL code generation is unsupported for target '%0'">;
-def err_drv_hlsl_bad_shader_required_in_target : Error<
-  "%select{shader model|Vulkan environment|shader stage}0 is required as %select{OS|environment}1 in target '%2' for HLSL code generation">;
-def err_drv_hlsl_16bit_types_unsupported: Error<
-  "'%0' option requires target HLSL Version >= 2018%select{| and shader model >= 6.2}1, but HLSL Version is '%2'%select{| and shader model is '%3'}1">;
-def err_drv_hlsl_bad_shader_unsupported : Error<
-  "%select{shader model|Vulkan environment|shader stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
-def warn_drv_dxc_missing_dxv : Warning<
-  "dxv not found; resulting DXIL will not be validated or signed for use in "
-  "release environment">, InGroup<DXILValidation>;
-def warn_drv_dxc_missing_spirv_val : Warning<
-  "spirv-val not found; resulting SPIR-V will not be validated">,
-  InGroup<SPIRVValidation>;
+def warn_drv_dxc_missing_dxv : Warning<"dxv not found. "
+    "Resulting DXIL will not be validated or signed for use in release environments.">,
+    InGroup<DXILValidation>;
 
 def err_drv_invalid_range_dxil_validator_version : Error<
-  "invalid validator version : %0; validator version must be less than or "
-  "equal to current internal version">;
+  "invalid validator version : %0\n"
+  "Validator version must be less than or equal to current internal version.">;
 def err_drv_invalid_format_dxil_validator_version : Error<
-  "invalid validator version : %0; format of validator version is "
-  "\"<major>.<minor>\" (ex:\"1.4\")">;
+  "invalid validator version : %0\n"
+  "Format of validator version is \"<major>.<minor>\" (ex:\"1.4\").">;
 def err_drv_invalid_empty_dxil_validator_version : Error<
-  "invalid validator version : %0; if validator major version is 0, minor "
-  "version must also be 0">;
+  "invalid validator version : %0\n"
+  "If validator major version is 0, minor version must also be 0.">;
 
 def warn_drv_sarif_format_unstable : Warning<
   "diagnostic formatting in SARIF mode is currently unstable">,
   InGroup<DiagGroup<"sarif-format-unstable">>;
 
+def err_drv_riscv_unsupported_with_linker_relaxation : Error<
+  "%0 is unsupported with RISC-V linker relaxation (-mrelax)">;
+
 def warn_drv_loongarch_conflicting_implied_val : Warning<
   "ignoring '%0' as it conflicts with that implied by '%1' (%2)">,
   InGroup<OptionIgnored>;
 def err_drv_loongarch_invalid_mfpu_EQ : Error<
   "invalid argument '%0' to -mfpu=; must be one of: 64, 32, none, 0 (alias for none)">;
-def err_drv_loongarch_wrong_fpu_width : Error<
-  "wrong fpu width; %select{LSX|LASX}0 depends on 64-bit FPU">;
-def err_drv_loongarch_invalid_simd_option_combination : Error<
-  "invalid option combination; LASX depends on LSX">;
-def err_drv_loongarch_invalid_msimd_EQ : Error<
-  "invalid argument '%0' to -msimd=; must be one of: none, lsx, lasx">;
 
 def err_drv_expand_response_file : Error<
   "failed to expand response file: %0">;
@@ -957,45 +743,4 @@ def warn_drv_missing_multilib : Warning<
   InGroup<DiagGroup<"missing-multilib">>;
 def note_drv_available_multilibs : Note<
   "available multilibs are:%0">;
-def err_drv_multilib_custom_error : Error<
-  "multilib configuration error: %0">;
-def warn_drv_multilib_not_available_for_target: Warning<
-  "no multilib structure encoded for Arm, Aarch64 and PPC targets">,
-  InGroup<DiagGroup<"multilib-not-found">>;
-
-def err_drv_experimental_crel : Error<
-  "-Wa,--allow-experimental-crel must be specified to use -Wa,--crel. "
-  "CREL is experimental and uses a non-standard section type code">;
-
-def err_drv_experimental_sframe : Error<
-  "-Wa,--allow-experimental-sframe must be specified to use -Wa,--gsframe. "
-  "SFrames are experimental and may be removed at any time without warning">;
-
-def warn_android_unversioned_fallback : Warning<
-  "using unversioned Android target directory %0 for target %1; unversioned "
-  "directories will not be used in Clang 19 -- provide a versioned directory "
-  "for the target version or lower instead">,
-  InGroup<DiagGroup<"android-unversioned-fallback">>;
-
-def err_drv_triple_version_invalid : Error<
-  "version '%0' in target triple '%1' is invalid">;
-
-def warn_missing_include_dirs : Warning<
-  "no such include directory: '%0'">, InGroup<MissingIncludeDirs>, DefaultIgnore;
-
-def err_drv_malformed_warning_suppression_mapping : Error<
-  "failed to process suppression mapping file '%0': %1">;
-
-def warn_drv_openacc_without_cir
-    : Warning<"OpenACC directives will result in no runtime behavior; use "
-              "-fclangir to enable runtime effect">,
-      InGroup<SourceUsesOpenACC>;
-
-def warn_drv_gcc_install_dir_libstdcxx : Warning<
-    "future releases of the clang compiler will prefer GCC installations "
-    "containing libstdc++ include directories; '%0' would be chosen over '%1'">,
-    InGroup<DiagGroup<"gcc-install-dir-libstdcxx">>;
-
-def err_drv_reflection_requires_cxx26 : Error<
-  "option '%0' is only supported when compiling in C++26 mode">;
 }
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