[clang] [flang] [llvm] [flang][flang-rt] Add -ffpe-trap= to set the initial FP exception halting mode (PR #208828)

Tarun Prabhu via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 27 09:55:25 PDT 2026


================
@@ -1485,6 +1485,46 @@ static bool parseFloatingPointArgs(CompilerInvocation &invoc,
       opts.FastRealMod = false;
   }
 
+  // Only the last -ffpe-trap= on the command line is effective. The list is a
+  // comma-separated set of exception mnemonics. The mnemonics "invalid",
+  // "zero", "overflow", "underflow", and "inexact" correspond to the Fortran
+  // 2023 IEEE_FLAG_TYPE values IEEE_INVALID, IEEE_DIVIDE_BY_ZERO,
+  // IEEE_OVERFLOW, IEEE_UNDERFLOW, and IEEE_INEXACT (F2023 17.2). The mnemonic
+  // "denormal" is a non-standard, gfortran-compatible extension (subnormal is
+  // an IEEE_FEATURES feature, not an exception flag). The mnemonic "none", as
+  // well as an empty list, requests no halting, allowing a later -ffpe-trap= to
+  // override an earlier one.
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::options::OPT_ffpe_trap_EQ)) {
+    using LangOptions = Fortran::common::LangOptions;
+    llvm::StringRef val = a->getValue();
+    unsigned traps = 0;
+    llvm::SmallVector<llvm::StringRef> trapList;
+    val.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;
+      }
+      unsigned bit = 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);
+      if (bit == 0) {
+        diags.Report(clang::diag::err_drv_unsupported_option_argument)
----------------
tarunprabhu wrote:

flang -fc1 may be a valid invocation, but it is NOT intended for end users. By invoking `-fc1` directly, the user is implicitly accepting responsibility for all arguments that are passed, and and accept that passing invalid options may result in a catastrophic failure. 

Option values are sometimes validated in multiple locations. For instance, `-mcmodel` is validated both in the driver, and by the underlying compiler. However, the actual checks in the two cases are different. In general, if validation may be affected by the presence of other options - some of which may be added by the driver, then performing that validation in `-fc1` is ok. For example, `-fopenmp-target-fast` implies `-O3` - so `-O3` will get passed to `-fc1`, though it may not be present in the driver. In this case, the driver cannot reasonably validate some other option `-foo` was provided that is incompatible with `-O3`. This check can only be performed in `-fc1`.

In short, if an option can be validated in the driver, it should be validated there, rather than deferring it to `-fc1`. Is there any reason not to validate the exception values in the driver?

https://github.com/llvm/llvm-project/pull/208828


More information about the cfe-commits mailing list