[flang-commits] [flang] [flang] Fix compiler invocation issue (#232487) (PR #235472)
via flang-commits
flang-commits at lists.llvm.org
Sun Oct 25 08:40:00 PDT 2026
https://github.com/Harshit2906 created https://github.com/llvm/llvm-project/pull/235472
Fixes #232487
>From 06e60c6471d0ef8ccc795e95bd35d9b5b65aaa77 Mon Sep 17 00:00:00 2001
From: Harshit <harshitjhiraparaharshit at gmail.com>
Date: Sun, 25 Oct 2026 21:04:57 +0530
Subject: [PATCH] [flang] Fix compiler invocation issue (#232487)
---
flang/lib/Frontend/CompilerInvocation.cpp | 1751 +++++----------------
1 file changed, 365 insertions(+), 1386 deletions(-)
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 38e66aad693cbc..46c6c87f534811 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -11,44 +11,34 @@
//===----------------------------------------------------------------------===//
#include "flang/Frontend/CompilerInvocation.h"
+#include "flang/Common/Fortran-features.h"
+#include "flang/Common/OpenMP-features.h"
+#include "flang/Common/Version.h"
#include "flang/Frontend/CodeGenOptions.h"
#include "flang/Frontend/PreprocessorOptions.h"
#include "flang/Frontend/TargetOptions.h"
-#include "flang/Optimizer/Passes/CommandLineOpts.h"
#include "flang/Semantics/semantics.h"
-#include "flang/Support/Fortran-features.h"
-#include "flang/Support/OpenMP-features.h"
-#include "flang/Support/Version.h"
-#include "flang/Tools/TargetSetup.h"
#include "flang/Version.inc"
+#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/DiagnosticDriver.h"
-#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Driver/CommonArgs.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Options/OptionUtils.h"
-#include "clang/Options/Options.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/OptionUtils.h"
+#include "clang/Driver/Options.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Frontend/Debug/Options.h"
-#include "llvm/Frontend/Driver/CodeGenOptions.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
-#include "llvm/Support/CodeGen.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
-#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
-#include <algorithm>
#include <cstdlib>
-#include <limits>
#include <memory>
#include <optional>
@@ -73,8 +63,8 @@ CompilerInvocationBase::~CompilerInvocationBase() = default;
static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
bool defaultColor = true) {
// Color diagnostics default to auto ("on" if terminal supports) in the
- // compiler driver `flang` but default to off in the frontend driver
- // `flang -fc1`, needing an explicit OPT_fdiagnostics_color.
+ // compiler driver `flang-new` but default to off in the frontend driver
+ // `flang-new -fc1`, needing an explicit OPT_fdiagnostics_color.
// Support both clang's -f[no-]color-diagnostics and gcc's
// -f[no-]diagnostics-colors[=never|always|auto].
enum {
@@ -85,11 +75,11 @@ static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
for (auto *a : args) {
const llvm::opt::Option &opt = a->getOption();
- if (opt.matches(clang::options::OPT_fcolor_diagnostics)) {
+ if (opt.matches(clang::driver::options::OPT_fcolor_diagnostics)) {
showColors = Colors_On;
- } else if (opt.matches(clang::options::OPT_fno_color_diagnostics)) {
+ } else if (opt.matches(clang::driver::options::OPT_fno_color_diagnostics)) {
showColors = Colors_Off;
- } else if (opt.matches(clang::options::OPT_fdiagnostics_color_EQ)) {
+ } else if (opt.matches(clang::driver::options::OPT_fdiagnostics_color_EQ)) {
llvm::StringRef value(a->getValue());
if (value == "always")
showColors = Colors_On;
@@ -108,15 +98,17 @@ static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
/// Extracts the optimisation level from \a args.
static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
- unsigned defaultOpt = 0;
+ unsigned defaultOpt = llvm::CodeGenOpt::None;
- if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_O_Group)) {
- if (a->getOption().matches(clang::options::OPT_O0))
- return 0;
+ if (llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_O_Group)) {
+ if (a->getOption().matches(clang::driver::options::OPT_O0))
+ return llvm::CodeGenOpt::None;
- assert(a->getOption().matches(clang::options::OPT_O));
+ assert(a->getOption().matches(clang::driver::options::OPT_O));
- return getLastArgIntValue(args, clang::options::OPT_O, defaultOpt, diags);
+ return getLastArgIntValue(args, clang::driver::options::OPT_O, defaultOpt,
+ diags);
}
return defaultOpt;
@@ -124,8 +116,7 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
llvm::opt::ArgList &args) {
- opts.setShowColors(parseShowColorsArgs(args) ? clang::ShowColorsKind::On
- : clang::ShowColorsKind::Off);
+ opts.ShowColors = parseShowColorsArgs(args);
return true;
}
@@ -135,7 +126,7 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
clang::DiagnosticsEngine &diags) {
using DebugInfoKind = llvm::codegenoptions::DebugInfoKind;
if (llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_debug_info_kind_EQ)) {
+ args.getLastArg(clang::driver::options::OPT_debug_info_kind_EQ)) {
std::optional<DebugInfoKind> val =
llvm::StringSwitch<std::optional<DebugInfoKind>>(arg->getValue())
.Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
@@ -153,337 +144,58 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
}
opts.setDebugInfo(val.value());
if (val != llvm::codegenoptions::DebugLineTablesOnly &&
- val != llvm::codegenoptions::DebugDirectivesOnly &&
- val != llvm::codegenoptions::FullDebugInfo &&
val != llvm::codegenoptions::NoDebugInfo) {
const auto debugWarning = diags.getCustomDiagID(
clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0");
diags.Report(debugWarning) << arg->getValue();
}
- opts.DwarfVersion =
- getLastArgIntValue(args, clang::options::OPT_dwarf_version_EQ,
- /*Default=*/0, diags);
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_split_dwarf_file))
- opts.SplitDwarfFile = a->getValue();
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_split_dwarf_output))
- opts.SplitDwarfOutput = a->getValue();
}
-
- if (const llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_dwarf_debug_flags))
- opts.DwarfDebugFlags = arg->getValue();
-
- opts.DebugInfoForProfiling =
- args.hasArg(clang::options::OPT_fdebug_info_for_profiling);
-
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_compress_debug_sections_EQ)) {
- auto type = llvm::StringSwitch<std::optional<llvm::DebugCompressionType>>(
- a->getValue())
- .Case("none", llvm::DebugCompressionType::None)
- .Case("zlib", llvm::DebugCompressionType::Zlib)
- .Case("zstd", llvm::DebugCompressionType::Zstd)
- .Default(std::nullopt);
- if (type) {
- opts.setCompressDebugSections(*type);
- } else {
- diags.Report(clang::diag::err_drv_invalid_value)
- << a->getAsString(args) << a->getValue();
- return false;
- }
- }
-
- return true;
-}
-
-static bool parseDoConcurrentMapping(Fortran::frontend::CodeGenOptions &opts,
- llvm::opt::ArgList &args,
- clang::DiagnosticsEngine &diags) {
- llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_fdo_concurrent_to_openmp_EQ);
- if (!arg)
- return true;
-
- using DoConcurrentMappingKind =
- Fortran::frontend::CodeGenOptions::DoConcurrentMappingKind;
- std::optional<DoConcurrentMappingKind> val =
- llvm::StringSwitch<std::optional<DoConcurrentMappingKind>>(
- arg->getValue())
- .Case("none", DoConcurrentMappingKind::DCMK_None)
- .Case("host", DoConcurrentMappingKind::DCMK_Host)
- .Case("device", DoConcurrentMappingKind::DCMK_Device)
- .Default(std::nullopt);
-
- if (!val.has_value()) {
- diags.Report(clang::diag::err_drv_invalid_value)
- << arg->getAsString(args) << arg->getValue();
- return false;
- }
-
- opts.setDoConcurrentMapping(val.value());
- return true;
-}
-
-static bool parseVectorLibArg(Fortran::frontend::CodeGenOptions &opts,
- llvm::opt::ArgList &args,
- clang::DiagnosticsEngine &diags) {
- llvm::opt::Arg *arg = args.getLastArg(clang::options::OPT_fveclib);
- if (!arg)
- return true;
-
- using VectorLibrary = llvm::driver::VectorLibrary;
- std::optional<VectorLibrary> val =
- llvm::StringSwitch<std::optional<VectorLibrary>>(arg->getValue())
- .Case("Accelerate", VectorLibrary::Accelerate)
- .Case("libmvec", VectorLibrary::LIBMVEC)
- .Case("MASSV", VectorLibrary::MASSV)
- .Case("SVML", VectorLibrary::SVML)
- .Case("SLEEF", VectorLibrary::SLEEF)
- .Case("Darwin_libsystem_m", VectorLibrary::Darwin_libsystem_m)
- .Case("ArmPL", VectorLibrary::ArmPL)
- .Case("AMDLIBM", VectorLibrary::AMDLIBM)
- .Case("NoLibrary", VectorLibrary::NoLibrary)
- .Default(std::nullopt);
- if (!val.has_value()) {
- diags.Report(clang::diag::err_drv_invalid_value)
- << arg->getAsString(args) << arg->getValue();
- return false;
- }
- opts.setVecLib(val.value());
return true;
}
-// Generate an OptRemark object containing info on if the -Rgroup
-// specified is enabled or not.
-static CodeGenOptions::OptRemark
-parseOptimizationRemark(clang::DiagnosticsEngine &diags,
- llvm::opt::ArgList &args, llvm::opt::OptSpecifier optEq,
- llvm::StringRef remarkOptName) {
- assert((remarkOptName == "pass" || remarkOptName == "pass-missed" ||
- remarkOptName == "pass-analysis") &&
- "Unsupported remark option name provided.");
- CodeGenOptions::OptRemark result;
-
- for (llvm::opt::Arg *a : args) {
- if (a->getOption().matches(clang::options::OPT_R_Joined)) {
- llvm::StringRef value = a->getValue();
-
- if (value == remarkOptName) {
- result.Kind = CodeGenOptions::RemarkKind::RK_Enabled;
- // Enable everything
- result.Pattern = ".*";
- result.Regex = std::make_shared<llvm::Regex>(result.Pattern);
-
- } else if (value.split('-') ==
- std::make_pair(llvm::StringRef("no"), remarkOptName)) {
- result.Kind = CodeGenOptions::RemarkKind::RK_Disabled;
- // Disable everything
- result.Pattern = "";
- result.Regex = nullptr;
- }
- } else if (a->getOption().matches(optEq)) {
- result.Kind = CodeGenOptions::RemarkKind::RK_WithPattern;
- result.Pattern = a->getValue();
- result.Regex = std::make_shared<llvm::Regex>(result.Pattern);
- std::string regexError;
-
- if (!result.Regex->isValid(regexError)) {
- diags.Report(clang::diag::err_drv_optimization_remark_pattern)
- << regexError << a->getAsString(args);
- return CodeGenOptions::OptRemark();
- }
- }
- }
- return result;
-}
-
static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
opts.OptimizationLevel = getOptimizationLevel(args, diags);
- if (args.hasFlag(clang::options::OPT_fdebug_pass_manager,
- clang::options::OPT_fno_debug_pass_manager, false))
+ if (args.hasFlag(clang::driver::options::OPT_fdebug_pass_manager,
+ clang::driver::options::OPT_fno_debug_pass_manager, false))
opts.DebugPassManager = 1;
- if (!args.hasFlag(clang::options::OPT_fprotect_parens,
- clang::options::OPT_fno_protect_parens, true))
- opts.ProtectParens = 0;
-
- if (args.hasFlag(clang::options::OPT_fstack_arrays,
- clang::options::OPT_fno_stack_arrays, false))
+ if (args.hasFlag(clang::driver::options::OPT_fstack_arrays,
+ clang::driver::options::OPT_fno_stack_arrays, false)) {
opts.StackArrays = 1;
-
- if (args.hasFlag(clang::options::OPT_fsafe_trampoline,
- clang::options::OPT_fno_safe_trampoline, false))
- opts.EnableSafeTrampoline = 1;
-
- if (args.hasFlag(clang::options::OPT_ffp_sum_reassociation,
- clang::options::OPT_fno_fp_sum_reassociation, true))
- opts.SplitSumExpressionTree = 1;
-
- // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
- // which enables the pass whenever the optimization pipeline runs.
- opts.InterchangeLoops =
- args.hasFlag(clang::options::OPT_floop_interchange,
- clang::options::OPT_fno_loop_interchange, true);
-
- if (args.hasArg(clang::options::OPT_funique_internal_linkage_names))
- opts.UniqueInternalLinkageNames = 1;
-
- if (args.getLastArg(clang::options::OPT_fexperimental_loop_fusion))
- opts.FuseLoops = 1;
-
- if (args.getLastArg(clang::options::OPT_vectorize_loops))
- opts.VectorizeLoop = 1;
-
- if (args.getLastArg(clang::options::OPT_vectorize_slp))
- opts.VectorizeSLP = 1;
-
- if (args.hasFlag(clang::options::OPT_floop_versioning,
- clang::options::OPT_fno_loop_versioning, false))
+ }
+ if (args.hasFlag(clang::driver::options::OPT_floop_versioning,
+ clang::driver::options::OPT_fno_loop_versioning, false)) {
opts.LoopVersioning = 1;
-
- if (args.hasFlag(clang::options::OPT_floop_tripcount_versioning,
- clang::options::OPT_fno_loop_tripcount_versioning, false))
- opts.LoopTripCountVersioning = 1;
-
- opts.UnrollLoops = args.hasFlag(clang::options::OPT_funroll_loops,
- clang::options::OPT_fno_unroll_loops,
- (opts.OptimizationLevel > 1));
-
- opts.AliasAnalysis = opts.OptimizationLevel > 0;
-
- // -mframe-pointer=none/non-leaf/reserved/all option.
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_mframe_pointer_EQ)) {
- std::optional<llvm::FramePointerKind> val =
- llvm::StringSwitch<std::optional<llvm::FramePointerKind>>(a->getValue())
- .Case("none", llvm::FramePointerKind::None)
- .Case("non-leaf", llvm::FramePointerKind::NonLeaf)
- .Case("non-leaf-no-reserve",
- llvm::FramePointerKind::NonLeafNoReserve)
- .Case("reserved", llvm::FramePointerKind::Reserved)
- .Case("all", llvm::FramePointerKind::All)
- .Default(std::nullopt);
-
- if (!val.has_value()) {
- diags.Report(clang::diag::err_drv_invalid_value)
- << a->getAsString(args) << a->getValue();
- } else
- opts.setFramePointer(val.value());
}
- for (auto *a : args.filtered(clang::options::OPT_fpass_plugin_EQ))
+ for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
opts.LLVMPassPlugins.push_back(a->getValue());
- opts.Reciprocals = clang::parseMRecipOption(diags, args);
-
- opts.PreferVectorWidth = clang::parseMPreferVectorWidthOption(diags, args);
-
// -fembed-offload-object option
- for (auto *a : args.filtered(clang::options::OPT_fembed_offload_object_EQ))
+ for (auto *a :
+ args.filtered(clang::driver::options::OPT_fembed_offload_object_EQ))
opts.OffloadObjects.push_back(a->getValue());
- if (args.hasArg(clang::options::OPT_finstrument_functions))
- opts.InstrumentFunctions = 1;
-
- if (args.hasArg(clang::options::OPT_fno_optimize_sibling_calls))
- opts.DisableTailCalls = 1;
-
- // -fno-integrated-as: emit GNU Assembler compatible assembly.
- if (!args.hasFlag(clang::options::OPT_fintegrated_as,
- clang::options::OPT_fno_integrated_as, true))
- opts.DisableIntegratedAS = 1;
-
- opts.FunctionSections =
- args.hasFlag(clang::options::OPT_ffunction_sections,
- clang::options::OPT_fno_function_sections,
- /*Default=*/false);
- opts.DataSections = args.hasFlag(clang::options::OPT_fdata_sections,
- clang::options::OPT_fno_data_sections,
- /*Default=*/false);
-
+ // -flto=full/thin option.
if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_mcode_object_version_EQ)) {
+ args.getLastArg(clang::driver::options::OPT_flto_EQ)) {
llvm::StringRef s = a->getValue();
- if (s == "6")
- opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_6;
- if (s == "5")
- opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_5;
- if (s == "4")
- opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_4;
- if (s == "none")
- opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_None;
- }
-
- // -f[no-]save-optimization-record[=<format>]
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_opt_record_file))
- opts.OptRecordFile = a->getValue();
-
- // Optimization file format. Defaults to yaml
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_opt_record_format))
- opts.OptRecordFormat = a->getValue();
-
- // Specifies, using a regex, which successful optimization passes(middle and
- // backend), to include in the final optimization record file generated. If
- // not provided -fsave-optimization-record will include all passes.
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_opt_record_passes))
- opts.OptRecordPasses = a->getValue();
-
- // Create OptRemark that allows printing of all successful optimization
- // passes applied.
- opts.OptimizationRemark =
- parseOptimizationRemark(diags, args, clang::options::OPT_Rpass_EQ,
- /*remarkOptName=*/"pass");
-
- // Create OptRemark that allows all missed optimization passes to be printed.
- opts.OptimizationRemarkMissed =
- parseOptimizationRemark(diags, args, clang::options::OPT_Rpass_missed_EQ,
- /*remarkOptName=*/"pass-missed");
-
- // Create OptRemark that allows all optimization decisions made by LLVM
- // to be printed.
- opts.OptimizationRemarkAnalysis = parseOptimizationRemark(
- diags, args, clang::options::OPT_Rpass_analysis_EQ,
- /*remarkOptName=*/"pass-analysis");
-
- if (opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo) {
- // If the user requested a flag that requires source locations available in
- // the backend, make sure that the backend tracks source location
- // information.
- bool needLocTracking = !opts.OptRecordFile.empty() ||
- !opts.OptRecordPasses.empty() ||
- !opts.OptRecordFormat.empty() ||
- opts.OptimizationRemark.hasValidPattern() ||
- opts.OptimizationRemarkMissed.hasValidPattern() ||
- opts.OptimizationRemarkAnalysis.hasValidPattern();
-
- if (needLocTracking)
- opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
+ assert((s == "full" || s == "thin") && "Unknown LTO mode.");
+ if (s == "full")
+ opts.PrepareForFullLTO = true;
+ else
+ opts.PrepareForThinLTO = true;
}
- if (auto *a = args.getLastArg(clang::options::OPT_save_temps_EQ))
+ if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
opts.SaveTempsDir = a->getValue();
- // -record-command-line option.
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_record_command_line)) {
- opts.RecordCommandLine = a->getValue();
- }
-
- // -mlink-builtin-bitcode
- for (auto *a : args.filtered(clang::options::OPT_mlink_builtin_bitcode))
- opts.BuiltinBCLibs.push_back(a->getValue());
-
// -mrelocation-model option.
if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_mrelocation_model)) {
+ args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
llvm::StringRef modelName = a->getValue();
auto relocModel =
llvm::StringSwitch<std::optional<llvm::Reloc::Model>>(modelName)
@@ -502,85 +214,24 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
}
// -pic-level and -pic-is-pie option.
- if (int picLevel =
- getLastArgIntValue(args, clang::options::OPT_pic_level, 0, diags)) {
+ if (int picLevel = getLastArgIntValue(
+ args, clang::driver::options::OPT_pic_level, 0, diags)) {
if (picLevel > 2)
diags.Report(clang::diag::err_drv_invalid_value)
- << args.getLastArg(clang::options::OPT_pic_level)->getAsString(args)
+ << args.getLastArg(clang::driver::options::OPT_pic_level)
+ ->getAsString(args)
<< picLevel;
opts.PICLevel = picLevel;
- if (args.hasArg(clang::options::OPT_pic_is_pie))
+ if (args.hasArg(clang::driver::options::OPT_pic_is_pie))
opts.IsPIE = 1;
}
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_fprofile_generate,
- clang::options::OPT_fprofile_generate_EQ)) {
- opts.setProfileInstr(llvm::driver::ProfileInstrKind::ProfileIRInstr);
- if (a->getOption().matches(clang::options::OPT_fprofile_generate_EQ)) {
- llvm::SmallString<128> path(a->getValue());
- llvm::sys::path::append(path, "default_%m.profraw");
- opts.InstrProfileOutput = std::string(path);
- }
- }
-
- if (auto A = args.getLastArg(clang::options::OPT_fprofile_use_EQ)) {
- opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileIRInstr);
- opts.ProfileInstrumentUsePath = A->getValue();
- }
-
- opts.SampleProfileFile =
- args.getLastArgValue(clang::options::OPT_fprofile_sample_use_EQ);
-
- if (args.hasFlag(clang::options::OPT_fpseudo_probe_for_profiling,
- clang::options::OPT_fno_pseudo_probe_for_profiling, false)) {
- opts.PseudoProbeForProfiling = 1;
- }
-
- // -mcmodel option.
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_mcmodel_EQ)) {
- llvm::StringRef modelName = a->getValue();
- std::optional<llvm::CodeModel::Model> codeModel = getCodeModel(modelName);
-
- if (codeModel.has_value())
- opts.CodeModel = modelName;
- else
- diags.Report(clang::diag::err_drv_invalid_value)
- << a->getAsString(args) << modelName;
- }
-
- if (const llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_mlarge_data_threshold_EQ)) {
- uint64_t LDT;
- if (llvm::StringRef(arg->getValue()).getAsInteger(/*Radix=*/10, LDT)) {
- diags.Report(clang::diag::err_drv_invalid_value)
- << arg->getSpelling() << arg->getValue();
- }
- opts.LargeDataThreshold = LDT;
- }
-
// This option is compatible with -f[no-]underscoring in gfortran.
- if (args.hasFlag(clang::options::OPT_fno_underscoring,
- clang::options::OPT_funderscoring, false)) {
+ if (args.hasFlag(clang::driver::options::OPT_fno_underscoring,
+ clang::driver::options::OPT_funderscoring, false)) {
opts.Underscoring = 0;
}
-
- if (const llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_complex_range_EQ)) {
- llvm::StringRef argValue = llvm::StringRef(arg->getValue());
- if (argValue == "full") {
- opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Full);
- } else if (argValue == "improved") {
- opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Improved);
- } else if (argValue == "basic") {
- opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Basic);
- } else {
- diags.Report(clang::diag::err_drv_invalid_value)
- << arg->getAsString(args) << arg->getValue();
- }
- }
}
/// Parses all target input arguments and populates the target
@@ -589,54 +240,19 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
/// \param [in] opts The target options instance to update
/// \param [in] args The list of input arguments (from the compiler invocation)
static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) {
- if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_triple))
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_triple))
opts.triple = a->getValue();
- opts.atomicIgnoreDenormalMode =
- args.hasFlag(clang::options::OPT_fatomic_ignore_denormal_mode,
- clang::options::OPT_fno_atomic_ignore_denormal_mode, false);
- opts.atomicFineGrainedMemory =
- args.hasFlag(clang::options::OPT_fatomic_fine_grained_memory,
- clang::options::OPT_fno_atomic_fine_grained_memory, false);
- opts.atomicRemoteMemory =
- args.hasFlag(clang::options::OPT_fatomic_remote_memory,
- clang::options::OPT_fno_atomic_remote_memory, false);
-
- if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_target_cpu))
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_target_cpu))
opts.cpu = a->getValue();
- if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_tune_cpu))
- opts.cpuToTuneFor = a->getValue();
-
for (const llvm::opt::Arg *currentArg :
- args.filtered(clang::options::OPT_target_feature))
+ args.filtered(clang::driver::options::OPT_target_feature))
opts.featuresAsWritten.emplace_back(currentArg->getValue());
-
- if (args.hasArg(clang::options::OPT_fdisable_real_10))
- opts.disabledRealKinds.push_back(10);
-
- if (args.hasArg(clang::options::OPT_fdisable_real_3))
- opts.disabledRealKinds.push_back(3);
-
- if (args.hasArg(clang::options::OPT_fdisable_integer_2))
- opts.disabledIntegerKinds.push_back(2);
-
- if (args.hasArg(clang::options::OPT_fdisable_integer_16))
- opts.disabledIntegerKinds.push_back(16);
-
- if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_mabi_EQ)) {
- llvm::StringRef V = a->getValue();
- // Normalize "vec-default" to an empty ABI name; the AIX extended Altivec
- // ABI is carried to the backend as the "vec-extabi" target-abi module flag.
- opts.abi = V == "vec-default" ? "" : V.str();
- }
-
- opts.SplitMachineFunctions =
- args.hasArg(clang::options::OPT_fsplit_machine_functions);
-
- opts.asmVerbose = args.hasFlag(clang::options::OPT_fverbose_asm,
- clang::options::OPT_fno_verbose_asm, false);
}
+
// Tweak the frontend configuration based on the frontend action
static void setUpFrontendBasedOnAction(FrontendOptions &opts) {
if (opts.programAction == DebugDumpParsingLog)
@@ -660,120 +276,113 @@ static std::optional<const char *> parseConvertArg(const char *s) {
static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
+ unsigned numErrorsBefore = diags.getNumErrors();
+
// By default the frontend driver creates a ParseSyntaxOnly action.
opts.programAction = ParseSyntaxOnly;
// Treat multiple action options as an invocation error. Note that `clang
// -cc1` does accept multiple action options, but will only consider the
// rightmost one.
- if (args.hasMultipleArgs(clang::options::OPT_Action_Group)) {
- llvm::SmallString<32> buf;
- llvm::raw_svector_ostream os(buf);
- for (const llvm::opt::Arg *arg :
- args.filtered(clang::options::OPT_Action_Group)) {
- if (buf.size())
- os << ", ";
- os << "'" << arg->getSpelling() << "'";
- }
- diags.Report(clang::diag::err_drv_too_many_actions) << buf;
+ if (args.hasMultipleArgs(clang::driver::options::OPT_Action_Group)) {
+ const unsigned diagID = diags.getCustomDiagID(
+ clang::DiagnosticsEngine::Error, "Only one action option is allowed");
+ diags.Report(diagID);
return false;
}
// Identify the action (i.e. opts.ProgramAction)
if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_Action_Group)) {
+ args.getLastArg(clang::driver::options::OPT_Action_Group)) {
switch (a->getOption().getID()) {
default: {
llvm_unreachable("Invalid option in group!");
}
- case clang::options::OPT_test_io:
+ case clang::driver::options::OPT_test_io:
opts.programAction = InputOutputTest;
break;
- case clang::options::OPT_E:
+ case clang::driver::options::OPT_E:
opts.programAction = PrintPreprocessedInput;
break;
- case clang::options::OPT_fsyntax_only:
+ case clang::driver::options::OPT_fsyntax_only:
opts.programAction = ParseSyntaxOnly;
break;
- case clang::options::OPT_emit_fir:
+ case clang::driver::options::OPT_emit_fir:
opts.programAction = EmitFIR;
break;
- case clang::options::OPT_emit_hlfir:
+ case clang::driver::options::OPT_emit_hlfir:
opts.programAction = EmitHLFIR;
break;
- case clang::options::OPT_emit_llvm:
+ case clang::driver::options::OPT_emit_llvm:
opts.programAction = EmitLLVM;
break;
- case clang::options::OPT_emit_llvm_bc:
+ case clang::driver::options::OPT_emit_llvm_bc:
opts.programAction = EmitLLVMBitcode;
break;
- case clang::options::OPT_emit_obj:
+ case clang::driver::options::OPT_emit_obj:
opts.programAction = EmitObj;
break;
- case clang::options::OPT_S:
+ case clang::driver::options::OPT_S:
opts.programAction = EmitAssembly;
break;
- case clang::options::OPT_fdebug_unparse:
+ case clang::driver::options::OPT_fdebug_unparse:
opts.programAction = DebugUnparse;
break;
- case clang::options::OPT_fdebug_unparse_no_sema:
+ case clang::driver::options::OPT_fdebug_unparse_no_sema:
opts.programAction = DebugUnparseNoSema;
break;
- case clang::options::OPT_fdebug_unparse_with_symbols:
+ case clang::driver::options::OPT_fdebug_unparse_with_symbols:
opts.programAction = DebugUnparseWithSymbols;
break;
- case clang::options::OPT_fdebug_unparse_with_modules:
- opts.programAction = DebugUnparseWithModules;
- break;
- case clang::options::OPT_fdebug_dump_symbols:
+ case clang::driver::options::OPT_fdebug_dump_symbols:
opts.programAction = DebugDumpSymbols;
break;
- case clang::options::OPT_fdebug_dump_parse_tree:
+ case clang::driver::options::OPT_fdebug_dump_parse_tree:
opts.programAction = DebugDumpParseTree;
break;
- case clang::options::OPT_fdebug_dump_pft:
+ case clang::driver::options::OPT_fdebug_dump_pft:
opts.programAction = DebugDumpPFT;
break;
- case clang::options::OPT_fdebug_dump_all:
+ case clang::driver::options::OPT_fdebug_dump_all:
opts.programAction = DebugDumpAll;
break;
- case clang::options::OPT_fdebug_dump_parse_tree_no_sema:
+ case clang::driver::options::OPT_fdebug_dump_parse_tree_no_sema:
opts.programAction = DebugDumpParseTreeNoSema;
break;
- case clang::options::OPT_fdebug_dump_provenance:
+ case clang::driver::options::OPT_fdebug_dump_provenance:
opts.programAction = DebugDumpProvenance;
break;
- case clang::options::OPT_fdebug_dump_parsing_log:
+ case clang::driver::options::OPT_fdebug_dump_parsing_log:
opts.programAction = DebugDumpParsingLog;
break;
- case clang::options::OPT_fdebug_measure_parse_tree:
+ case clang::driver::options::OPT_fdebug_measure_parse_tree:
opts.programAction = DebugMeasureParseTree;
break;
- case clang::options::OPT_fdebug_pre_fir_tree:
+ case clang::driver::options::OPT_fdebug_pre_fir_tree:
opts.programAction = DebugPreFIRTree;
break;
- case clang::options::OPT_fget_symbols_sources:
+ case clang::driver::options::OPT_fget_symbols_sources:
opts.programAction = GetSymbolsSources;
break;
- case clang::options::OPT_fget_definition:
+ case clang::driver::options::OPT_fget_definition:
opts.programAction = GetDefinition;
break;
- case clang::options::OPT_init_only:
+ case clang::driver::options::OPT_init_only:
opts.programAction = InitOnly;
break;
// TODO:
- // case clang::options::OPT_emit_llvm:
- // case clang::options::OPT_emit_llvm_only:
- // case clang::options::OPT_emit_codegen_only:
- // case clang::options::OPT_emit_module:
+ // case clang::driver::options::OPT_emit_llvm:
+ // case clang::driver::options::OPT_emit_llvm_only:
+ // case clang::driver::options::OPT_emit_codegen_only:
+ // case clang::driver::options::OPT_emit_module:
// (...)
}
// Parse the values provided with `-fget-definition` (there should be 3
// integers)
if (llvm::opt::OptSpecifier(a->getOption().getID()) ==
- clang::options::OPT_fget_definition) {
+ clang::driver::options::OPT_fget_definition) {
unsigned optVals[3] = {0, 0, 0};
for (unsigned i = 0; i < 3; i++) {
@@ -793,28 +402,25 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
}
// Parsing -load <dsopath> option and storing shared object path
- if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_load)) {
+ if (llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_load)) {
opts.plugins.push_back(a->getValue());
}
// Parsing -plugin <name> option and storing plugin name and setting action
- if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_plugin)) {
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_plugin)) {
opts.programAction = PluginAction;
opts.actionName = a->getValue();
}
- opts.outputFile = args.getLastArgValue(clang::options::OPT_o);
- opts.dependencyOutputFile =
- args.getLastArgValue(clang::options::OPT_dependency_file);
- opts.dependencyTargets = args.getAllArgValues(clang::options::OPT_MT);
- opts.showHelp = args.hasArg(clang::options::OPT_help);
- opts.showVersion = args.hasArg(clang::options::OPT_version);
- opts.printSupportedCPUs =
- args.hasArg(clang::options::OPT_print_supported_cpus);
+ opts.outputFile = args.getLastArgValue(clang::driver::options::OPT_o);
+ opts.showHelp = args.hasArg(clang::driver::options::OPT_help);
+ opts.showVersion = args.hasArg(clang::driver::options::OPT_version);
// Get the input kind (from the value passed via `-x`)
InputKind dashX(Language::Unknown);
- if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_x)) {
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_x)) {
llvm::StringRef xValue = a->getValue();
// Principal languages.
dashX = llvm::StringSwitch<InputKind>(xValue)
@@ -822,8 +428,6 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
// pre-processed inputs.
.Case("f95", Language::Fortran)
.Case("f95-cpp-input", Language::Fortran)
- // CUDA Fortran
- .Case("cuda", Language::Fortran)
.Default(Language::Unknown);
// Flang's intermediate representations.
@@ -841,7 +445,7 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
// Collect the input files and save them in our instance of FrontendOptions.
std::vector<std::string> inputs =
- args.getAllArgValues(clang::options::OPT_INPUT);
+ args.getAllArgValues(clang::driver::options::OPT_INPUT);
opts.inputs.clear();
if (inputs.empty())
// '-' is the default input if none is given.
@@ -861,47 +465,53 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
}
// Set fortranForm based on options -ffree-form and -ffixed-form.
- if (const auto *arg = args.getLastArg(clang::options::OPT_ffixed_form,
- clang::options::OPT_ffree_form)) {
- opts.fortranForm = arg->getOption().matches(clang::options::OPT_ffixed_form)
- ? FortranForm::FixedForm
- : FortranForm::FreeForm;
+ if (const auto *arg =
+ args.getLastArg(clang::driver::options::OPT_ffixed_form,
+ clang::driver::options::OPT_ffree_form)) {
+ opts.fortranForm =
+ arg->getOption().matches(clang::driver::options::OPT_ffixed_form)
+ ? FortranForm::FixedForm
+ : FortranForm::FreeForm;
}
// Set fixedFormColumns based on -ffixed-line-length=<value>
if (const auto *arg =
- args.getLastArg(clang::options::OPT_ffixed_line_length_EQ)) {
+ args.getLastArg(clang::driver::options::OPT_ffixed_line_length_EQ)) {
llvm::StringRef argValue = llvm::StringRef(arg->getValue());
+ bool correctness_of_input = !argValue.empty();
+ for(auto char_in_string: argValue) {
+ if(char_in_string>='0' && char_in_string<='9') {
+ continue;
+ } else {
+ correctness_of_input=false;
+ break;
+ }
+ }
std::int64_t columns = -1;
if (argValue == "none") {
columns = 0;
} else if (argValue.getAsInteger(/*Radix=*/10, columns)) {
- if (!argValue.empty() && llvm::all_of(argValue, llvm::isDigit)) {
- // Route oversized positive decimals to the large-columns diagnostic.
- columns = std::numeric_limits<std::int64_t>::max();
- } else {
- columns = -1;
- }
+ columns = -1;
}
- if (columns < 0) {
+ if(correctness_of_input && columns==-1) {
+ diags.Report(clang::diag::err_drv_large_columns)
+ << arg->getOption().getName() << arg->getValue();
+ } else if (columns < 0) {
diags.Report(clang::diag::err_drv_negative_columns)
<< arg->getOption().getName() << arg->getValue();
} else if (columns == 0) {
- opts.fixedFormColumns = std::nullopt;
+ opts.fixedFormColumns = 1000000;
} else if (columns < 7) {
diags.Report(clang::diag::err_drv_small_columns)
<< arg->getOption().getName() << arg->getValue() << "7";
- } else if (columns > std::numeric_limits<int>::max()) {
- diags.Report(clang::diag::err_drv_large_columns)
- << arg->getOption().getName() << arg->getValue()
- << std::numeric_limits<int>::max();
} else {
opts.fixedFormColumns = columns;
}
}
// Set conversion based on -fconvert=<value>
- if (const auto *arg = args.getLastArg(clang::options::OPT_fconvert_EQ)) {
+ if (const auto *arg =
+ args.getLastArg(clang::driver::options::OPT_fconvert_EQ)) {
const char *argValue = arg->getValue();
if (auto convert = parseConvertArg(argValue))
opts.envDefaults.push_back({"FORT_CONVERT", *convert});
@@ -911,96 +521,41 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
}
// -f{no-}implicit-none
- opts.features.Enable(Fortran::common::LanguageFeature::ImplicitNoneTypeAlways,
- args.hasFlag(clang::options::OPT_fimplicit_none,
- clang::options::OPT_fno_implicit_none,
- false));
-
- // -f{no-}implicit-none-ext
- opts.features.Enable(Fortran::common::LanguageFeature::ImplicitNoneExternal,
- args.hasFlag(clang::options::OPT_fimplicit_none_ext,
- clang::options::OPT_fno_implicit_none_ext,
- false));
-
- // -f{no-}implicit-module-prefix
opts.features.Enable(
- Fortran::common::LanguageFeature::ImplicitModulePrefix,
- args.hasFlag(clang::options::OPT_fimplicit_module_prefix,
- clang::options::OPT_fno_implicit_module_prefix, false));
+ Fortran::common::LanguageFeature::ImplicitNoneTypeAlways,
+ args.hasFlag(clang::driver::options::OPT_fimplicit_none,
+ clang::driver::options::OPT_fno_implicit_none, false));
// -f{no-}backslash
opts.features.Enable(Fortran::common::LanguageFeature::BackslashEscapes,
- args.hasFlag(clang::options::OPT_fbackslash,
- clang::options::OPT_fno_backslash, false));
+ args.hasFlag(clang::driver::options::OPT_fbackslash,
+ clang::driver::options::OPT_fno_backslash,
+ false));
// -f{no-}logical-abbreviations
opts.features.Enable(
Fortran::common::LanguageFeature::LogicalAbbreviations,
- args.hasFlag(clang::options::OPT_flogical_abbreviations,
- clang::options::OPT_fno_logical_abbreviations, false));
-
- // -f{no-}unsigned
- opts.features.Enable(Fortran::common::LanguageFeature::Unsigned,
- args.hasFlag(clang::options::OPT_funsigned,
- clang::options::OPT_fno_unsigned, false));
-
- // -f{no-}out-of-bounds-subscripts
- opts.features.Enable(
- Fortran::common::LanguageFeature::OutOfBoundsSubscripts,
- args.hasFlag(clang::options::OPT_fout_of_bounds_subscripts,
- clang::options::OPT_fno_out_of_bounds_subscripts, true));
-
- // -frelaxed-c-loc-checks
- if (args.hasArg(clang::options::OPT_relaxed_c_loc)) {
- opts.features.Enable(Fortran::common::LanguageFeature::RelaxedCLocChecks);
- }
-
- // -f{no-}openacc-default-none-scalars-strict
- opts.features.Enable(
- Fortran::common::LanguageFeature::OpenAccDefaultNoneScalarsStrict,
- args.hasFlag(clang::options::OPT_fopenacc_default_none_scalars_strict,
- clang::options::OPT_fno_openacc_default_none_scalars_strict,
+ args.hasFlag(clang::driver::options::OPT_flogical_abbreviations,
+ clang::driver::options::OPT_fno_logical_abbreviations,
false));
- // -f{no-}openacc-multiple-names-in-routine
- opts.features.Enable(
- Fortran::common::LanguageFeature::OpenACCMultipleNamesInRoutine,
- args.hasFlag(clang::options::OPT_fopenacc_multiple_names_in_routine,
- clang::options::OPT_fno_openacc_multiple_names_in_routine,
- true));
-
- // -f{no-}prefer-intrinsic-module-use-association
- if (const auto *arg = args.getLastArg(
- clang::options::OPT_fprefer_intrinsic_module_use_association,
- clang::options::OPT_fno_prefer_intrinsic_module_use_association)) {
- opts.features.Enable(
- Fortran::common::LanguageFeature::PreferIntrinsicModuleUseAssociation,
- arg->getOption().matches(
- clang::options::OPT_fprefer_intrinsic_module_use_association));
- }
-
// -f{no-}xor-operator
- opts.features.Enable(Fortran::common::LanguageFeature::XOROperator,
- args.hasFlag(clang::options::OPT_fxor_operator,
- clang::options::OPT_fno_xor_operator,
- false));
+ opts.features.Enable(
+ Fortran::common::LanguageFeature::XOROperator,
+ args.hasFlag(clang::driver::options::OPT_fxor_operator,
+ clang::driver::options::OPT_fno_xor_operator, false));
// -fno-automatic
- if (args.hasArg(clang::options::OPT_fno_automatic)) {
+ if (args.hasArg(clang::driver::options::OPT_fno_automatic)) {
opts.features.Enable(Fortran::common::LanguageFeature::DefaultSave);
}
- // -f{no}-save-main-program
- opts.features.Enable(Fortran::common::LanguageFeature::SaveMainProgram,
- args.hasFlag(clang::options::OPT_fsave_main_program,
- clang::options::OPT_fno_save_main_program,
- false));
-
- if (args.hasArg(clang::options::OPT_falternative_parameter_statement)) {
+ if (args.hasArg(
+ clang::driver::options::OPT_falternative_parameter_statement)) {
opts.features.Enable(Fortran::common::LanguageFeature::OldStyleParameter);
}
if (const llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_finput_charset_EQ)) {
+ args.getLastArg(clang::driver::options::OPT_finput_charset_EQ)) {
llvm::StringRef argValue = arg->getValue();
if (argValue == "utf-8") {
opts.encoding = Fortran::parser::Encoding::UTF_8;
@@ -1015,19 +570,28 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
setUpFrontendBasedOnAction(opts);
opts.dashX = dashX;
- return !diags.hasUncompilableErrorOccurred();
+ return diags.getNumErrors() == numErrorsBefore;
}
// Generate the path to look for intrinsic modules
-static std::string getIntrinsicDir(const char *argv) {
+static std::string getIntrinsicDir() {
// TODO: Find a system independent API
llvm::SmallString<128> driverPath;
- driverPath.assign(llvm::sys::fs::getMainExecutable(argv, nullptr));
+ driverPath.assign(llvm::sys::fs::getMainExecutable(nullptr, nullptr));
llvm::sys::path::remove_filename(driverPath);
driverPath.append("/../include/flang/");
return std::string(driverPath);
}
+// Generate the path to look for OpenMP headers
+static std::string getOpenMPHeadersDir() {
+ llvm::SmallString<128> includePath;
+ includePath.assign(llvm::sys::fs::getMainExecutable(nullptr, nullptr));
+ llvm::sys::path::remove_filename(includePath);
+ includePath.append("/../include/flang/OpenMP/");
+ return std::string(includePath);
+}
+
/// Parses all preprocessor input arguments and populates the preprocessor
/// options accordingly.
///
@@ -1036,9 +600,9 @@ static std::string getIntrinsicDir(const char *argv) {
static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
llvm::opt::ArgList &args) {
// Add macros from the command line.
- for (const auto *currentArg :
- args.filtered(clang::options::OPT_D, clang::options::OPT_U)) {
- if (currentArg->getOption().matches(clang::options::OPT_D)) {
+ for (const auto *currentArg : args.filtered(clang::driver::options::OPT_D,
+ clang::driver::options::OPT_U)) {
+ if (currentArg->getOption().matches(clang::driver::options::OPT_D)) {
opts.addMacroDef(currentArg->getValue());
} else {
opts.addMacroUndef(currentArg->getValue());
@@ -1046,212 +610,116 @@ static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
}
// Add the ordered list of -I's.
- for (const auto *currentArg : args.filtered(clang::options::OPT_I))
+ for (const auto *currentArg : args.filtered(clang::driver::options::OPT_I))
opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue());
// Prepend the ordered list of -intrinsic-modules-path
// to the default location to search.
for (const auto *currentArg :
- args.filtered(clang::options::OPT_fintrinsic_modules_path))
+ args.filtered(clang::driver::options::OPT_fintrinsic_modules_path))
opts.searchDirectoriesFromIntrModPath.emplace_back(currentArg->getValue());
// -cpp/-nocpp
- if (const auto *currentArg =
- args.getLastArg(clang::options::OPT_cpp, clang::options::OPT_nocpp))
- opts.macrosFlag = (currentArg->getOption().matches(clang::options::OPT_cpp))
- ? PPMacrosFlag::Include
- : PPMacrosFlag::Exclude;
- // Enable -cpp based on -x unless explicitly disabled with -nocpp
- if (opts.macrosFlag != PPMacrosFlag::Exclude)
- if (const auto *dashX = args.getLastArg(clang::options::OPT_x))
- opts.macrosFlag = llvm::StringSwitch<PPMacrosFlag>(dashX->getValue())
- .Case("f95-cpp-input", PPMacrosFlag::Include)
- .Default(opts.macrosFlag);
-
- opts.noReformat = args.hasArg(clang::options::OPT_fno_reformat);
- opts.preprocessIncludeLines =
- args.hasArg(clang::options::OPT_fpreprocess_include_lines);
- opts.noLineDirectives = args.hasArg(clang::options::OPT_P);
- opts.showMacros = args.hasArg(clang::options::OPT_dM);
+ if (const auto *currentArg = args.getLastArg(
+ clang::driver::options::OPT_cpp, clang::driver::options::OPT_nocpp))
+ opts.macrosFlag =
+ (currentArg->getOption().matches(clang::driver::options::OPT_cpp))
+ ? PPMacrosFlag::Include
+ : PPMacrosFlag::Exclude;
+
+ opts.noReformat = args.hasArg(clang::driver::options::OPT_fno_reformat);
+ opts.noLineDirectives = args.hasArg(clang::driver::options::OPT_P);
}
/// Parses all semantic related arguments and populates the variables
/// options accordingly. Returns false if new errors are generated.
static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
+ unsigned numErrorsBefore = diags.getNumErrors();
+
// -J/module-dir option
- std::vector<std::string> moduleDirList =
- args.getAllArgValues(clang::options::OPT_module_dir);
- // User can only specify one -J/-module-dir directory, but may repeat
- // -J/-module-dir as long as the directory is the same each time.
+ auto moduleDirList =
+ args.getAllArgValues(clang::driver::options::OPT_module_dir);
+ // User can only specify -J/-module-dir once
// https://gcc.gnu.org/onlinedocs/gfortran/Directory-Options.html
- std::sort(moduleDirList.begin(), moduleDirList.end());
- moduleDirList.erase(std::unique(moduleDirList.begin(), moduleDirList.end()),
- moduleDirList.end());
if (moduleDirList.size() > 1) {
const unsigned diagID =
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "Only one '-module-dir/-J' directory allowed. "
- "'-module-dir/-J' may be given multiple times "
- "but the directory must be the same each time.");
+ "Only one '-module-dir/-J' option allowed");
diags.Report(diagID);
}
if (moduleDirList.size() == 1)
res.setModuleDir(moduleDirList[0]);
// -fdebug-module-writer option
- if (args.hasArg(clang::options::OPT_fdebug_module_writer)) {
+ if (args.hasArg(clang::driver::options::OPT_fdebug_module_writer)) {
res.setDebugModuleDir(true);
}
- // -fhermetic-module-files option
- if (args.hasArg(clang::options::OPT_fhermetic_module_files)) {
- res.setHermeticModuleFileOutput(true);
- }
-
// -module-suffix
if (const auto *moduleSuffix =
- args.getLastArg(clang::options::OPT_module_suffix)) {
+ args.getLastArg(clang::driver::options::OPT_module_suffix)) {
res.setModuleFileSuffix(moduleSuffix->getValue());
}
// -f{no-}analyzed-objects-for-unparse
- res.setUseAnalyzedObjectsForUnparse(
- args.hasFlag(clang::options::OPT_fanalyzed_objects_for_unparse,
- clang::options::OPT_fno_analyzed_objects_for_unparse, true));
+ res.setUseAnalyzedObjectsForUnparse(args.hasFlag(
+ clang::driver::options::OPT_fanalyzed_objects_for_unparse,
+ clang::driver::options::OPT_fno_analyzed_objects_for_unparse, true));
- return !diags.hasUncompilableErrorOccurred();
+ return diags.getNumErrors() == numErrorsBefore;
}
/// Parses all diagnostics related arguments and populates the variables
/// options accordingly. Returns false if new errors are generated.
-/// FC1 driver entry point for parsing diagnostic arguments.
static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
- auto &features{res.getFrontendOpts().features};
- // The order of these flags (-pedantic -W<feature> -w) is important and is
- // chosen to match clang's behavior.
-
- // -pedantic
- if (args.hasArg(clang::options::OPT_pedantic)) {
- features.WarnOnAllNonstandard();
- features.WarnOnAllUsage();
- res.setEnableConformanceChecks();
- res.setEnableUsageChecks();
- }
+ unsigned numErrorsBefore = diags.getNumErrors();
// -Werror option
// TODO: Currently throws a Diagnostic for anything other than -W<error>,
// this has to change when other -W<opt>'s are supported.
- if (args.hasArg(clang::options::OPT_W_Joined)) {
- const auto &wArgs = args.getAllArgValues(clang::options::OPT_W_Joined);
- // TODO: Consider using std::string_view instead of llvm::StringRef
- // when moving to C++20:
- for (const llvm::StringRef wArg : wArgs) {
+ if (args.hasArg(clang::driver::options::OPT_W_Joined)) {
+ const auto &wArgs =
+ args.getAllArgValues(clang::driver::options::OPT_W_Joined);
+ for (const auto &wArg : wArgs) {
if (wArg == "error") {
res.setWarnAsErr(true);
- // -Wfatal-errors
- } else if (wArg == "fatal-errors") {
- res.setMaxErrors(1);
- // -W[no-]<feature>
- } else if (features.EnableWarning(wArg)) {
- if (auto canonical{features.CheckDeprecatedSpelling(wArg)}) {
- std::string suggestion{*canonical};
- if (wArg.starts_with("no-")) {
- suggestion = "no-" + suggestion;
- }
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Warning,
- "-W%0 is deprecated; use -W%1 instead");
- diags.Report(diagID) << wArg << suggestion;
- }
} else {
- const unsigned diagID = diags.getCustomDiagID(
- clang::DiagnosticsEngine::Error, "Unknown diagnostic option: -W%0");
- diags.Report(diagID) << wArg;
+ const unsigned diagID =
+ diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
+ "Only `-Werror` is supported currently.");
+ diags.Report(diagID);
}
}
}
- // -w
- if (args.hasArg(clang::options::OPT_w)) {
- features.DisableAllWarnings();
- res.setDisableWarnings();
- }
+ // Default to off for `flang-new -fc1`.
+ res.getFrontendOpts().showColors =
+ parseShowColorsArgs(args, /*defaultDiagColor=*/false);
- // Default to off for `flang -fc1`.
- bool showColors{parseShowColorsArgs(args, false)};
- auto colorsMode =
- showColors ? clang::ShowColorsKind::On : clang::ShowColorsKind::Off;
- diags.getDiagnosticOptions().setShowColors(colorsMode);
- res.getDiagnosticOpts().setShowColors(colorsMode);
- res.getFrontendOpts().showColors = showColors;
- return !diags.hasUncompilableErrorOccurred();
+ return diags.getNumErrors() == numErrorsBefore;
}
/// Parses all Dialect related arguments and populates the variables
/// options accordingly. Returns false if new errors are generated.
static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
- // -fd-lines-as-code
- if (args.hasArg(clang::options::OPT_fd_lines_as_code)) {
- if (res.getFrontendOpts().fortranForm == FortranForm::FreeForm) {
- const unsigned fdLinesAsWarning = diags.getCustomDiagID(
- clang::DiagnosticsEngine::Warning,
- "‘-fd-lines-as-code’ has no effect in free form.");
- diags.Report(fdLinesAsWarning);
- } else {
- res.getFrontendOpts().features.Enable(
- Fortran::common::LanguageFeature::OldDebugLines, true);
- }
- }
-
- // -fd-lines-as-comments
- if (args.hasArg(clang::options::OPT_fd_lines_as_comments)) {
- if (res.getFrontendOpts().fortranForm == FortranForm::FreeForm) {
- const unsigned fdLinesAsWarning = diags.getCustomDiagID(
- clang::DiagnosticsEngine::Warning,
- "‘-fd-lines-as-comments’ has no effect in free form.");
- diags.Report(fdLinesAsWarning);
- } else {
- res.getFrontendOpts().features.Enable(
- Fortran::common::LanguageFeature::OldDebugLines, false);
- }
- }
+ unsigned numErrorsBefore = diags.getNumErrors();
// -fdefault* family
- if (const llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_fdefault_real_8,
- clang::options::OPT_fdefault_real_4)) {
- const llvm::opt::Option &opt = arg->getOption();
- if (opt.matches(clang::options::OPT_fdefault_real_8)) {
- res.getDefaultKinds().set_defaultRealKind(8);
- res.getDefaultKinds().set_doublePrecisionKind(16);
- } else if (opt.matches(clang::options::OPT_fdefault_real_4)) {
- res.getDefaultKinds().set_defaultRealKind(4);
- res.getDefaultKinds().set_doublePrecisionKind(8);
- }
+ if (args.hasArg(clang::driver::options::OPT_fdefault_real_8)) {
+ res.getDefaultKinds().set_defaultRealKind(8);
+ res.getDefaultKinds().set_doublePrecisionKind(16);
}
- if (const llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_fdefault_integer_8,
- clang::options::OPT_fdefault_integer_4)) {
- const llvm::opt::Option &opt = arg->getOption();
- if (opt.matches(clang::options::OPT_fdefault_integer_8)) {
- res.getDefaultKinds().set_defaultIntegerKind(8);
- res.getDefaultKinds().set_subscriptIntegerKind(8);
- res.getDefaultKinds().set_sizeIntegerKind(8);
- res.getDefaultKinds().set_defaultLogicalKind(8);
- } else if (opt.matches(clang::options::OPT_fdefault_integer_4)) {
- // Note that the subscript integer kind is set to 8 here. If a
- // default-integer-kind is not provided, it is also set to 8.
- res.getDefaultKinds().set_defaultIntegerKind(4);
- res.getDefaultKinds().set_subscriptIntegerKind(8);
- res.getDefaultKinds().set_sizeIntegerKind(4);
- res.getDefaultKinds().set_defaultLogicalKind(4);
- }
+ if (args.hasArg(clang::driver::options::OPT_fdefault_integer_8)) {
+ res.getDefaultKinds().set_defaultIntegerKind(8);
+ res.getDefaultKinds().set_subscriptIntegerKind(8);
+ res.getDefaultKinds().set_sizeIntegerKind(8);
+ res.getDefaultKinds().set_defaultLogicalKind(8);
}
- if (args.hasArg(clang::options::OPT_fdefault_double_8)) {
- if (!args.hasArg(clang::options::OPT_fdefault_real_8)) {
+ if (args.hasArg(clang::driver::options::OPT_fdefault_double_8)) {
+ if (!args.hasArg(clang::driver::options::OPT_fdefault_real_8)) {
// -fdefault-double-8 has to be used with -fdefault-real-8
// to be compatible with gfortran
const unsigned diagID = diags.getCustomDiagID(
@@ -1262,31 +730,102 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
// https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html
res.getDefaultKinds().set_doublePrecisionKind(8);
}
- if (args.hasArg(clang::options::OPT_flarge_sizes))
+ if (args.hasArg(clang::driver::options::OPT_flarge_sizes))
res.getDefaultKinds().set_sizeIntegerKind(8);
- // -x cuda
- auto language = args.getLastArgValue(clang::options::OPT_x);
- if (language == "cuda") {
+ // -fopenmp and -fopenacc
+ if (args.hasArg(clang::driver::options::OPT_fopenacc)) {
res.getFrontendOpts().features.Enable(
- Fortran::common::LanguageFeature::CUDA);
+ Fortran::common::LanguageFeature::OpenACC);
}
-
- // -fopenacc
- if (args.hasArg(clang::options::OPT_fopenacc)) {
+ if (args.hasArg(clang::driver::options::OPT_fopenmp)) {
+ // By default OpenMP is set to 1.1 version
+ res.getLangOpts().OpenMPVersion = 11;
res.getFrontendOpts().features.Enable(
- Fortran::common::LanguageFeature::OpenACC);
+ Fortran::common::LanguageFeature::OpenMP);
+ if (int Version = getLastArgIntValue(
+ args, clang::driver::options::OPT_fopenmp_version_EQ,
+ res.getLangOpts().OpenMPVersion, diags)) {
+ res.getLangOpts().OpenMPVersion = Version;
+ }
+ if (args.hasArg(clang::driver::options::OPT_fopenmp_is_target_device)) {
+ res.getLangOpts().OpenMPIsTargetDevice = 1;
+
+ // Get OpenMP host file path if any and report if a non existent file is
+ // found
+ if (auto *arg = args.getLastArg(
+ clang::driver::options::OPT_fopenmp_host_ir_file_path)) {
+ res.getLangOpts().OMPHostIRFile = arg->getValue();
+ if (!llvm::sys::fs::exists(res.getLangOpts().OMPHostIRFile))
+ diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found)
+ << res.getLangOpts().OMPHostIRFile;
+ }
+
+ if (args.hasFlag(
+ clang::driver::options::OPT_fopenmp_assume_teams_oversubscription,
+ clang::driver::options::
+ OPT_fno_openmp_assume_teams_oversubscription,
+ /*Default=*/false))
+ res.getLangOpts().OpenMPTeamSubscription = true;
+
+ if (args.hasArg(
+ clang::driver::options::OPT_fopenmp_assume_no_thread_state))
+ res.getLangOpts().OpenMPNoThreadState = 1;
+
+ if (args.hasArg(
+ clang::driver::options::OPT_fopenmp_assume_no_nested_parallelism))
+ res.getLangOpts().OpenMPNoNestedParallelism = 1;
+
+ if (args.hasFlag(clang::driver::options::
+ OPT_fopenmp_assume_threads_oversubscription,
+ clang::driver::options::
+ OPT_fno_openmp_assume_threads_oversubscription,
+ /*Default=*/false))
+ res.getLangOpts().OpenMPThreadSubscription = true;
+
+ if ((args.hasArg(clang::driver::options::OPT_fopenmp_target_debug) ||
+ args.hasArg(clang::driver::options::OPT_fopenmp_target_debug_EQ))) {
+ res.getLangOpts().OpenMPTargetDebug = getLastArgIntValue(
+ args, clang::driver::options::OPT_fopenmp_target_debug_EQ,
+ res.getLangOpts().OpenMPTargetDebug, diags);
+
+ if (!res.getLangOpts().OpenMPTargetDebug &&
+ args.hasArg(clang::driver::options::OPT_fopenmp_target_debug))
+ res.getLangOpts().OpenMPTargetDebug = 1;
+ }
+ }
+
+ switch (llvm::Triple(res.getTargetOpts().triple).getArch()) {
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ case llvm::Triple::amdgcn:
+ if (!res.getLangOpts().OpenMPIsTargetDevice) {
+ const unsigned diagID = diags.getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "OpenMP AMDGPU/NVPTX is only prepared to deal with device code.");
+ diags.Report(diagID);
+ }
+ res.getLangOpts().OpenMPIsGPU = 1;
+ break;
+ default:
+ res.getLangOpts().OpenMPIsGPU = 0;
+ break;
+ }
}
+ // -pedantic
+ if (args.hasArg(clang::driver::options::OPT_pedantic)) {
+ res.setEnableConformanceChecks();
+ res.setEnableUsageChecks();
+ }
// -std=f2018
// TODO: Set proper options when more fortran standards
// are supported.
- if (args.hasArg(clang::options::OPT_std_EQ)) {
- auto standard = args.getLastArgValue(clang::options::OPT_std_EQ);
+ if (args.hasArg(clang::driver::options::OPT_std_EQ)) {
+ auto standard = args.getLastArgValue(clang::driver::options::OPT_std_EQ);
// We only allow f2018 as the given standard
- if (standard == "f2018") {
+ if (standard.equals("f2018")) {
res.setEnableConformanceChecks();
- res.getFrontendOpts().features.WarnOnAllNonstandard();
} else {
const unsigned diagID =
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
@@ -1294,241 +833,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
diags.Report(diagID);
}
}
- // -fcoarray
- if (args.hasArg(clang::options::OPT_fcoarray)) {
- res.getFrontendOpts().features.Enable(
- Fortran::common::LanguageFeature::Coarray);
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Warning,
- "Support for multi image Fortran features is "
- "still experimental and in development.");
- diags.Report(diagID);
- }
-
- return !diags.hasUncompilableErrorOccurred();
-}
-
-/// Parses all OpenMP related arguments if the -fopenmp option is present,
-/// populating the \c res object accordingly. Returns false if new errors are
-/// generated.
-static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
- clang::DiagnosticsEngine &diags) {
- llvm::opt::Arg *arg = args.getLastArg(clang::options::OPT_fopenmp,
- clang::options::OPT_fno_openmp);
- if (!arg || arg->getOption().matches(clang::options::OPT_fno_openmp)) {
- bool isSimdSpecified =
- args.hasFlag(clang::options::OPT_fopenmp_simd,
- clang::options::OPT_fno_openmp_simd, /*Default=*/false);
- if (!isSimdSpecified)
- return true;
- res.getLangOpts().OpenMPSimd = 1;
- }
-
- llvm::Triple t(res.getTargetOpts().triple);
-
- constexpr unsigned newestFullySupported = 31;
- constexpr unsigned latestFinalized = 60;
- // By default OpenMP is set to the most recent fully supported version
- res.getLangOpts().OpenMPVersion = newestFullySupported;
- res.getFrontendOpts().features.Enable(
- Fortran::common::LanguageFeature::OpenMP);
- if (auto *arg = args.getLastArg(clang::options::OPT_fopenmp_version_EQ)) {
- llvm::SmallVector<unsigned> ompVersions;
- for (llvm::omp::Version v : llvm::omp::getOpenMPVersions()) {
- ompVersions.push_back(static_cast<unsigned>(v));
- }
- unsigned oldVersions[] = {11, 20, 25, 30};
- unsigned version = 0;
-
- auto reportBadVersion = [&](llvm::StringRef value) {
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "'%0' is not a valid OpenMP version in '%1', "
- "valid versions are %2");
- std::string buffer;
- llvm::raw_string_ostream versions(buffer);
- llvm::interleaveComma(ompVersions, versions);
-
- diags.Report(diagID) << value << arg->getAsString(args) << versions.str();
- };
-
- llvm::StringRef value = arg->getValue();
- if (!value.getAsInteger(/*radix=*/10, version)) {
- if (llvm::is_contained(ompVersions, version)) {
- res.getLangOpts().OpenMPVersion = version;
-
- if (version > latestFinalized)
- diags.Report(clang::diag::warn_openmp_spec_incomplete) << version;
- else if (version > newestFullySupported)
- diags.Report(clang::diag::warn_openmp_impl_incomplete) << version;
- } else if (llvm::is_contained(oldVersions, version)) {
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Warning,
- "OpenMP version %0 is no longer supported, "
- "assuming version %1");
- std::string assumed = std::to_string(res.getLangOpts().OpenMPVersion);
- diags.Report(diagID) << value << assumed;
- } else {
- reportBadVersion(value);
- }
- } else {
- reportBadVersion(value);
- }
- }
-
- if (args.hasFlag(clang::options::OPT_fopenmp_assume_teams_oversubscription,
- clang::options::OPT_fno_openmp_assume_teams_oversubscription,
- /*Default=*/false))
- res.getLangOpts().OpenMPTeamSubscription = true;
- if (args.hasFlag(
- clang::options::OPT_fopenmp_assume_threads_oversubscription,
- clang::options::OPT_fno_openmp_assume_threads_oversubscription,
- /*Default=*/false))
- res.getLangOpts().OpenMPThreadSubscription = true;
-
- if (args.hasArg(clang::options::OPT_fopenmp_force_usm)) {
- res.getLangOpts().OpenMPForceUSM = 1;
- }
- if (args.hasArg(clang::options::OPT_fopenmp_is_target_device)) {
- res.getLangOpts().OpenMPIsTargetDevice = 1;
-
- // Get OpenMP host file path if any and report if a non existent file is
- // found
- if (auto *arg =
- args.getLastArg(clang::options::OPT_fopenmp_host_ir_file_path)) {
- res.getLangOpts().OMPHostIRFile = arg->getValue();
- if (!llvm::sys::fs::exists(res.getLangOpts().OMPHostIRFile))
- diags.Report(clang::diag::err_omp_host_ir_file_not_found)
- << res.getLangOpts().OMPHostIRFile;
- }
-
- if (args.hasArg(clang::options::OPT_fopenmp_assume_no_thread_state))
- res.getLangOpts().OpenMPNoThreadState = 1;
-
- if (args.hasArg(clang::options::OPT_fopenmp_assume_no_nested_parallelism))
- res.getLangOpts().OpenMPNoNestedParallelism = 1;
-
- if ((args.hasArg(clang::options::OPT_fopenmp_target_debug) ||
- args.hasArg(clang::options::OPT_fopenmp_target_debug_EQ))) {
- res.getLangOpts().OpenMPTargetDebug =
- getLastArgIntValue(args, clang::options::OPT_fopenmp_target_debug_EQ,
- res.getLangOpts().OpenMPTargetDebug, diags);
-
- if (!res.getLangOpts().OpenMPTargetDebug &&
- args.hasArg(clang::options::OPT_fopenmp_target_debug))
- res.getLangOpts().OpenMPTargetDebug = 1;
- }
- if (args.hasArg(clang::options::OPT_no_offloadlib))
- res.getLangOpts().NoGPULib = 1;
- }
- if (llvm::Triple(res.getTargetOpts().triple).isGPU()) {
- if (!res.getLangOpts().OpenMPIsTargetDevice) {
- const unsigned diagID = diags.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "OpenMP GPU is only prepared to deal with device code.");
- diags.Report(diagID);
- }
- res.getLangOpts().OpenMPIsGPU = 1;
- } else {
- res.getLangOpts().OpenMPIsGPU = 0;
- }
-
- // Get the OpenMP target triples if any.
- if (auto *arg = args.getLastArg(clang::options::OPT_offload_targets_EQ)) {
- enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
- auto getArchPtrSize = [](const llvm::Triple &triple) {
- if (triple.isArch16Bit())
- return Arch16Bit;
- if (triple.isArch32Bit())
- return Arch32Bit;
- assert(triple.isArch64Bit() && "Expected 64-bit architecture");
- return Arch64Bit;
- };
-
- for (unsigned i = 0; i < arg->getNumValues(); ++i) {
- llvm::Triple tt(arg->getValue(i));
-
- if (tt.getArch() == llvm::Triple::UnknownArch ||
- !(tt.getArch() == llvm::Triple::aarch64 || tt.isPPC() ||
- tt.getArch() == llvm::Triple::systemz ||
- tt.getArch() == llvm::Triple::x86 ||
- tt.getArch() == llvm::Triple::x86_64 || tt.isGPU()))
- diags.Report(clang::diag::err_drv_invalid_omp_target)
- << arg->getValue(i);
- else if (getArchPtrSize(t) != getArchPtrSize(tt))
- diags.Report(clang::diag::err_drv_incompatible_omp_arch)
- << arg->getValue(i) << t.str();
- else
- res.getLangOpts().OMPTargetTriples.push_back(tt);
- }
- }
- return !diags.hasUncompilableErrorOccurred();
-}
-
-/// Parses signed integer overflow options and populates the
-/// CompilerInvocation accordingly.
-/// Returns false if new errors are generated.
-///
-/// \param [out] invoc Stores the processed arguments
-/// \param [in] args The compiler invocation arguments to parse
-/// \param [out] diags DiagnosticsEngine to report erros with
-static bool parseIntegerOverflowArgs(CompilerInvocation &invoc,
- llvm::opt::ArgList &args,
- clang::DiagnosticsEngine &diags) {
- Fortran::common::LangOptions &opts = invoc.getLangOpts();
-
- if (args.getLastArg(clang::options::OPT_fwrapv))
- opts.setSignedOverflowBehavior(Fortran::common::LangOptions::SOB_Defined);
-
- return true;
-}
-
-/// Set the IEEE Floating point rounding modes, underflow mode and halting mode.
-///
-/// Initial halting mode:
-/// -ffpe-trap= sets the initial floating-point exception halting mode for the
-/// main program. Only the last -ffpe-trap= on the command line is effective.
-/// The value is a comma-separated set of exception mnemonics: "invalid",
-/// "zero", "overflow", "underflow", and "inexact" correspond to the Fortran
-/// 2023 IEEE_FLAG_TYPE values (F2023 17.2), and "denormal" is a non-standard,
-/// gfortran-compatible extension. "none", as well as an empty list, requests no
-/// halting and resets any earlier request.
-///
-/// TODO:
-/// Rounding modes
-/// Underflow mode
-///
-/// The value and the target-support warnings are validated in the driver (see
-/// addIEEEFPModesOptions() in clang/lib/Driver/ToolChains/Flang.cpp);
-/// here we only translate the already-validated list, so an unrecognized
-/// mnemonic maps to 0 and is ignored rather than re-diagnosed.
-static void setIEEEFPModesArgs(Fortran::common::LangOptions &opts,
- llvm::opt::ArgList &args) {
- const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_ffpe_trap_EQ);
- if (!a)
- return;
-
- using LangOptions = Fortran::common::LangOptions;
- unsigned traps = 0;
- llvm::SmallVector<llvm::StringRef> trapList;
- llvm::StringRef(a->getValue())
- .split(trapList, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
- for (llvm::StringRef trap : trapList) {
- if (trap == "none") {
- // Reset to no halting; a later mnemonic can re-enable.
- traps = 0;
- continue;
- }
- traps |= llvm::StringSwitch<unsigned>(trap)
- .Case("invalid", LangOptions::FPE_Invalid)
- .Case("denormal", LangOptions::FPE_Denormal)
- .Case("zero", LangOptions::FPE_DivByZero)
- .Case("overflow", LangOptions::FPE_Overflow)
- .Case("underflow", LangOptions::FPE_Underflow)
- .Case("inexact", LangOptions::FPE_Inexact)
- .Default(0);
- }
- opts.FPExceptionTraps = traps;
+ return diags.getNumErrors() == numErrorsBefore;
}
/// Parses all floating point related arguments and populates the
@@ -1541,17 +846,17 @@ static void setIEEEFPModesArgs(Fortran::common::LangOptions &opts,
static bool parseFloatingPointArgs(CompilerInvocation &invoc,
llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
- Fortran::common::LangOptions &opts = invoc.getLangOpts();
+ LangOptions &opts = invoc.getLangOpts();
if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_ffp_contract)) {
+ args.getLastArg(clang::driver::options::OPT_ffp_contract)) {
const llvm::StringRef val = a->getValue();
- enum Fortran::common::LangOptions::FPModeKind fpContractMode;
+ enum LangOptions::FPModeKind fpContractMode;
if (val == "off")
- fpContractMode = Fortran::common::LangOptions::FPM_Off;
+ fpContractMode = LangOptions::FPM_Off;
else if (val == "fast")
- fpContractMode = Fortran::common::LangOptions::FPM_Fast;
+ fpContractMode = LangOptions::FPM_Fast;
else {
diags.Report(clang::diag::err_drv_unsupported_option_argument)
<< a->getSpelling() << val;
@@ -1561,200 +866,48 @@ static bool parseFloatingPointArgs(CompilerInvocation &invoc,
opts.setFPContractMode(fpContractMode);
}
- if (args.getLastArg(clang::options::OPT_menable_no_infs)) {
+ if (args.getLastArg(clang::driver::options::OPT_menable_no_infinities)) {
opts.NoHonorInfs = true;
}
- if (args.getLastArg(clang::options::OPT_menable_no_nans)) {
+ if (args.getLastArg(clang::driver::options::OPT_menable_no_nans)) {
opts.NoHonorNaNs = true;
}
- if (args.getLastArg(clang::options::OPT_fapprox_func)) {
+ if (args.getLastArg(clang::driver::options::OPT_fapprox_func)) {
opts.ApproxFunc = true;
}
- if (args.getLastArg(clang::options::OPT_fno_signed_zeros)) {
+ if (args.getLastArg(clang::driver::options::OPT_fno_signed_zeros)) {
opts.NoSignedZeros = true;
}
- if (args.getLastArg(clang::options::OPT_mreassociate)) {
+ if (args.getLastArg(clang::driver::options::OPT_mreassociate)) {
opts.AssociativeMath = true;
}
- if (args.getLastArg(clang::options::OPT_freciprocal_math)) {
+ if (args.getLastArg(clang::driver::options::OPT_freciprocal_math)) {
opts.ReciprocalMath = true;
}
- if (args.getLastArg(clang::options::OPT_ffast_math)) {
+ if (args.getLastArg(clang::driver::options::OPT_ffast_math)) {
opts.NoHonorInfs = true;
opts.NoHonorNaNs = true;
opts.AssociativeMath = true;
opts.ReciprocalMath = true;
opts.ApproxFunc = true;
opts.NoSignedZeros = true;
- opts.FastRealMod = true;
- opts.setFPContractMode(Fortran::common::LangOptions::FPM_Fast);
- }
-
- if (llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_ffast_real_mod,
- clang::options::OPT_fno_fast_real_mod)) {
- if (arg->getOption().matches(clang::options::OPT_ffast_real_mod))
- opts.FastRealMod = true;
- if (arg->getOption().matches(clang::options::OPT_fno_fast_real_mod))
- opts.FastRealMod = false;
- }
-
- if (args.getLastArg(clang::options::OPT_fcheck_integer_mod_zero_divisor))
- opts.CheckIntegerModZeroDivisor = true;
-
- // Set the initial IEEE floating point modes
- setIEEEFPModesArgs(opts, args);
-
- return true;
-}
-
-/// Parses vscale range options and populates the CompilerInvocation
-/// accordingly.
-/// Returns false if new errors are generated.
-///
-/// \param [out] invoc Stores the processed arguments
-/// \param [in] args The compiler invocation arguments to parse
-/// \param [out] diags DiagnosticsEngine to report erros with
-static bool parseVScaleArgs(CompilerInvocation &invoc, llvm::opt::ArgList &args,
- clang::DiagnosticsEngine &diags) {
- const auto *vscaleMin = args.getLastArg(clang::options::OPT_mvscale_min_EQ);
- const auto *vscaleMax = args.getLastArg(clang::options::OPT_mvscale_max_EQ);
-
- if (!vscaleMin && !vscaleMax)
- return true;
-
- llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple);
- if (!triple.isAArch64() && !triple.isRISCV()) {
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "`-mvscale-max` and `-mvscale-min` are not "
- "supported for this architecture: %0");
- diags.Report(diagID) << triple.getArchName();
- return false;
- }
-
- Fortran::common::LangOptions &opts = invoc.getLangOpts();
- if (vscaleMin) {
- llvm::StringRef argValue = llvm::StringRef(vscaleMin->getValue());
- unsigned vscaleMinVal;
- if (argValue.getAsInteger(/*Radix=*/10, vscaleMinVal)) {
- diags.Report(clang::diag::err_drv_unsupported_option_argument)
- << vscaleMax->getSpelling() << argValue;
- return false;
- }
- opts.VScaleMin = vscaleMinVal;
- }
-
- if (vscaleMax) {
- llvm::StringRef argValue = llvm::StringRef(vscaleMax->getValue());
- unsigned vscaleMaxVal;
- if (argValue.getAsInteger(/*Radix=w*/ 10, vscaleMaxVal)) {
- diags.Report(clang::diag::err_drv_unsupported_option_argument)
- << vscaleMax->getSpelling() << argValue;
- return false;
- }
- opts.VScaleMax = vscaleMaxVal;
- }
- return true;
-}
-
-static bool parseLinkerOptionsArgs(CompilerInvocation &invoc,
- llvm::opt::ArgList &args,
- clang::DiagnosticsEngine &diags) {
- llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple);
- CodeGenOptions &opts = invoc.getCodeGenOpts();
-
- // TODO: support --dependent-lib on other platforms when MLIR supports
- // !llvm.dependent.lib
- if (args.hasArg(clang::options::OPT_dependent_lib) && !triple.isOSWindows()) {
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "--dependent-lib is only supported on Windows");
- diags.Report(diagID);
- return false;
- }
-
- opts.DependentLibs = args.getAllArgValues(clang::options::OPT_dependent_lib);
-
- // -flto=full/thin option.
- if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_flto_EQ)) {
- llvm::StringRef s = a->getValue();
- assert((s == "full" || s == "thin") && "Unknown LTO mode.");
- if (s == "full")
- opts.PrepareForFullLTO = true;
- else
- opts.PrepareForThinLTO = true;
+ opts.setFPContractMode(LangOptions::FPM_Fast);
}
- // -fsplit-lto-unit option
- if (args.hasArg(clang::options::OPT_fsplit_lto_unit))
- opts.EnableSplitLTOUnit = true;
-
- // -ffat-lto-objects
- if (const llvm::opt::Arg *arg =
- args.getLastArg(clang::options::OPT_ffat_lto_objects,
- clang::options::OPT_fno_fat_lto_objects)) {
- opts.PrepareForFatLTO =
- arg->getOption().matches(clang::options::OPT_ffat_lto_objects);
- if (opts.PrepareForFatLTO) {
- assert((opts.PrepareForFullLTO || opts.PrepareForThinLTO) &&
- "Unknown LTO mode");
-
- if (!triple.isOSBinFormatELF())
- diags.Report(clang::diag::err_drv_unsupported_opt_for_target)
- << arg->getAsString(args) << triple.getTriple();
- }
- }
return true;
}
-static bool parseLangOptionsArgs(CompilerInvocation &invoc,
- llvm::opt::ArgList &args,
- clang::DiagnosticsEngine &diags) {
- bool success = true;
-
- success &= parseIntegerOverflowArgs(invoc, args, diags);
- success &= parseFloatingPointArgs(invoc, args, diags);
- success &= parseVScaleArgs(invoc, args, diags);
-
- return success;
-}
-
-// Copied from clang/lib/Frontend/CompilerInvocation.cpp.
-static void addDiagnosticArgs(llvm::opt::ArgList &args,
- llvm::opt::OptSpecifier group,
- llvm::opt::OptSpecifier groupWithValue,
- std::vector<std::string> &diagnostics) {
- for (auto *a : args.filtered(group)) {
- if (a->getOption().getKind() == llvm::opt::Option::FlagClass) {
- // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
- // its name (minus the "W" or "R" at the beginning) to the diagnostics.
- diagnostics.push_back(
- std::string(a->getOption().getName().drop_front(1)));
- } else if (a->getOption().matches(groupWithValue)) {
- // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
- // group. Add only the group name to the diagnostics.
- diagnostics.push_back(
- std::string(a->getOption().getName().drop_front(1).rtrim("=-")));
- } else {
- // Otherwise, add its value (for OPT_W_Joined and similar).
- diagnostics.push_back(a->getValue());
- }
- }
-}
-
bool CompilerInvocation::createFromArgs(
- CompilerInvocation &invoc, llvm::ArrayRef<const char *> commandLineArgs,
+ CompilerInvocation &res, llvm::ArrayRef<const char *> commandLineArgs,
clang::DiagnosticsEngine &diags, const char *argv0) {
bool success = true;
- clang::DiagnosticOptions &diagOpts = diags.getDiagnosticOptions();
// Set the default triple for this CompilerInvocation. This might be
// overridden by users with `-triple` (see the call to `ParseTargetArgs`
@@ -1762,15 +915,15 @@ bool CompilerInvocation::createFromArgs(
// NOTE: Like in Clang, it would be nice to use option marshalling
// for this so that the entire logic for setting-up the triple is in one
// place.
- invoc.getTargetOpts().triple =
+ res.getTargetOpts().triple =
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
// Parse the arguments
- const llvm::opt::OptTable &opts = clang::getDriverOptTable();
- llvm::opt::Visibility visibilityMask(clang::options::FC1Option);
+ const llvm::opt::OptTable &opts = clang::driver::getDriverOptTable();
+ const unsigned includedFlagsBitmask = clang::driver::options::FC1Option;
unsigned missingArgIndex, missingArgCount;
llvm::opt::InputArgList args = opts.ParseArgs(
- commandLineArgs, missingArgIndex, missingArgCount, visibilityMask);
+ commandLineArgs, missingArgIndex, missingArgCount, includedFlagsBitmask);
// Check for missing argument error.
if (missingArgCount) {
@@ -1780,10 +933,10 @@ bool CompilerInvocation::createFromArgs(
}
// Issue errors on unknown arguments
- for (const auto *a : args.filtered(clang::options::OPT_UNKNOWN)) {
+ for (const auto *a : args.filtered(clang::driver::options::OPT_UNKNOWN)) {
auto argString = a->getAsString(args);
std::string nearest;
- if (opts.findNearest(argString, nearest, visibilityMask) > 1)
+ if (opts.findNearest(argString, nearest, includedFlagsBitmask) > 1)
diags.Report(clang::diag::err_drv_unknown_argument) << argString;
else
diags.Report(clang::diag::err_drv_unknown_argument_with_suggestion)
@@ -1791,142 +944,43 @@ bool CompilerInvocation::createFromArgs(
success = false;
}
- // Handle -Wno-<warning> flags.
- addDiagnosticArgs(args, clang::options::OPT_W_Group,
- clang::options::OPT_W_value_Group, diagOpts.Warnings);
- auto vfs = llvm::vfs::getRealFileSystem();
- clang::ProcessWarningOptions(diags, diagOpts, *vfs, /*ReportDiags=*/false);
-
- // -fno-ppc-native-vector-element-order
- if (args.hasArg(clang::options::OPT_fno_ppc_native_vec_elem_order)) {
- invoc.loweringOpts.setNoPPCNativeVecElemOrder(true);
+ // -flang-experimental-hlfir
+ if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir) ||
+ args.hasArg(clang::driver::options::OPT_emit_hlfir)) {
+ res.loweringOpts.setLowerToHighLevelFIR(true);
}
- // -f[no-]init-global-zero
- if (args.hasFlag(clang::options::OPT_finit_global_zero,
- clang::options::OPT_fno_init_global_zero,
- /*default=*/true))
- invoc.loweringOpts.setInitGlobalZero(true);
- else
- invoc.loweringOpts.setInitGlobalZero(false);
-
- // -finit-local=<zero|0x<hex>> and -finit-local-zero
- // (-finit-local-zero is an alias that the driver already expands to
- // -finit-local=zero, so we only need to handle OPT_finit_local_EQ here.)
- if (const llvm::opt::Arg *a =
- args.getLastArg(clang::options::OPT_finit_local_EQ)) {
- llvm::StringRef val = a->getValue();
- if (val == "zero") {
- invoc.loweringOpts.setInitLocalMode(Fortran::lower::InitLocalKind::Zero);
- } else if (val.starts_with("0x") || val.starts_with("0X")) {
- unsigned long long hexVal = 0;
- if (val.drop_front(2).getAsInteger(16, hexVal) || hexVal > 0xFF) {
- diags.Report(clang::diag::err_drv_invalid_value)
- << a->getAsString(args) << val;
- } else {
- invoc.loweringOpts.setInitLocalMode(Fortran::lower::InitLocalKind::Hex);
- invoc.loweringOpts.setInitLocalPattern(static_cast<uint8_t>(hexVal));
- }
- } else {
- diags.Report(clang::diag::err_drv_invalid_value)
- << a->getAsString(args) << val;
- }
+ if (args.hasArg(clang::driver::options::OPT_flang_experimental_polymorphism)) {
+ res.loweringOpts.setPolymorphicTypeImpl(true);
}
- // Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
- // -Rpass-analysis. This will be used later when processing and outputting the
- // remarks generated by LLVM in ExecuteCompilerInvocation.cpp.
- for (auto *a : args.filtered(clang::options::OPT_R_Group)) {
- if (a->getOption().matches(clang::options::OPT_R_value_Group))
- // This is -Rfoo=, where foo is the name of the diagnostic
- // group. Add only the remark option name to the diagnostics. e.g. for
- // -Rpass= we will add the string "pass".
- invoc.getDiagnosticOpts().Remarks.push_back(
- std::string(a->getOption().getName().drop_front(1).rtrim("=-")));
- else
- // If no regex was provided, add the provided value, e.g. for -Rpass add
- // the string "pass".
- invoc.getDiagnosticOpts().Remarks.push_back(a->getValue());
- }
-
- // -frealloc-lhs is the default.
- if (!args.hasFlag(clang::options::OPT_frealloc_lhs,
- clang::options::OPT_fno_realloc_lhs, true)) {
- invoc.loweringOpts.setReallocateLHS(false);
- invoc.getLangOpts().NoReallocateLHS = true;
- }
-
- invoc.loweringOpts.setRepackArrays(args.hasFlag(
- clang::options::OPT_frepack_arrays, clang::options::OPT_fno_repack_arrays,
- /*default=*/false));
- invoc.loweringOpts.setStackRepackArrays(
- args.hasFlag(clang::options::OPT_fstack_repack_arrays,
- clang::options::OPT_fno_stack_repack_arrays,
- /*default=*/false));
- if (auto *arg =
- args.getLastArg(clang::options::OPT_frepack_arrays_contiguity_EQ))
- invoc.loweringOpts.setRepackArraysWhole(arg->getValue() ==
- llvm::StringRef{"whole"});
-
- // -f[no-]openacc-combined-loop-firstprivate
- invoc.loweringOpts.setOpenACCCombinedLoopFirstprivate(
- args.hasFlag(clang::options::OPT_fopenacc_combined_loop_firstprivate,
- clang::options::OPT_fno_openacc_combined_loop_firstprivate,
- /*default=*/true));
-
- // -f[no-]openacc-acc-kernels-do-concurrent-independent
- invoc.loweringOpts.setOpenACCKernelsDoConcurrentIndependent(args.hasFlag(
- clang::options::OPT_fopenacc_acc_kernels_do_concurrent_independent,
- clang::options::OPT_fno_openacc_acc_kernels_do_concurrent_independent,
- /*default=*/true));
-
- if (auto *arg = args.getLastArg(clang::options::OPT_ffp_maxmin_behavior_EQ)) {
- auto value = Fortran::common::parseFPMaxminBehavior(arg->getValue());
- invoc.getCodeGenOpts().setFPMaxminBehavior(value);
- invoc.loweringOpts.setFPMaxminBehavior(value);
- }
-
- success &= parseFrontendArgs(invoc.getFrontendOpts(), args, diags);
- parseTargetArgs(invoc.getTargetOpts(), args);
- parsePreprocessorArgs(invoc.getPreprocessorOpts(), args);
- parseCodeGenArgs(invoc.getCodeGenOpts(), args, diags);
- success &= parseDoConcurrentMapping(invoc.getCodeGenOpts(), args, diags);
- success &= parseDebugArgs(invoc.getCodeGenOpts(), args, diags);
-
- // Enable USE statement preservation for debug info if debug level is above
- // LineTablesOnly.
- using DebugInfoKind = llvm::codegenoptions::DebugInfoKind;
- DebugInfoKind debugLevel = invoc.getCodeGenOpts().getDebugInfo();
- invoc.loweringOpts.setPreserveUseDebugInfo(
- debugLevel > DebugInfoKind::DebugLineTablesOnly);
-
- success &= parseVectorLibArg(invoc.getCodeGenOpts(), args, diags);
- success &= parseSemaArgs(invoc, args, diags);
- success &= parseDialectArgs(invoc, args, diags);
- success &= parseOpenMPArgs(invoc, args, diags);
- success &= parseDiagArgs(invoc, args, diags);
+ success &= parseFrontendArgs(res.getFrontendOpts(), args, diags);
+ parseTargetArgs(res.getTargetOpts(), args);
+ parsePreprocessorArgs(res.getPreprocessorOpts(), args);
+ parseCodeGenArgs(res.getCodeGenOpts(), args, diags);
+ success &= parseDebugArgs(res.getCodeGenOpts(), args, diags);
+ success &= parseSemaArgs(res, args, diags);
+ success &= parseDialectArgs(res, args, diags);
+ success &= parseDiagArgs(res, args, diags);
// Collect LLVM (-mllvm) and MLIR (-mmlir) options.
// NOTE: Try to avoid adding any options directly to `llvmArgs` or
// `mlirArgs`. Instead, you can use
// * `-mllvm <your-llvm-option>`, or
// * `-mmlir <your-mlir-option>`.
- invoc.frontendOpts.llvmArgs = args.getAllArgValues(clang::options::OPT_mllvm);
- invoc.frontendOpts.mlirArgs = args.getAllArgValues(clang::options::OPT_mmlir);
-
- if (args.hasArg(clang::options::OPT_foffload_device))
- invoc.getLangOpts().OffloadDevice = 1;
-
- success &= parseLangOptionsArgs(invoc, args, diags);
+ res.frontendOpts.llvmArgs =
+ args.getAllArgValues(clang::driver::options::OPT_mllvm);
+ res.frontendOpts.mlirArgs =
+ args.getAllArgValues(clang::driver::options::OPT_mmlir);
- success &= parseLinkerOptionsArgs(invoc, args, diags);
+ success &= parseFloatingPointArgs(res, args, diags);
// Set the string to be used as the return value of the COMPILER_OPTIONS
// intrinsic of iso_fortran_env. This is either passed in from the parent
// compiler driver invocation with an environment variable, or failing that
// set to the command line arguments of the frontend driver invocation.
- invoc.allCompilerInvocOpts = std::string();
- llvm::raw_string_ostream os(invoc.allCompilerInvocOpts);
+ res.allCompilerInvocOpts = std::string();
+ llvm::raw_string_ostream os(res.allCompilerInvocOpts);
char *compilerOptsEnv = std::getenv("FLANG_COMPILER_OPTIONS_STRING");
if (compilerOptsEnv != nullptr) {
os << compilerOptsEnv;
@@ -1938,12 +992,6 @@ bool CompilerInvocation::createFromArgs(
}
}
- // Process the timing-related options.
- if (args.hasArg(clang::options::OPT_ftime_report))
- invoc.enableTimers = true;
-
- invoc.setArgv0(argv0);
-
return success;
}
@@ -1984,6 +1032,10 @@ void CompilerInvocation::setDefaultFortranOpts() {
std::vector<std::string> searchDirectories{"."s};
fortranOptions.searchDirectories = searchDirectories;
+ // Add the location of omp_lib.h to the search directories. Currently this is
+ // identical to the modules' directory.
+ fortranOptions.searchDirectories.emplace_back(getOpenMPHeadersDir());
+
fortranOptions.isFixedForm = false;
}
@@ -2002,20 +1054,6 @@ void CompilerInvocation::setDefaultPredefinitions() {
fortranOptions.predefinitions.emplace_back("__flang_patchlevel__",
FLANG_VERSION_PATCHLEVEL_STRING);
- // Add predefinitions based on the relocation model
- if (unsigned PICLevel = getCodeGenOpts().PICLevel) {
- fortranOptions.predefinitions.emplace_back("__PIC__",
- std::to_string(PICLevel));
- fortranOptions.predefinitions.emplace_back("__pic__",
- std::to_string(PICLevel));
- if (getCodeGenOpts().IsPIE) {
- fortranOptions.predefinitions.emplace_back("__PIE__",
- std::to_string(PICLevel));
- fortranOptions.predefinitions.emplace_back("__pie__",
- std::to_string(PICLevel));
- }
- }
-
// Add predefinitions based on extensions enabled
if (frontendOptions.features.IsEnabled(
Fortran::common::LanguageFeature::OpenACC)) {
@@ -2023,48 +1061,13 @@ void CompilerInvocation::setDefaultPredefinitions() {
}
if (frontendOptions.features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP)) {
- Fortran::common::setOpenMPMacro(
- static_cast<unsigned>(getLangOpts().getOpenMPVersion()),
- fortranOptions.predefinitions);
- }
-
- if (frontendOptions.features.IsEnabled(
- Fortran::common::LanguageFeature::CUDA)) {
- fortranOptions.predefinitions.emplace_back("_CUDA", "1");
+ Fortran::common::setOpenMPMacro(getLangOpts().OpenMPVersion,
+ fortranOptions.predefinitions);
}
-
llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
- if (targetTriple.isOSLinux()) {
- fortranOptions.predefinitions.emplace_back("__linux__", "1");
- } else if (targetTriple.isOSAIX()) {
- fortranOptions.predefinitions.emplace_back("_AIX", "1");
- }
-
- switch (targetTriple.getArch()) {
- default:
- break;
- case llvm::Triple::ArchType::x86_64:
+ if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) {
fortranOptions.predefinitions.emplace_back("__x86_64__", "1");
fortranOptions.predefinitions.emplace_back("__x86_64", "1");
- break;
- case llvm::Triple::ArchType::ppc:
- case llvm::Triple::ArchType::ppc64:
- case llvm::Triple::ArchType::ppcle:
- case llvm::Triple::ArchType::ppc64le:
- // '__powerpc__' is a generic macro for any PowerPC.
- fortranOptions.predefinitions.emplace_back("__powerpc__", "1");
- if (targetTriple.isOSAIX() && targetTriple.isArch64Bit()) {
- fortranOptions.predefinitions.emplace_back("__64BIT__", "1");
- }
- break;
- case llvm::Triple::ArchType::aarch64:
- fortranOptions.predefinitions.emplace_back("__aarch64__", "1");
- fortranOptions.predefinitions.emplace_back("__aarch64", "1");
- break;
- case llvm::Triple::ArchType::systemz:
- fortranOptions.predefinitions.emplace_back("__s390x__", "1");
- fortranOptions.predefinitions.emplace_back("__s390x", "1");
- break;
}
}
@@ -2080,10 +1083,6 @@ void CompilerInvocation::setFortranOpts() {
}
fortranOptions.fixedFormColumns = frontendOptions.fixedFormColumns;
- // -E
- fortranOptions.prescanAndReformat =
- frontendOptions.programAction == PrintPreprocessedInput;
-
fortranOptions.features = frontendOptions.features;
fortranOptions.encoding = frontendOptions.encoding;
@@ -2099,15 +1098,8 @@ void CompilerInvocation::setFortranOpts() {
preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
preprocessorOptions.searchDirectoriesFromIntrModPath.end());
- // Add the ordered list of -fintrinsic-modules-path
- fortranOptions.intrinsicModuleDirectories.insert(
- fortranOptions.intrinsicModuleDirectories.end(),
- preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
- preprocessorOptions.searchDirectoriesFromIntrModPath.end());
-
// Add the default intrinsic module directory
- fortranOptions.intrinsicModuleDirectories.emplace_back(
- getIntrinsicDir(getArgv0()));
+ fortranOptions.intrinsicModuleDirectories.emplace_back(getIntrinsicDir());
// Add the directory supplied through -J/-module-dir to the list of search
// directories
@@ -2123,39 +1115,40 @@ void CompilerInvocation::setFortranOpts() {
if (frontendOptions.needProvenanceRangeToCharBlockMappings)
fortranOptions.needProvenanceRangeToCharBlockMappings = true;
- fortranOptions.features = frontendOptions.features;
+ if (getEnableConformanceChecks())
+ fortranOptions.features.WarnOnAllNonstandard();
+
+ if (getEnableUsageChecks())
+ fortranOptions.features.WarnOnAllUsage();
}
-std::unique_ptr<Fortran::semantics::SemanticsContext>
-CompilerInvocation::getSemanticsCtx(
- Fortran::parser::AllCookedSources &allCookedSources,
- const llvm::TargetMachine &targetMachine) {
+void CompilerInvocation::setSemanticsOpts(
+ Fortran::parser::AllCookedSources &allCookedSources) {
auto &fortranOptions = getFortranOpts();
- auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
- getDefaultKinds(), fortranOptions.features, getLangOpts(),
- allCookedSources, getCodeGenOpts().getFPMaxminBehavior());
+ semanticsContext = std::make_unique<semantics::SemanticsContext>(
+ getDefaultKinds(), fortranOptions.features, allCookedSources);
semanticsContext->set_moduleDirectory(getModuleDir())
.set_searchDirectories(fortranOptions.searchDirectories)
.set_intrinsicModuleDirectories(fortranOptions.intrinsicModuleDirectories)
- .set_maxErrors(getMaxErrors())
.set_warningsAreErrors(getWarnAsErr())
- .set_moduleFileSuffix(getModuleFileSuffix())
- .set_underscoring(getCodeGenOpts().Underscoring)
- .set_openAccDefaultNoneScalarsStrictDisableOption(
- clang::getDriverOptTable()
- .getOptionPrefixedName(
- clang::options::OPT_fno_openacc_default_none_scalars_strict)
- .str())
- .set_targetTriple(targetMachine.getTargetTriple().str())
- .set_targetFeatures(targetMachine.getTargetFeatureString().str());
-
- std::string compilerVersion = Fortran::common::getFlangFullVersion();
- Fortran::tools::setUpTargetCharacteristics(
- semanticsContext->targetCharacteristics(), targetMachine, getTargetOpts(),
- compilerVersion, allCompilerInvocOpts);
- return semanticsContext;
+ .set_moduleFileSuffix(getModuleFileSuffix());
+
+ llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
+ // FIXME: Handle real(3) ?
+ if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
+ semanticsContext->targetCharacteristics().DisableType(
+ Fortran::common::TypeCategory::Real, /*kind=*/10);
+ }
+
+ std::string version = Fortran::common::getFlangFullVersion();
+ semanticsContext->targetCharacteristics()
+ .set_compilerOptionsString(allCompilerInvocOpts)
+ .set_compilerVersionString(version);
+
+ if (targetTriple.isPPC())
+ semanticsContext->targetCharacteristics().set_isPPC(true);
}
/// Set \p loweringOptions controlling lowering behavior based
@@ -2165,33 +1158,19 @@ void CompilerInvocation::setLoweringOptions() {
// Lower TRANSPOSE as a runtime call under -O0.
loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
- loweringOpts.setUnderscoring(codegenOpts.Underscoring);
- loweringOpts.setSkipExternalRttiDefinition(skipExternalRttiDefinition);
-
- const Fortran::common::LangOptions &langOptions = getLangOpts();
- loweringOpts.setIntegerWrapAround(langOptions.getSignedOverflowBehavior() ==
- Fortran::common::LangOptions::SOB_Defined);
- loweringOpts.setProtectParens(codegenOpts.ProtectParens);
- loweringOpts.setSplitSumExpressionTree(codegenOpts.SplitSumExpressionTree);
+
+ const LangOptions &langOptions = getLangOpts();
Fortran::common::MathOptionsBase &mathOpts = loweringOpts.getMathOptions();
// TODO: when LangOptions are finalized, we can represent
// the math related options using Fortran::commmon::MathOptionsBase,
// so that we can just copy it into LoweringOptions.
mathOpts
.setFPContractEnabled(langOptions.getFPContractMode() ==
- Fortran::common::LangOptions::FPM_Fast)
+ LangOptions::FPM_Fast)
.setNoHonorInfs(langOptions.NoHonorInfs)
.setNoHonorNaNs(langOptions.NoHonorNaNs)
.setApproxFunc(langOptions.ApproxFunc)
.setNoSignedZeros(langOptions.NoSignedZeros)
.setAssociativeMath(langOptions.AssociativeMath)
.setReciprocalMath(langOptions.ReciprocalMath);
-
- if (codegenOpts.getComplexRange() ==
- CodeGenOptions::ComplexRangeKind::CX_Improved ||
- codegenOpts.getComplexRange() ==
- CodeGenOptions::ComplexRangeKind::CX_Basic)
- loweringOpts.setComplexDivisionToRuntime(false);
-
- loweringOpts.setFPExceptionTraps(langOptions.FPExceptionTraps);
}
More information about the flang-commits
mailing list