Author: Vineet Kumar
Date: 2026-08-05T07:26:50-05:00
New Revision: 9063da54488c147b5fd9c51128dcb8682632dd1c

URL: 
https://github.com/llvm/llvm-project/commit/9063da54488c147b5fd9c51128dcb8682632dd1c
DIFF: 
https://github.com/llvm/llvm-project/commit/9063da54488c147b5fd9c51128dcb8682632dd1c.diff

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

Implement the gfortran-style `-ffpe-trap=<list>` option, which sets the
initial floating-point exception halting mode for the main program unit.
The Fortran 2023 standard (17.6) permits the initial halting mode to be
processor defined, so honoring this at program start is conforming.

`<list>` is a comma-separated set of exception mnemonics: `invalid`,
`zero`, `overflow`, `underflow`, and `inexact`, corresponding to the
IEEE_FLAG_TYPE values IEEE_INVALID, IEEE_DIVIDE_BY_ZERO, IEEE_OVERFLOW,
IEEE_UNDERFLOW, and IEEE_INEXACT. As a non-standard, gfortran-compatible
extension, `denormal` halts on the x86 denormal-operand exception. An
empty list or the value `none` disables halting, and the last
`-ffpe-trap=` on the command line wins (allowing an earlier request to
be overridden).

Changes by component:
- clang/Driver: give `-ffpe-trap=` FlangOption/FC1Option visibility and
a one-line HelpText plus a detailed DocBrief (moved into f_Group);
forward the flag to -fc1. Emit a target-based warning when halting
control is unavailable (non-x86 and non-Linux targets), and a
denormal-specific warning on non-x86 targets. The check is intentionally
conservative and only ever under-warns; the runtime remains
authoritative.
- flang/Frontend: parse the list into a LangOptions bitmask
(FPExceptionTrapKind), error on unknown mnemonics, and propagate the
mask to the lowering options.
- flang/Lower: genMain() injects a call to _FortranAEnableFPETraps into
the main program unit only (after ProgramStart, before _QQmain), so the
mode persists across procedures as required by F2023 17.6.
- flang-rt: add EnableFPETraps(), which enables halting only for the
exceptions whose halting control is supported on the target
(IEEE_SUPPORT_HALTING, F2023 17.11.40); it is a no-op elsewhere.

Testing:
- Driver tests for forwarding, "none"/empty, last-wins, bad-argument
errors, and the unsupported-target / denormal warnings.
- FIR lowering tests for the emitted call and constant mask, including a
negative test that a non-main compilation unit emits no call.
- flang-rt execution tests that verify each exception (invalid, zero,
overflow, underflow, inexact, denormal) actually terminates the program
with SIGFPE, plus a selectivity test that an unrelated enabled trap does
not halt. The denormal execution test is gated to x86.

These changes were generated with the assistance of AI tooling and have
been reviewed, tested, and validated by the author.

Resolves #198657

Added: 
    flang-rt/test/Driver/fpe-trap-exec-denormal.f90
    flang-rt/test/Driver/fpe-trap-exec-divzero.f90
    flang-rt/test/Driver/fpe-trap-exec-inexact.f90
    flang-rt/test/Driver/fpe-trap-exec-overflow.f90
    flang-rt/test/Driver/fpe-trap-exec-underflow.f90
    flang-rt/test/Driver/fpe-trap-exec.f90
    flang/test/Driver/fpe-trap.f90
    flang/test/Lower/fpe-trap-nonmain.f90
    flang/test/Lower/fpe-trap.f90

Modified: 
    clang/include/clang/Options/FlangOptions.td
    clang/lib/Driver/ToolChains/Flang.cpp
    clang/test/Driver/gfortran.f90
    flang-rt/lib/runtime/exceptions.cpp
    flang/docs/ReleaseNotes.md
    flang/include/flang/Lower/LoweringOptions.def
    flang/include/flang/Optimizer/Builder/Runtime/Main.h
    flang/include/flang/Runtime/exceptions.h
    flang/include/flang/Support/LangOptions.def
    flang/include/flang/Support/LangOptions.h
    flang/lib/Frontend/CompilerInvocation.cpp
    flang/lib/Lower/Bridge.cpp
    flang/lib/Optimizer/Builder/Runtime/Main.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Options/FlangOptions.td 
b/clang/include/clang/Options/FlangOptions.td
index bafc063663fe2..6b375c3b2b7dc 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -21,7 +21,6 @@ def static_libgfortran : Flag<["-"], "static-libgfortran">, 
Group<gfortran_Group
 // "f" options with values for gfortran.
 def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, 
Group<gfortran_Group>;
 def fcheck_EQ : Joined<["-"], "fcheck=">, Group<gfortran_Group>;
-def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<gfortran_Group>;
 def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, 
Group<gfortran_Group>;
 def finit_character_EQ : Joined<["-"], "finit-character=">, 
Group<gfortran_Group>;
 def finit_integer_EQ : Joined<["-"], "finit-integer=">, Group<gfortran_Group>;
@@ -327,6 +326,65 @@ defm real_sum_reassociation
         standard-conforming Fortran semantics.
       }]>;
 
+def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<f_Group>,
+  HelpText<"Set the initial floating-point exception halting mode for the main 
program">,
+  DocBrief<[{The ``-ffpe-trap=[list]`` option sets the initial floating-point
+exception halting mode for the main program unit. This is the halting mode in
+effect when the main program begins execution; the program may subsequently
+change it (for example, with ``IEEE_SET_HALTING_MODE``). ``[list]`` is a
+(possibly empty) comma-separated list of ``none`` or the following exceptions:
+``invalid``, ``zero``, ``overflow``, ``underflow``, ``inexact``, and
+``denormal``. The first five exceptions correspond to the Fortran 2023 (17.6)
+``IEEE_FLAG_TYPE`` values ``IEEE_INVALID``, ``IEEE_DIVIDE_BY_ZERO``,
+``IEEE_OVERFLOW``, ``IEEE_UNDERFLOW``, and ``IEEE_INEXACT``, whereas
+``denormal`` is a non-standard GFortran-compatible extension that halts on the
+hardware denormal (subnormal) operand exception. The value ``none`` may appear
+anywhere in the list; it disables halting and clears any preceding exceptions 
in
+the list, while exceptions following it are still effective (e.g.,
+``invalid,none,zero`` enables halting on ``zero`` only). In the absence of this
+option, or when an empty list is passed to it, the program runs with traps
+disabled (equivalent to passing ``none``). Multiple occurrences of this option
+are allowed, in which case only the last one takes effect.
+
+Run-time halting relies on glibc's ``feenableexcept`` (exposed as
+``IEEE_SUPPORT_HALTING``). The compile-time warning is a conservative
+approximation from the target triple; the runtime is the definitive authority 
on
+which exceptions can be trapped.
+
+The table below summarizes the halting behavior for 
diff erent system
+configurations. The C standard library is ``glibc`` (in practice Linux) or
+``non-glibc``; "Standard Exception" covers ``invalid``, ``zero``, ``overflow``,
+``underflow``, and ``inexact``. In the Standard Exception and Denormal columns,
+each cell names the compiler action followed by the run-time action:
+``compiler accepts`` = the compiler forwards the request without a warning,
+``compiler warns`` = the compiler emits a warning, ``runtime halts`` = the
+exception is trapped at run time, and ``runtime ignores`` = the request is
+silently ignored at run time.
+
++--------------+--------------------+--------------------+-------------------+
+| Architecture | C Standard Library | Standard Exception | Denormal          |
++==============+====================+====================+===================+
+| x86          | glibc              | compiler accepts,  | compiler accepts, |
+|              |                    | runtime halts      | runtime halts     |
++--------------+--------------------+--------------------+-------------------+
+| non-x86      | glibc              | compiler accepts,  | compiler warns,   |
+|              |                    | runtime halts      | runtime ignores   |
++--------------+--------------------+--------------------+-------------------+
+| x86          | non-glibc          | compiler accepts,  | compiler accepts, |
+|              |                    | runtime ignores    | runtime ignores   |
++--------------+--------------------+--------------------+-------------------+
+| non-x86      | non-glibc          | compiler warns,    | compiler warns,   |
+|              |                    | runtime ignores    | runtime ignores   |
++--------------+--------------------+--------------------+-------------------+
+
+Notes:
+
+* On non-x86 targets the standard exceptions halt only where the target's glibc
+  ``feenableexcept`` supports them; the runtime probes each at start-up (via
+  ``IEEE_SUPPORT_HALTING``) and enables only those it can.
+* ``denormal`` is honored only on x86_64; on 32-bit x86 it is silently ignored
+  (no warning).}]>;
+
 defm init_global_zero : BoolOptionWithoutMarshalling<"f", "init-global-zero",
   PosFlag<SetTrue, [], [], "Zero initialize globals without default 
initialization (default)">,
   NegFlag<SetFalse, [], [], "Do not zero initialize globals without default 
initialization">>;

diff  --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index 7ea657ad49474..25bb9832432cc 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -1068,6 +1068,72 @@ static void addFloatingPointOptions(const Driver &D, 
const ArgList &Args,
     CmdArgs.push_back("-freciprocal-math");
 }
 
+// Add options related to IEEE Floating point modes
+//
+// Initial halting mode:
+// Validate -ffpe-trap= and forward it to -fc1. This is handled separately from
+// addFloatingPointOptions() on purpose: -ffpe-trap= is not part of the
+// fast-math option set, so it must not be skipped by that function's
+// -ffast-math fast path. The value check and the target-support warnings 
depend
+// only on the option value and the target triple (no frontend-only state), so
+// they are done here in the driver rather than deferred to -fc1; -fc1 only
+// translates the list into its LangOptions bitmask.
+//
+// TODO:
+// Rounding modes
+// Underflow mode
+static void addIEEEFPModesOptions(const Driver &D, const ArgList &Args,
+                                  ArgStringList &CmdArgs,
+                                  const llvm::Triple &Triple) {
+  const Arg *A = Args.getLastArg(options::OPT_ffpe_trap_EQ);
+  if (!A)
+    return;
+
+  // The value is a comma-separated list of exception mnemonics. "none" and an
+  // empty list request no halting and reset any earlier request in the list;
+  // any other unrecognized mnemonic is an error.
+  llvm::SmallVector<StringRef, 6> Traps;
+  StringRef(A->getValue())
+      .split(Traps, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+  bool RequestsTrap = false;
+  bool RequestsDenormal = false;
+  for (StringRef Trap : Traps) {
+    if (Trap == "none") {
+      RequestsTrap = false;
+      RequestsDenormal = false;
+      continue;
+    }
+    bool IsKnown = llvm::StringSwitch<bool>(Trap)
+                       .Cases({"invalid", "zero", "overflow", "underflow",
+                               "inexact", "denormal"},
+                              true)
+                       .Default(false);
+    if (!IsKnown) {
+      D.Diag(diag::err_drv_unsupported_option_argument)
+          << A->getSpelling() << Trap;
+      return;
+    }
+    RequestsTrap = true;
+    RequestsDenormal |= (Trap == "denormal");
+  }
+
+  // Run-time halting is implemented in flang-rt only where the target's
+  // floating-point environment can trap: it relies on glibc's feenableexcept
+  // (in practice Linux), and "denormal" additionally requires an x86 target.
+  // Warn (conservatively) when the target cannot honor the request; the 
runtime
+  // otherwise ignores it. The denormal-specific warning names just
+  // "-ffpe-trap=denormal" to point at the unsupported mnemonic.
+  if (RequestsTrap && !Triple.isX86() && !Triple.isOSLinux())
+    D.Diag(diag::warn_drv_unsupported_option_for_target)
+        << A->getAsString(Args) << Triple.str();
+  else if (RequestsDenormal && !Triple.isX86())
+    D.Diag(diag::warn_drv_unsupported_option_for_target)
+        << "-ffpe-trap=denormal" << Triple.str();
+
+  A->render(Args, CmdArgs);
+}
+
 static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
                                  const InputInfo &Input) {
   StringRef Format = "yaml";
@@ -1247,6 +1313,10 @@ void Flang::ConstructJob(Compilation &C, const JobAction 
&JA,
   // Floating point related options
   addFloatingPointOptions(D, Args, CmdArgs);
 
+  // Initial floating-point exception halting mode. Handled separately so it is
+  // not skipped by the -ffast-math fast path in addFloatingPointOptions().
+  addIEEEFPModesOptions(D, Args, CmdArgs, Triple);
+
   // Add target args, features, etc.
   addTargetOptions(Args, CmdArgs, JA.getOffloadingArch(),
                    JA.getOffloadingDeviceKind());

diff  --git a/clang/test/Driver/gfortran.f90 b/clang/test/Driver/gfortran.f90
index c985428650ecd..2eb20c802f187 100644
--- a/clang/test/Driver/gfortran.f90
+++ b/clang/test/Driver/gfortran.f90
@@ -68,7 +68,6 @@
 ! RUN:     -ff2c \
 ! RUN:     -ffixed-form \
 ! RUN:     -ffixed-line-length-42 \
-! RUN:     -ffpe-trap=list \
 ! RUN:     -ffree-form \
 ! RUN:     -ffree-line-length-42 \
 ! RUN:     -ffrontend-optimize \
@@ -188,7 +187,6 @@
 ! CHECK: "-ff2c"
 ! CHECK: "-ffixed-form"
 ! CHECK: "-ffixed-line-length-42"
-! CHECK: "-ffpe-trap=list"
 ! CHECK: "-ffree-form"
 ! CHECK: "-ffree-line-length-42"
 ! CHECK: "-ffrontend-optimize"

diff  --git a/flang-rt/lib/runtime/exceptions.cpp 
b/flang-rt/lib/runtime/exceptions.cpp
index 2b1a4f14b1f36..5fb83f0375227 100644
--- a/flang-rt/lib/runtime/exceptions.cpp
+++ b/flang-rt/lib/runtime/exceptions.cpp
@@ -142,6 +142,12 @@ uint32_t RTNAME(fegetexcept)() {
 
 // Check if the processor has the ability to control whether to halt or
 // continue execution when a given exception is raised.
+//
+// TODO: Support halting on x86 without glibc. The MXCSR helpers above (guarded
+// by _MM_EXCEPT_DENORM) already provide the machinery, so this gate could be
+// widened to `#if defined(__USE_GNU) || defined(_MM_EXCEPT_DENORM)` to cover
+// x86_64 macOS/BSD and musl-Linux. Doing so also needs the x87 control word 
for
+// REAL(10), 32-bit x86 (__i386__), and Windows SEH handling; see PR 
discussion.
 bool RTNAME(SupportHalting)([[maybe_unused]] uint32_t except) {
 #ifdef __USE_GNU
   except = RTNAME(MapException)(except);
@@ -161,6 +167,25 @@ bool RTNAME(SupportHalting)([[maybe_unused]] uint32_t 
except) {
 #endif
 }
 
+void RTNAME(EnableFPETraps)(uint32_t excepts) {
+  // Enable halting only for those exceptions whose halting control is 
supported
+  // by the processor. The Fortran standard restricts IEEE_SET_HALTING_MODE to
+  // flags for which IEEE_SUPPORT_HALTING is true (F2023 17.11.40); on targets
+  // without halting control (e.g. non-glibc), this is a no-op.
+  uint32_t supported = 0;
+  for (uint32_t flag = 1; flag <= excepts; flag <<= 1) {
+    if ((excepts & flag) && RTNAME(SupportHalting)(flag)) {
+      supported |= flag;
+    }
+  }
+  if (supported == 0) {
+    return;
+  }
+  uint32_t mapped = RTNAME(MapException)(supported);
+  RTNAME(feclearexcept)(mapped);
+  RTNAME(feenableexcept)(mapped);
+}
+
 // A hardware FZ (flush to zero) bit is the negation of the
 // ieee_[get|set]_underflow_mode GRADUAL argument.
 #if defined(_MM_FLUSH_ZERO_MASK)

diff  --git a/flang-rt/test/Driver/fpe-trap-exec-denormal.f90 
b/flang-rt/test/Driver/fpe-trap-exec-denormal.f90
new file mode 100644
index 0000000000000..97490e2bdd6db
--- /dev/null
+++ b/flang-rt/test/Driver/fpe-trap-exec-denormal.f90
@@ -0,0 +1,33 @@
+! Test that -ffpe-trap=denormal enables run-time halting on the (non-standard,
+! gfortran-compatible) denormal-operand exception.
+
+! The denormal-operand exception is an x86 SSE feature (__FE_DENORM); on other
+! architectures it is not available, so restrict this test to x86 glibc.
+! REQUIRES: target=x86_64{{.*}}-linux-gnu
+! UNSUPPORTED: offload-cuda
+
+! Built without traps: the operation on a subnormal operand completes and the
+! program exits normally.
+! RUN: %flang %isysroot -L"%libdir" %s -o %t.notrap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t.notrap \
+! RUN:     | FileCheck --check-prefix=NOTRAP %s
+
+! Built with -ffpe-trap=denormal: adding a subnormal operand raises the
+! denormal-operand exception and halting terminates the program with SIGFPE
+! (signal 8, i.e. shell exit 136).
+! RUN: %flang %isysroot -L"%libdir" -ffpe-trap=denormal %s -o %t.trap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" sh -c 'ulimit -c 0; 
%t.trap; test $? -eq 136'
+
+program fpe_trap_denormal
+  real :: x, y
+  ! Build a subnormal value at runtime. Its operands are normal, so this does
+  ! not itself raise the denormal-operand exception, and 2**-127 is an exact
+  ! subnormal, so it does not raise underflow either.
+  x = tiny(0.0) * (0.5 + real(command_argument_count()))
+  ! x is subnormal, so this operation has a denormal operand.
+  y = x + x
+  print '(A)', "no-trap"
+  print *, y
+end program
+
+! NOTRAP: no-trap

diff  --git a/flang-rt/test/Driver/fpe-trap-exec-divzero.f90 
b/flang-rt/test/Driver/fpe-trap-exec-divzero.f90
new file mode 100644
index 0000000000000..b68494c72da1b
--- /dev/null
+++ b/flang-rt/test/Driver/fpe-trap-exec-divzero.f90
@@ -0,0 +1,38 @@
+! Test that -ffpe-trap=zero enables run-time halting on an IEEE_DIVIDE_BY_ZERO
+! exception, and that trapping is selective (a 
diff erent enabled trap does not
+! halt on a divide-by-zero).
+
+! Halting requires both glibc (feenableexcept) and hardware that delivers a
+! trap when an enabled FP exception is raised. Arm makes FP-exception trapping
+! optional, and the AArch64 CI hardware does not deliver SIGFPE, so restrict
+! this run-time test to x86 glibc.
+! REQUIRES: target=x86_64{{.*}}-linux-gnu
+! UNSUPPORTED: offload-cuda
+
+! Built without traps: the division by zero yields infinity and the program
+! exits normally.
+! RUN: %flang %isysroot -L"%libdir" %s -o %t.notrap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t.notrap \
+! RUN:     | FileCheck --check-prefix=NOTRAP %s
+
+! Built with -ffpe-trap=zero: the division by zero raises IEEE_DIVIDE_BY_ZERO
+! and halting terminates the program with SIGFPE (signal 8, i.e. shell exit 
136).
+! RUN: %flang %isysroot -L"%libdir" -ffpe-trap=zero %s -o %t.trap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" sh -c 'ulimit -c 0; 
%t.trap; test $? -eq 136'
+
+! Selectivity: trapping on overflow only must not halt on a divide-by-zero.
+! RUN: %flang %isysroot -L"%libdir" -ffpe-trap=overflow %s -o %t.other
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t.other \
+! RUN:     | FileCheck --check-prefix=NOTRAP %s
+
+program fpe_trap_divzero
+  real :: x, y
+  ! command_argument_count() is not known at compile time, which prevents the
+  ! division from being folded away by the compiler.
+  x = real(command_argument_count())
+  y = 1.0 / x
+  print '(A)', "no-trap"
+  print *, y
+end program
+
+! NOTRAP: no-trap

diff  --git a/flang-rt/test/Driver/fpe-trap-exec-inexact.f90 
b/flang-rt/test/Driver/fpe-trap-exec-inexact.f90
new file mode 100644
index 0000000000000..db1a9ac9a41c3
--- /dev/null
+++ b/flang-rt/test/Driver/fpe-trap-exec-inexact.f90
@@ -0,0 +1,33 @@
+! Test that -ffpe-trap=inexact enables run-time halting on an IEEE_INEXACT
+! exception.
+
+! Halting requires both glibc (feenableexcept) and hardware that delivers a
+! trap when an enabled FP exception is raised. Arm makes FP-exception trapping
+! optional, and the AArch64 CI hardware does not deliver SIGFPE, so restrict
+! this run-time test to x86 glibc.
+! REQUIRES: target=x86_64{{.*}}-linux-gnu
+! UNSUPPORTED: offload-cuda
+
+! Built without traps: the inexact division completes and the program exits
+! normally.
+! RUN: %flang %isysroot -L"%libdir" %s -o %t.notrap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t.notrap \
+! RUN:     | FileCheck --check-prefix=NOTRAP %s
+
+! Built with -ffpe-trap=inexact: the division 1.0/3.0 is inexact and halting
+! terminates the program with SIGFPE (signal 8, i.e. shell exit 136). This is
+! the first floating-point operation, so the trap is deterministic.
+! RUN: %flang %isysroot -L"%libdir" -ffpe-trap=inexact %s -o %t.trap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" sh -c 'ulimit -c 0; 
%t.trap; test $? -eq 136'
+
+program fpe_trap_inexact
+  real :: x, y
+  ! real(3 + count) is exact for the runtime-unknown small integer, so the
+  ! division below is the first inexact operation.
+  x = real(3 + command_argument_count())
+  y = 1.0 / x
+  print '(A)', "no-trap"
+  print *, y
+end program
+
+! NOTRAP: no-trap

diff  --git a/flang-rt/test/Driver/fpe-trap-exec-overflow.f90 
b/flang-rt/test/Driver/fpe-trap-exec-overflow.f90
new file mode 100644
index 0000000000000..7fb3b990fbf07
--- /dev/null
+++ b/flang-rt/test/Driver/fpe-trap-exec-overflow.f90
@@ -0,0 +1,32 @@
+! Test that -ffpe-trap=overflow enables run-time halting on an IEEE_OVERFLOW
+! exception.
+
+! Halting requires both glibc (feenableexcept) and hardware that delivers a
+! trap when an enabled FP exception is raised. Arm makes FP-exception trapping
+! optional, and the AArch64 CI hardware does not deliver SIGFPE, so restrict
+! this run-time test to x86 glibc.
+! REQUIRES: target=x86_64{{.*}}-linux-gnu
+! UNSUPPORTED: offload-cuda
+
+! Built without traps: the overflowing multiplication yields infinity and the
+! program exits normally.
+! RUN: %flang %isysroot -L"%libdir" %s -o %t.notrap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t.notrap \
+! RUN:     | FileCheck --check-prefix=NOTRAP %s
+
+! Built with -ffpe-trap=overflow: the multiplication raises IEEE_OVERFLOW and
+! halting terminates the program with SIGFPE (signal 8, i.e. shell exit 136).
+! RUN: %flang %isysroot -L"%libdir" -ffpe-trap=overflow %s -o %t.trap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" sh -c 'ulimit -c 0; 
%t.trap; test $? -eq 136'
+
+program fpe_trap_overflow
+  real :: x, y
+  ! Subtracting a runtime-unknown value keeps x == huge while preventing the
+  ! compiler from folding the overflowing multiplication.
+  x = huge(0.0) - real(command_argument_count())
+  y = x * x
+  print '(A)', "no-trap"
+  print *, y
+end program
+
+! NOTRAP: no-trap

diff  --git a/flang-rt/test/Driver/fpe-trap-exec-underflow.f90 
b/flang-rt/test/Driver/fpe-trap-exec-underflow.f90
new file mode 100644
index 0000000000000..1e7d8aa8d198f
--- /dev/null
+++ b/flang-rt/test/Driver/fpe-trap-exec-underflow.f90
@@ -0,0 +1,33 @@
+! Test that -ffpe-trap=underflow enables run-time halting on an IEEE_UNDERFLOW
+! exception.
+
+! Halting requires both glibc (feenableexcept) and hardware that delivers a
+! trap when an enabled FP exception is raised. Arm makes FP-exception trapping
+! optional, and the AArch64 CI hardware does not deliver SIGFPE, so restrict
+! this run-time test to x86 glibc.
+! REQUIRES: target=x86_64{{.*}}-linux-gnu
+! UNSUPPORTED: offload-cuda
+
+! Built without traps: the underflowing multiplication completes and the
+! program exits normally.
+! RUN: %flang %isysroot -L"%libdir" %s -o %t.notrap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t.notrap \
+! RUN:     | FileCheck --check-prefix=NOTRAP %s
+
+! Built with -ffpe-trap=underflow: squaring the smallest normal value yields a
+! result below the subnormal range, raising IEEE_UNDERFLOW, and halting
+! terminates the program with SIGFPE (signal 8, i.e. shell exit 136).
+! RUN: %flang %isysroot -L"%libdir" -ffpe-trap=underflow %s -o %t.trap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" sh -c 'ulimit -c 0; 
%t.trap; test $? -eq 136'
+
+program fpe_trap_underflow
+  real :: x, y
+  ! x == tiny (the smallest normal), computed via a runtime-unknown factor so
+  ! the multiplication below is not folded. tiny*1.0 is exact (no underflow).
+  x = tiny(0.0) * real(command_argument_count() + 1)
+  y = x * x
+  print '(A)', "no-trap"
+  print *, y
+end program
+
+! NOTRAP: no-trap

diff  --git a/flang-rt/test/Driver/fpe-trap-exec.f90 
b/flang-rt/test/Driver/fpe-trap-exec.f90
new file mode 100644
index 0000000000000..b5c5d6cae1d61
--- /dev/null
+++ b/flang-rt/test/Driver/fpe-trap-exec.f90
@@ -0,0 +1,33 @@
+! Test that -ffpe-trap= actually enables halting at run time: an invalid
+! floating-point operation must terminate the program with a signal (SIGFPE)
+! when the corresponding trap is enabled, and must complete normally otherwise.
+
+! Halting requires both glibc (feenableexcept) and hardware that delivers a
+! trap when an enabled FP exception is raised. Arm makes FP-exception trapping
+! optional, and the AArch64 CI hardware does not deliver SIGFPE, so restrict
+! this run-time test to x86 glibc.
+! REQUIRES: target=x86_64{{.*}}-linux-gnu
+! UNSUPPORTED: offload-cuda
+
+! Built without traps: the invalid operation yields a NaN and the program exits
+! normally.
+! RUN: %flang %isysroot -L"%libdir" %s -o %t.notrap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t.notrap \
+! RUN:     | FileCheck --check-prefix=NOTRAP %s
+
+! Built with -ffpe-trap=invalid: the invalid operation raises IEEE_INVALID and
+! halting terminates the program with SIGFPE (signal 8, i.e. shell exit 136).
+! RUN: %flang %isysroot -L"%libdir" -ffpe-trap=invalid %s -o %t.trap
+! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" sh -c 'ulimit -c 0; 
%t.trap; test $? -eq 136'
+
+program fpe_trap_exec
+  real :: x, y
+  ! command_argument_count() is not known at compile time, which prevents the
+  ! invalid operation from being folded away by the compiler.
+  x = real(command_argument_count()) - 1.0
+  y = sqrt(x)
+  print '(A)', "no-trap"
+  print *, y
+end program
+
+! NOTRAP: no-trap

diff  --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index 19a69a0a7c675..2871b4b66c155 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -48,6 +48,11 @@ page](https://llvm.org/releases/).
   reducing debug information size in compiled binaries.
 
 ## New Compiler Flags
+- Added the gfortran-compatible `-ffpe-trap=` flag, which sets the initial
+  floating-point exception halting mode of the main program. It takes a
+  comma-separated list of `invalid`, `zero`, `overflow`, `underflow`, 
`inexact`,
+  and the extension `denormal`, or `none` to disable halting. See the Flang
+  command line reference for the supported targets and details.
 
 - Added `-gz` and `-gz=<format>` flags to enable compression of DWARF debug
   sections. Supported formats are `zlib`, `zstd`, and `none`.

diff  --git a/flang/include/flang/Lower/LoweringOptions.def 
b/flang/include/flang/Lower/LoweringOptions.def
index 0b02ffd5a3b22..61ccb2ac19bdd 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -93,5 +93,9 @@ ENUM_LOWERINGOPT(PreserveUseDebugInfo, unsigned, 1, 0)
 /// Portable, Extremum, ExtremeNum). Default: Legacy.
 ENUM_LOWERINGOPT(FPMaxminBehavior, Fortran::common::FPMaxminBehavior, 2, 0)
 
+/// Bitmask of floating-point exceptions to trap on (from -ffpe-trap=).
+/// 0 means no trapping. Bit values match IEEE_FLAG_TYPE encoding.
+ENUM_LOWERINGOPT(FPExceptionTraps, unsigned, 8, 0)
+
 #undef LOWERINGOPT
 #undef ENUM_LOWERINGOPT

diff  --git a/flang/include/flang/Optimizer/Builder/Runtime/Main.h 
b/flang/include/flang/Optimizer/Builder/Runtime/Main.h
index d4067b367f73e..1acc3cbed35c5 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Main.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Main.h
@@ -25,7 +25,8 @@ namespace fir::runtime {
 
 void genMain(fir::FirOpBuilder &builder, mlir::Location loc,
              const std::vector<Fortran::lower::EnvironmentDefault> &defs,
-             bool initCuda = false, bool initCoarrayEnv = false);
+             bool initCuda = false, bool initCoarrayEnv = false,
+             unsigned fpExceptionTraps = 0);
 }
 
 #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_MAIN_H

diff  --git a/flang/include/flang/Runtime/exceptions.h 
b/flang/include/flang/Runtime/exceptions.h
index 2497a48402233..99cb8788f7c50 100644
--- a/flang/include/flang/Runtime/exceptions.h
+++ b/flang/include/flang/Runtime/exceptions.h
@@ -47,6 +47,11 @@ void RTNAME(SetUnderflowMode)(bool flag);
 std::size_t RTNAME(GetModesTypeSize)(void);
 std::size_t RTNAME(GetStatusTypeSize)(void);
 
+// Enable trapping on the specified floating-point exceptions.
+// The excepts argument is a bitmask of IEEE_FLAG_TYPE values
+// (as used by MapException).
+void RTNAME(EnableFPETraps)(std::uint32_t excepts);
+
 } // extern "C"
 } // namespace Fortran::runtime
 #endif // FORTRAN_RUNTIME_EXCEPTIONS_H_

diff  --git a/flang/include/flang/Support/LangOptions.def 
b/flang/include/flang/Support/LangOptions.def
index 7ae73c6755b57..80d2302cc8c72 100644
--- a/flang/include/flang/Support/LangOptions.def
+++ b/flang/include/flang/Support/LangOptions.def
@@ -69,6 +69,8 @@ LANGOPT(OpenMPSimd, 1, false)
 LANGOPT(NoReallocateLHS, 1, false)
 /// Enable fast MOD operations for REAL
 LANGOPT(FastRealMod, 1, false)
+/// Bitmask of floating-point exceptions to trap on (from -ffpe-trap=)
+LANGOPT(FPExceptionTraps, 8, 0)
 LANGOPT(VScaleMin, 32, 0)  ///< Minimum vscale range value
 LANGOPT(VScaleMax, 32, 0)  ///< Maximum vscale range value
 

diff  --git a/flang/include/flang/Support/LangOptions.h 
b/flang/include/flang/Support/LangOptions.h
index 1dd676e62a9e5..42b488c3d18a3 100644
--- a/flang/include/flang/Support/LangOptions.h
+++ b/flang/include/flang/Support/LangOptions.h
@@ -43,6 +43,18 @@ class LangOptionsBase {
     FPM_Fast,
   };
 
+  /// Floating-point exception trap kinds for -ffpe-trap=.
+  /// Bit values match the Fortran IEEE_FLAG_TYPE encoding used by
+  /// the runtime's MapException().
+  enum FPExceptionTrapKind : unsigned {
+    FPE_Invalid = 1,
+    FPE_Denormal = 2,
+    FPE_DivByZero = 4,
+    FPE_Overflow = 8,
+    FPE_Underflow = 16,
+    FPE_Inexact = 32,
+  };
+
 #define LANGOPT(Name, Bits, Default) unsigned Name : Bits;
 #define ENUM_LANGOPT(Name, Type, Bits, Default)
 #include "LangOptions.def"

diff  --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index da9877cf2e417..33ce6cb6869f1 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1431,6 +1431,54 @@ static bool parseIntegerOverflowArgs(CompilerInvocation 
&invoc,
   return true;
 }
 
+/// Set the IEEE Floating point rounding modes, underflow mode and halting 
mode.
+///
+/// Initial halting mode:
+/// -ffpe-trap= sets the initial floating-point exception halting mode for the
+/// main program. Only the last -ffpe-trap= on the command line is effective.
+/// The value is a comma-separated set of exception mnemonics: "invalid",
+/// "zero", "overflow", "underflow", and "inexact" correspond to the Fortran
+/// 2023 IEEE_FLAG_TYPE values (F2023 17.2), and "denormal" is a non-standard,
+/// gfortran-compatible extension. "none", as well as an empty list, requests 
no
+/// halting and resets any earlier request.
+///
+/// TODO:
+/// Rounding modes
+/// Underflow mode
+///
+/// The value and the target-support warnings are validated in the driver (see
+/// addIEEEFPModesOptions() in clang/lib/Driver/ToolChains/Flang.cpp);
+/// here we only translate the already-validated list, so an unrecognized
+/// mnemonic maps to 0 and is ignored rather than re-diagnosed.
+static void setIEEEFPModesArgs(Fortran::common::LangOptions &opts,
+                               llvm::opt::ArgList &args) {
+  const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_ffpe_trap_EQ);
+  if (!a)
+    return;
+
+  using LangOptions = Fortran::common::LangOptions;
+  unsigned traps = 0;
+  llvm::SmallVector<llvm::StringRef> trapList;
+  llvm::StringRef(a->getValue())
+      .split(trapList, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+  for (llvm::StringRef trap : trapList) {
+    if (trap == "none") {
+      // Reset to no halting; a later mnemonic can re-enable.
+      traps = 0;
+      continue;
+    }
+    traps |= llvm::StringSwitch<unsigned>(trap)
+                 .Case("invalid", LangOptions::FPE_Invalid)
+                 .Case("denormal", LangOptions::FPE_Denormal)
+                 .Case("zero", LangOptions::FPE_DivByZero)
+                 .Case("overflow", LangOptions::FPE_Overflow)
+                 .Case("underflow", LangOptions::FPE_Underflow)
+                 .Case("inexact", LangOptions::FPE_Inexact)
+                 .Default(0);
+  }
+  opts.FPExceptionTraps = traps;
+}
+
 /// Parses all floating point related arguments and populates the
 /// CompilerInvocation accordingly.
 /// Returns false if new errors are generated.
@@ -1505,6 +1553,9 @@ static bool parseFloatingPointArgs(CompilerInvocation 
&invoc,
       opts.FastRealMod = false;
   }
 
+  // Set the initial IEEE floating point modes
+  setIEEEFPModesArgs(opts, args);
+
   return true;
 }
 
@@ -2046,4 +2097,6 @@ void CompilerInvocation::setLoweringOptions() {
       codegenOpts.getComplexRange() ==
           CodeGenOptions::ComplexRangeKind::CX_Basic)
     loweringOpts.setComplexDivisionToRuntime(false);
+
+  loweringOpts.setFPExceptionTraps(langOptions.FPExceptionTraps);
 }

diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index ed8b256f47fd4..534dffb6f284b 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -614,14 +614,15 @@ class FirConverter : public 
Fortran::lower::AbstractConverter {
     // Generate the `main` entry point if necessary
     if (hasMainProgram)
       createBuilderOutsideOfFuncOpAndDo([&]() {
-        fir::runtime::genMain(*builder, toLocation(),
-                              bridge.getEnvironmentDefaults(),
-                              
(getFoldingContext().languageFeatures().IsEnabled(
-                                   Fortran::common::LanguageFeature::CUDA) &&
-                               
getFoldingContext().languageFeatures().IsEnabled(
-                                   
Fortran::common::LanguageFeature::CUDAInit)),
-                              getFoldingContext().languageFeatures().IsEnabled(
-                                  Fortran::common::LanguageFeature::Coarray));
+        fir::runtime::genMain(
+            *builder, toLocation(), bridge.getEnvironmentDefaults(),
+            (getFoldingContext().languageFeatures().IsEnabled(
+                 Fortran::common::LanguageFeature::CUDA) &&
+             getFoldingContext().languageFeatures().IsEnabled(
+                 Fortran::common::LanguageFeature::CUDAInit)),
+            getFoldingContext().languageFeatures().IsEnabled(
+                Fortran::common::LanguageFeature::Coarray),
+            bridge.getLoweringOptions().getFPExceptionTraps());
       });
 
     finalizeOpenMPLowering(globalOmpRequiresSymbols);

diff  --git a/flang/lib/Optimizer/Builder/Runtime/Main.cpp 
b/flang/lib/Optimizer/Builder/Runtime/Main.cpp
index acc7700891805..2427088ec7f83 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Main.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Main.cpp
@@ -14,6 +14,7 @@
 #include "flang/Optimizer/Dialect/FIROps.h"
 #include "flang/Optimizer/Dialect/MIF/MIFOps.h"
 #include "flang/Runtime/CUDA/init.h"
+#include "flang/Runtime/exceptions.h"
 #include "flang/Runtime/main.h"
 #include "flang/Runtime/stop.h"
 
@@ -23,7 +24,7 @@ using namespace Fortran::runtime;
 void fir::runtime::genMain(
     fir::FirOpBuilder &builder, mlir::Location loc,
     const std::vector<Fortran::lower::EnvironmentDefault> &defs, bool initCuda,
-    bool initCoarrayEnv) {
+    bool initCoarrayEnv, unsigned fpExceptionTraps) {
   auto *context = builder.getContext();
   auto argcTy = builder.getDefaultIntegerType();
   auto ptrTy = mlir::LLVM::LLVMPointerType::get(context);
@@ -71,6 +72,16 @@ void fir::runtime::genMain(
   if (initCoarrayEnv)
     mif::InitOp::create(builder, loc);
 
+  if (fpExceptionTraps != 0) {
+    auto i32Ty = builder.getI32Type();
+    auto enableFn =
+        builder.createFunction(loc, RTNAME_STRING(EnableFPETraps),
+                               mlir::FunctionType::get(context, {i32Ty}, {}));
+    mlir::Value trapsVal =
+        builder.createIntegerConstant(loc, i32Ty, fpExceptionTraps);
+    fir::CallOp::create(builder, loc, enableFn, mlir::ValueRange{trapsVal});
+  }
+
   fir::CallOp::create(builder, loc, qqMainFn);
 
   mlir::Value ret = builder.createIntegerConstant(loc, argcTy, 0);

diff  --git a/flang/test/Driver/fpe-trap.f90 b/flang/test/Driver/fpe-trap.f90
new file mode 100644
index 0000000000000..71f77c61d5928
--- /dev/null
+++ b/flang/test/Driver/fpe-trap.f90
@@ -0,0 +1,80 @@
+! Test the -ffpe-trap= option: driver forwarding and driver-level validation
+! (value checking and target-support warnings).
+
+!--- The driver forwards -ffpe-trap= to the frontend 
---------------------------
+
+! Test all supported exception types are forwarded to -fc1.
+! RUN: %flang -ffpe-trap=invalid,zero,overflow,underflow,inexact,denormal -### 
%s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-ALL %s
+! CHECK-ALL: -fc1
+! CHECK-ALL-SAME: -ffpe-trap=invalid,zero,overflow,underflow,inexact,denormal
+
+! Test a single exception type.
+! RUN: %flang -ffpe-trap=invalid -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-SINGLE %s
+! CHECK-SINGLE: -fc1
+! CHECK-SINGLE-SAME: -ffpe-trap=invalid
+
+! Only the last -ffpe-trap= is forwarded to the frontend.
+! RUN: %flang -ffpe-trap=invalid -ffpe-trap=overflow -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-LAST %s
+! CHECK-LAST: -fc1
+! CHECK-LAST-SAME: -ffpe-trap=overflow
+! CHECK-LAST-NOT: -ffpe-trap=invalid
+
+! By default (no -ffpe-trap=), nothing is forwarded to the frontend.
+! RUN: %flang -### %s 2>&1 | FileCheck --check-prefix=CHECK-DEFAULT %s
+! CHECK-DEFAULT: -fc1
+! CHECK-DEFAULT-NOT: -ffpe-trap
+
+!--- "none" and an empty list are accepted 
-------------------------------------
+
+! These are valid and must not produce a driver error (a non-zero exit code
+! would make these RUN lines fail).
+! RUN: %flang -ffpe-trap=none -### %s
+! RUN: %flang -ffpe-trap= -### %s
+! RUN: %flang -ffpe-trap=invalid,none -### %s
+
+!--- The driver rejects an unknown mnemonic 
------------------------------------
+
+! RUN: not %flang -ffpe-trap=bogus -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-BADARG %s
+! CHECK-BADARG: error: unsupported argument 'bogus' to option '-ffpe-trap='
+
+!--- -ffpe-trap= is independent of -ffast-math / -Ofast 
------------------------
+
+! -ffpe-trap= is not part of the fast-math option set, so it is still forwarded
+! and still validated when -ffast-math/-Ofast is present.
+! RUN: %flang -Ofast -ffpe-trap=invalid -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-FASTMATH %s
+! CHECK-FASTMATH: -fc1
+! CHECK-FASTMATH-SAME: -ffpe-trap=invalid
+
+! RUN: not %flang -Ofast -ffpe-trap=bogus -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-BADARG %s
+
+!--- The driver warns when the target cannot honor the request 
-----------------
+
+! On a target without floating-point halting support, the driver warns and the
+! option is ignored at run time.
+! RUN: %flang --target=powerpc64-ibm-aix -ffpe-trap=invalid -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-WARN %s
+! CHECK-WARN: warning: ignoring '-ffpe-trap=invalid' option as it is not 
currently supported for target 'powerpc64-ibm-aix'
+
+! On a supported non-x86 target (glibc/Linux), no warning is emitted.
+! RUN: %flang --target=aarch64-unknown-linux-gnu -ffpe-trap=invalid -### %s 
2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-NOWARN --allow-empty %s
+! CHECK-NOWARN-NOT: ignoring '-ffpe-trap
+
+! The "denormal" exception is an x86-only extension: requesting it for a 
non-x86
+! target warns even though the target is otherwise supported.
+! RUN: %flang --target=aarch64-unknown-linux-gnu -ffpe-trap=invalid,denormal 
-### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-DENORM %s
+! CHECK-DENORM: warning: ignoring '-ffpe-trap=denormal' option as it is not 
currently supported for target 'aarch64-unknown-linux-gnu'
+
+! On x86 the "denormal" exception is supported, so no warning is emitted.
+! RUN: %flang --target=x86_64-unknown-linux-gnu -ffpe-trap=denormal -### %s 
2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-X86DENORM --allow-empty %s
+! CHECK-X86DENORM-NOT: ignoring '-ffpe-trap
+
+end program

diff  --git a/flang/test/Lower/fpe-trap-nonmain.f90 
b/flang/test/Lower/fpe-trap-nonmain.f90
new file mode 100644
index 0000000000000..18a4e4f7cc089
--- /dev/null
+++ b/flang/test/Lower/fpe-trap-nonmain.f90
@@ -0,0 +1,20 @@
+! Test that -ffpe-trap= only affects the main program unit: a compilation unit
+! without a main program must not generate a call to _FortranAEnableFPETraps.
+
+! RUN: %flang_fc1 -emit-fir -ffpe-trap=invalid,zero,overflow %s -o - | 
FileCheck %s
+
+subroutine sub(x)
+  real :: x
+  x = x + 1.0
+end subroutine
+
+module m
+contains
+  function f(y) result(z)
+    real :: y, z
+    z = y * 2.0
+  end function
+end module
+
+! CHECK-NOT: fir.call @_FortranAEnableFPETraps
+! CHECK-NOT: @_QQmain

diff  --git a/flang/test/Lower/fpe-trap.f90 b/flang/test/Lower/fpe-trap.f90
new file mode 100644
index 0000000000000..1e39cfe9fc55f
--- /dev/null
+++ b/flang/test/Lower/fpe-trap.f90
@@ -0,0 +1,31 @@
+! Test that -ffpe-trap= generates a call to _FortranAEnableFPETraps in main().
+
+! RUN: %flang_fc1 -emit-fir -ffpe-trap=invalid %s -o - | FileCheck 
--check-prefix=CHECK-INVALID %s
+! RUN: %flang_fc1 -emit-fir -ffpe-trap=invalid,zero,overflow %s -o - | 
FileCheck --check-prefix=CHECK-MULTI %s
+! RUN: %flang_fc1 -emit-fir -ffpe-trap=invalid,underflow,inexact,denormal %s 
-o - | FileCheck --check-prefix=CHECK-EXT %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck --check-prefix=CHECK-NONE %s
+! RUN: %flang_fc1 -emit-fir -ffpe-trap=none %s -o - | FileCheck 
--check-prefix=CHECK-NONE %s
+! RUN: %flang_fc1 -emit-fir -ffpe-trap=invalid,none %s -o - | FileCheck 
--check-prefix=CHECK-NONE %s
+
+program test
+  continue
+end
+
+! CHECK-INVALID: %[[INVALID:.*]] = arith.constant 1 : i32
+! CHECK-INVALID: fir.call @_FortranAProgramStart(
+! CHECK-INVALID: fir.call @_FortranAEnableFPETraps(%[[INVALID]])
+! CHECK-INVALID: fir.call @_QQmain
+
+! invalid=1, zero=4, overflow=8 => 13
+! CHECK-MULTI: %[[MULTI:.*]] = arith.constant 13 : i32
+! CHECK-MULTI: fir.call @_FortranAProgramStart(
+! CHECK-MULTI: fir.call @_FortranAEnableFPETraps(%[[MULTI]])
+! CHECK-MULTI: fir.call @_QQmain
+
+! invalid=1, denormal=2, underflow=16, inexact=32 => 51
+! CHECK-EXT: %[[EXT:.*]] = arith.constant 51 : i32
+! CHECK-EXT: fir.call @_FortranAProgramStart(
+! CHECK-EXT: fir.call @_FortranAEnableFPETraps(%[[EXT]])
+! CHECK-EXT: fir.call @_QQmain
+
+! CHECK-NONE-NOT: @_FortranAEnableFPETraps


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to