Bug description
The CMake option FPE_TRAP_ENABLED is documented as "Enable FPE trap in compiler options", but
it adds no compiler option. Setting it to ON has exactly one effect: it defines the
preprocessor macro FPE_TRAP_ENABLED, which compiles out the body of Set_IEEE_Constants in
the Sys*.f90 layer.
Two consequences:
- No floating-point trapping is enabled. No
-ffpe-trap (GFortran) or -fpe0 (Intel) flag
is added anywhere in the build system. A user who sets -DFPE_TRAP_ENABLED=ON expecting a
trapping build gets an ordinary non-trapping build.
- The global IEEE constants are left undefined.
Set_IEEE_Constants is the only place that
assigns NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S. These are module variables in
NWTC_Num with no initializer, assigned once from SetConstants. With the macro defined the
whole assignment block is #ifndef-ed out, so they retain indeterminate values for the life
of the run. The source comment acknowledges this: "note that anything that refers to NaN or
Inf will be incorrect in that case."
So the option as it stands removes the NaN/Inf definitions — the cost of a trapping build —
without delivering the trapping that would justify it. It is only correct if the user separately
supplies trapping flags through CMAKE_Fortran_FLAGS, which is not what the option's help text
describes.
To Reproduce
- Configure twice, changing only the option:
cmake -B build-off -DCMAKE_BUILD_TYPE=Release -DFPE_TRAP_ENABLED=OFF
cmake -B build-on -DCMAKE_BUILD_TYPE=Release -DFPE_TRAP_ENABLED=ON
- Compare the generated Fortran flags, e.g.
diff <(grep Fortran_FLAGS build-off/modules/aerodyn/CMakeFiles/aerodynlib.dir/flags.make) \
<(grep Fortran_FLAGS build-on/modules/aerodyn/CMakeFiles/aerodynlib.dir/flags.make)
- The flag lines are identical apart from
-DFPE_TRAP_ENABLED. No -ffpe-trap appears in
either; grep -r ffpe-trap over the whole source and build trees returns nothing.
Expected behavior
-DFPE_TRAP_ENABLED=ON should produce a build that traps on floating-point exceptions, since
that is what the option name and help string promise. Suppressing the NaN/Inf generation block
should be a consequence of trapping being enabled, not the entire behaviour.
Relevant code
CMakeLists.txt:43 — option(FPE_TRAP_ENABLED "Enable FPE trap in compiler options" off)
CMakeLists.txt:104-106 — the option's only effect:
if (FPE_TRAP_ENABLED)
add_definitions(-DFPE_TRAP_ENABLED)
endif (FPE_TRAP_ENABLED)
modules/nwtc-library/src/SysGnuLinux.f90:298 — #ifndef FPE_TRAP_ENABLED around the entire
body of Set_IEEE_Constants. The same guard appears in SysGnuWin.f90:298,
SysMatlabLinuxGnu.f90:301, SysIVF_Labview.f90:371 and SysFlangLinux.f90:275.
modules/nwtc-library/src/NWTC_Num.f90:33,35 (and the ReKi/SiKi equivalents) — the
variables are declared with no initializer.
modules/nwtc-library/src/NWTC_Num.f90:5478 — the single call site, inside SetConstants.
Impact
Low frequency, but silent when it bites. Anyone using the option for its stated purpose gets no
trapping, so the debugging session it was enabled for cannot work. Any code path that reads
NaN/Inf in such a build reads an undefined value rather than the intended IEEE constant;
these are referenced in WAMIT2.f90 and AeroDisk_IO.f90 among others.
There is also a forward-looking reason to fix it. PR #3464 introduces a build rule that uses
NOT FPE_TRAP_ENABLED as a proxy for "this is not a trapping build", in order to decide whether
-fno-trapping-math is safe to apply to the OLAF kernels. That inference is only sound if the
option genuinely tracks trapping builds. As things stand, a user who enables trapping the
conventional way — -DCMAKE_Fortran_FLAGS="-ffpe-trap=invalid,zero,overflow" without also
setting -DFPE_TRAP_ENABLED=ON — would get -fno-trapping-math applied anyway.
Suggested fix
Either of the following would resolve it; the first matches the documented intent.
- Make the option add the trapping flags per compiler, for example
-ffpe-trap=invalid,zero,overflow for GNU and -fpe0 for Intel, alongside the existing
add_definitions. The Sys*.f90 guard then does what its comment says it does.
- Keep the current behaviour but rename and re-document the option to reflect it — something
like FPE_TRAP_COMPATIBLE, with help text stating that it only suppresses the NaN/Inf
generation and must be paired with user-supplied trapping flags.
In either case, it would help to have the build fail fast, or at least warn, when -ffpe-trap
appears in CMAKE_Fortran_FLAGS while FPE_TRAP_ENABLED is OFF, since that combination
currently produces a trapping build that still executes the deliberate divide-by-zero in
Set_IEEE_Constants and will abort during initialization.
OpenFAST Version
Reproduced on dev at 386378cdb (v5.0.0-423-g386378cdb). The behaviour is long-standing,
not a recent regression.
System Information
- OS: Linux (Debian 12, container)
- Compiler: GNU Fortran (Debian 12.2.0-14+deb12u1) 12.2.0
- CMake: 3.25.1
- Build:
CMAKE_BUILD_TYPE=Release, DOUBLE_PRECISION=ON
Additional context
This is a build-system issue only; it does not affect results in any default build, since
FPE_TRAP_ENABLED defaults to off and the NaN/Inf constants are then set correctly.
Bug description
The CMake option
FPE_TRAP_ENABLEDis documented as "Enable FPE trap in compiler options", butit adds no compiler option. Setting it to
ONhas exactly one effect: it defines thepreprocessor macro
FPE_TRAP_ENABLED, which compiles out the body ofSet_IEEE_Constantsinthe
Sys*.f90layer.Two consequences:
-ffpe-trap(GFortran) or-fpe0(Intel) flagis added anywhere in the build system. A user who sets
-DFPE_TRAP_ENABLED=ONexpecting atrapping build gets an ordinary non-trapping build.
Set_IEEE_Constantsis the only place thatassigns
NaN_D,Inf_D,NaN,Inf,NaN_S,Inf_S. These are module variables inNWTC_Numwith no initializer, assigned once fromSetConstants. With the macro defined thewhole assignment block is
#ifndef-ed out, so they retain indeterminate values for the lifeof the run. The source comment acknowledges this: "note that anything that refers to NaN or
Inf will be incorrect in that case."
So the option as it stands removes the NaN/Inf definitions — the cost of a trapping build —
without delivering the trapping that would justify it. It is only correct if the user separately
supplies trapping flags through
CMAKE_Fortran_FLAGS, which is not what the option's help textdescribes.
To Reproduce
-DFPE_TRAP_ENABLED. No-ffpe-trapappears ineither;
grep -r ffpe-trapover the whole source and build trees returns nothing.Expected behavior
-DFPE_TRAP_ENABLED=ONshould produce a build that traps on floating-point exceptions, sincethat is what the option name and help string promise. Suppressing the NaN/Inf generation block
should be a consequence of trapping being enabled, not the entire behaviour.
Relevant code
CMakeLists.txt:43—option(FPE_TRAP_ENABLED "Enable FPE trap in compiler options" off)CMakeLists.txt:104-106— the option's only effect:modules/nwtc-library/src/SysGnuLinux.f90:298—#ifndef FPE_TRAP_ENABLEDaround the entirebody of
Set_IEEE_Constants. The same guard appears inSysGnuWin.f90:298,SysMatlabLinuxGnu.f90:301,SysIVF_Labview.f90:371andSysFlangLinux.f90:275.modules/nwtc-library/src/NWTC_Num.f90:33,35(and theReKi/SiKiequivalents) — thevariables are declared with no initializer.
modules/nwtc-library/src/NWTC_Num.f90:5478— the single call site, insideSetConstants.Impact
Low frequency, but silent when it bites. Anyone using the option for its stated purpose gets no
trapping, so the debugging session it was enabled for cannot work. Any code path that reads
NaN/Infin such a build reads an undefined value rather than the intended IEEE constant;these are referenced in
WAMIT2.f90andAeroDisk_IO.f90among others.There is also a forward-looking reason to fix it. PR #3464 introduces a build rule that uses
NOT FPE_TRAP_ENABLEDas a proxy for "this is not a trapping build", in order to decide whether-fno-trapping-mathis safe to apply to the OLAF kernels. That inference is only sound if theoption genuinely tracks trapping builds. As things stand, a user who enables trapping the
conventional way —
-DCMAKE_Fortran_FLAGS="-ffpe-trap=invalid,zero,overflow"without alsosetting
-DFPE_TRAP_ENABLED=ON— would get-fno-trapping-mathapplied anyway.Suggested fix
Either of the following would resolve it; the first matches the documented intent.
-ffpe-trap=invalid,zero,overflowfor GNU and-fpe0for Intel, alongside the existingadd_definitions. TheSys*.f90guard then does what its comment says it does.like
FPE_TRAP_COMPATIBLE, with help text stating that it only suppresses the NaN/Infgeneration and must be paired with user-supplied trapping flags.
In either case, it would help to have the build fail fast, or at least warn, when
-ffpe-trapappears in
CMAKE_Fortran_FLAGSwhileFPE_TRAP_ENABLEDisOFF, since that combinationcurrently produces a trapping build that still executes the deliberate divide-by-zero in
Set_IEEE_Constantsand will abort during initialization.OpenFAST Version
Reproduced on
devat386378cdb(v5.0.0-423-g386378cdb). The behaviour is long-standing,not a recent regression.
System Information
CMAKE_BUILD_TYPE=Release,DOUBLE_PRECISION=ONAdditional context
This is a build-system issue only; it does not affect results in any default build, since
FPE_TRAP_ENABLEDdefaults tooffand the NaN/Inf constants are then set correctly.