Bug 98890 - ICE on reference to module function
Summary: ICE on reference to module function
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 11.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-invalid-code
Depends on:
Blocks:
 
Reported: 2021-01-29 13:34 UTC by Jakub Jelinek
Modified: 2021-02-19 17:22 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-02-04 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2021-01-29 13:34:01 UTC
gfortran ICEs on the following testcase:

module foo
contains
  real function bar(x)
    real :: x(2,2)
    bar=baz*x(1,1)
  end function bar      
  real function baz(x)
    real :: x(2,2)
    baz=x(1,1)
  end function baz      
end module foo

Doesn't say anything even with implicit none, so maybe it is ok that baz lookup gives the module function rather than a local variable, but shouldn't something complain that it refers to the module function in an invalid way (rather than say calling it)?  Originally this was reported due to a typo (the baz* should have been bar* ).
If baz returns some incompatible type such as integer, then an error is diagnosed.
Comment 1 Jakub Jelinek 2021-01-29 13:42:49 UTC
Seems the ICE is quite long, seems before around (+- 25 revisions) r137400 gfortran ICEd in the FE:
internal compiler error: in gfc_conv_variable, at fortran/trans-expr.c:483
and after that it ICEs in gimple verification, as the multiplication has operand with invalid type.
Comment 2 Dominique d'Humieres 2021-02-04 11:03:35 UTC
With --enable-checking=yes I get

pr98890.f90:3:19:

    3 |   real function bar(x)
      |                   ^
Error: type mismatch in binary expression
real(kind=4)

real(kind=4)

real(kind=4) (*<T5e4>) (real(kind=4)[4] * restrict)

_2 = _1 * baz;
pr98890.f90:3:19: internal compiler error: 'verify_gimple' failed

With --enable-checking=release and GCC8 to 11, I get

    5 |     bar=baz*x(1,1)
      |                  ^
internal compiler error: in convert_mode_scalar, at expr.c:314

For GCC7 I get

internal compiler error: in convert_move, at expr.c:229
Comment 3 Tobias Burnus 2021-02-05 11:43:19 UTC
Likewise for the following, which uses an assignment:

  implicit none
contains
  real function bar(x)
    real :: x(2,2)
    bar = bar          ! OK
    bar = baz          ! ERROR: function name not reference
    bar = get_funptr() ! ERROR: proc-pointer returning function

    bar = bar * x(1,1) ! OK
    bar = baz * x(1,1) ! error - as above but as operator
    bar = get_funptr() * x(1,1) ! likewise
  end function bar      
  function get_funptr() result(ptr)
    procedure(bar), pointer :: ptr
    ptr => bar
  end
  real function baz(x) result(bazr)
    real :: x(2,2)
    bazr=x(1,1)
  end function baz      
end module foo

  * * *

I am not sure whether the problem is that expr_type == EXPR_VARIABLE instead of expr_type == EXPR_FUNCTION
or whether the proper fix should be inside both resolve_ordinary_assign() and resolve_operator() a check like:

  symbol_attribute rhs_attr = gfc_expr_attr (rhs);
  if (rhs_attr.function && ...)
    {
      gfc_error ("Unexpected function name at %L", &rhs->where);
      return false;
    }
  if (rhs_attr.proc_pointer)
    {
      gfc_error ("Unexpected procedure pointer at %L", &rhs->where);
      return false;
    }

where "..." detects that the rhs may be used as result name in this context.

This check always confuses me. And a quick try failed:

I tried rhs_attr – but it is identical for 'bar' and baz'; and also 'sym->result = sym' is the same (if changing 'baz' to use no result variable). I also thought about the namespace but thanks to BLOCK and contained procedures (which may access their parent's result variable) it is not that simple.

 * * *

I have not checked but, e.g., for 'call foo(baz)' a similar issue may pop up. I think not occurring, but to check: proc_pointer_comp (should be resolved already at parse time?) and derived-type procedures returning proc pointers (same check as for other functions).
Comment 4 Tobias Burnus 2021-02-19 16:10:43 UTC
Related issue but without an ICE:

   contains
      integer function f1()
        !f2 = 1   ! gives an error as expected
        j = f2    ! <<<< accepted; cast of function addr to integer(kind=4)
        f1 = 1    ! ↑ ifort: 'already been used as an external function name'
      end function
      integer function f2()
        f2=1
      end function
   end
Comment 5 Jerry DeLisle 2021-02-19 16:47:09 UTC
(In reply to Tobias Burnus from comment #4)
> Related issue but without an ICE:
> 
>    contains
>       integer function f1()
>         !f2 = 1   ! gives an error as expected
>         j = f2    ! <<<< accepted; cast of function addr to integer(kind=4)
>         f1 = 1    ! ↑ ifort: 'already been used as an external function name'
>       end function
>       integer function f2()
>         f2=1
>       end function
>    end

A variation with a question:

program p1
  implicit none
  integer j, k
  j = 99
  k = f1()
  print *, j, k
contains  
  integer function f1()
    !f2 = 1
    j = f2  ! Should this be warned or rejected?
    print *, j
    f1 = 1  ! This should not be rejected
  end function
  integer function f2()
    f2=1
  end function
end
Comment 6 Jerry DeLisle 2021-02-19 17:22:22 UTC
I should have noted in the above case, if we remove the parens on line 5,

   k = f1 is rejected.