https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125458

--- Comment #11 from Steve Kargl <kargl at gcc dot gnu.org> ---
(In reply to Thomas Koenig from comment #9)
> I have found this to be deep regression country.
> 
> One problem that I see is that the arith* functions are called both
> during matching and during resolution, and they should be doing
> somewhat different things upon encountering an error.  I've toyed
> with the idea of putting in a global variable which states which
> phase we are currently in (matching, resolution, front-end optimization
> and translation) and handling errors differently based on that,
> but I don't have the time for that at the moment.
> 
> Steve, maybe you have an idea?

Just spent an hour or 2 tracing through the parsing.
At some point, arith.cc(is_hard_arith_error) is called
and it it considered to be a *not hard error* so
gfortran accepts the resulting multiplication.  This
occurs even if -frange-check is specified on the command
line.

(gdb) n
869       return check_result (rc, op1, result, resultp);
(gdb) p rc
$8 = ARITH_OVERFLOW

We see rc=ARITH_OVERFLOW and

(gdb) s
check_result (rc=ARITH_OVERFLOW, x=0x804413c40, r=0x804413e00,
rp=0x7fffffffdad8)
    at ../../gcc/gcc/fortran/arith.cc:662
662       if (val == ARITH_UNDERFLOW)
(gdb) 
669       if (val == ARITH_ASYMMETRIC)
(gdb) 
675       if (is_hard_arith_error (val))
(gdb) s
is_hard_arith_error (code=ARITH_OVERFLOW) at ../../gcc/gcc/fortran/arith.cc:156
156       switch (code)
(gdb) s
check_result (rc=<optimized out>, x=<optimized out>, r=<optimized out>, 
    rp=<optimized out>) at ../../gcc/gcc/fortran/arith.cc:678
678         *rp = r;

this is where gfortran accepts the result of the multiplication.

(gdb) s
680       return val;
(gdb) p val
$9 = <optimized out>
(gdb) n
eval_intrinsic (op=op@entry=INTRINSIC_TIMES, eval=eval@entry=..., 
    op1=0x804413c40, op2=0x804413d20) at ../../gcc/gcc/fortran/arith.cc:1964
1964      if (rc == ARITH_INVALID_TYPE || rc == ARITH_NOT_REDUCED)
(gdb) p rc
$10 = ARITH_OVERFLOW
(gdb) call debug(result)
28958985279684 (INTEGER 4)

The finger points at Harald.

commit 93e1d4d24ed014387da97e2ce11556d68fe98e66
Author:     Harald Anlauf <[email protected]>
AuthorDate: Tue Mar 5 21:54:26 2024 +0100
Commit:     Harald Anlauf <[email protected]>
CommitDate: Wed Mar 6 17:55:36 2024 +0100

    Fortran: error recovery while simplifying expressions [PR103707,PR106987]

    When an exception is encountered during simplification of arithmetic
    expressions, the result may depend on whether range-checking is active
    (-frange-check) or not.  However, the code path in the front-end should
    stay the same for "soft" errors for which the exception is triggered by the
    check, while "hard" errors should always terminate the simplification, so
    that error recovery is independent of the flag.  Separation of arithmetic
    error codes into "hard" and "soft" errors shall be done consistently via
    is_hard_arith_error().

If I force is_hard_arith_error() to return true, which rejects the
result, I get an ICE.  :(  This is likely a NULL dereference of a
freed expr->where.

Reply via email to