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

--- Comment #4 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #0)

Sorry, my Fortran knowledge is practically non-existent.

Here's your example on Compiler Explorer:

  https://godbolt.org/z/86hrKedfe

> Take:
> ```
>   print *, foo_io()
> 
> contains
> 
>   function foo_io()
>     integer :: foo_io(2)
> 
>     print * , "foo"
>     foo_io = [42, 42]
>   end function
> 
> end
> ```
> 
> This currently hangs at runtime because it is violating the Fortran
> restriction on output statements. It would be interesting to have analyzer
> support to detect this case.
> 
> The IR:
> ```
> MAIN() {
> ...
>   dt_parm.6.common.unit = 6;
>   _gfortran_st_write (&dt_parm.6);
> ...
>   foo_io (&atmp.7); [static-chain: &FRAME.13];
> ...
>   _gfortran_st_write_done (&dt_parm.6);
> }
> 
> foo_io () {
> ...
>   dt_parm.0.common.unit = 6;
>   _gfortran_st_write (&dt_parm.0);
> }
> 
> ```

Am I correct in thinking that:
   _gfortran_st_write (&dt_parm.6);
blocks and acquires a lock on dt_parm.6.common.unit,
that:
  _gfortran_st_write_done (&dt_parm.6);
releases the lock on dt_parm.6.common.unit,

and thus we'd have something like:

MAIN() {
...
  _gfortran_st_write (&dt_parm.6);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  |
  (1) lock acquired here
...
  foo_io (&atmp.7); [static-chain: &FRAME.13];

within foo_io ():
...
  dt_parm.0.common.unit = 6;
  _gfortran_st_write (&dt_parm.0);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  |
  (2) deadlock; lock on unit 6 already acquired at (1)


If so, this could potentially implemented via a new state machine in
-fanalyzer, mapping "unit" values to a bool "locked" state, where a call to
_gfortran_st_write transitions the unit to "locked" and _gfortran_st_write_done
transitions it to "unlocked", and the default state is "unlocked".  Are there
other states or transitions that would be needed?

What would a warning ideally look like at the source level?

Reply via email to