Bug 48279

Summary: [4.6/4.7 Regression] segfault in gfc_check_vardef_context
Product: gcc Reporter: Adrian Prantl <adrian>
Component: fortranAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: adrian, burnus, jakub, janus, kargls
Priority: P4 Keywords: ice-on-invalid-code
Version: 4.6.0   
Target Milestone: 4.6.1   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48776
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2011-03-24 23:58:42
Attachments: Draft patch for the main issue and for the -std=f2003/f2008 diagnostic

Description Adrian Prantl 2011-03-24 23:03:55 UTC
I have found gfortran 4.6-rc2 (and also svn r171355) to segfault in gfc_check_vardef_context().
The code spans over 3 modules, but I used delta to come up with the following minimal example: 

$ cat sidl_string_array.F03

module sidl_string_array
  type sidl_string_1d
  end type sidl_string_1d
  interface set
    module procedure &
      setg1_p
  end interface
contains
  subroutine setg1_p(array, index, val)
    type(sidl_string_1d), intent(inout) :: array
  end subroutine setg1_p
end module sidl_string_array

$ cat s_Hard.F03
module s_Hard
  use sidl_string_array
  type, bind(c) :: s_Hard_t
  end type s_Hard_t
  interface set_d_interface
  end interface 
  interface get_d_string
    module procedure get_d_string_p
  end interface 
  contains ! Derived type member access functions
    type(sidl_string_1d) function get_d_string_p(s)
      type(s_Hard_t), intent(in) :: s
    end function get_d_string_p
    subroutine set_d_objectArray_p(s, d_objectArray)
    end subroutine set_d_objectArray_p
end module s_Hard

$ cat main.F03 
  subroutine initHard(h, ex)
    use s_Hard
    type(s_Hard_t), intent(inout) :: h
    call set(get_d_string(h), 0, 'Three')
  end subroutine initHard

$ gfortran -c sidl_string_array.F03 -o sidl_string_array.o
$ gfortran -c s_Hard.F03 -o s_Hard.o
s_Hard.F03:3.27:

  type, bind(c) :: s_Hard_t
                           1
Warning: Derived type 's_hard_t' with BIND(C) attribute at (1) is empty, and may be inaccessible by the C companion processor

$ gfortran main.F03
f951: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Comment 1 Adrian Prantl 2011-03-24 23:06:21 UTC
Sorry, I forgot to mention that the machine was an x86_64 with Ubuntu 10.04.
Comment 2 Dominique d'Humieres 2011-03-24 23:58:42 UTC
There is a change of behavior between revisions 166533 and 167096. At revisions 4.5.2 and 166533 one gets:

pr48279.f90:16.27:

  type, bind(c) :: s_Hard_t
                           1
Error: Derived type 's_hard_t' at (1) is empty
pr48279.f90:32.14:

    use s_Hard
              1
Fatal Error: Can't open module file 's_hard.mod' for reading at (1): No such file or directory

The change is likely due to revision 166633.
Comment 3 Adrian Prantl 2011-03-25 00:06:15 UTC
(In reply to comment #2)
> There is a change of behavior between revisions 166533 and 167096. At revisions
> 4.5.2 and 166533 one gets:
> 
> pr48279.f90:16.27:
> 
>   type, bind(c) :: s_Hard_t
>                            1
> Error: Derived type 's_hard_t' at (1) is empty
> pr48279.f90:32.14:
> 
>     use s_Hard
>               1
> Fatal Error: Can't open module file 's_hard.mod' for reading at (1): No such
> file or directory
> 
> The change is likely due to revision 166633.
 
feel free to use 

module s_Hard
  use sidl_string_array
  use iso_c_binding
  type, bind(c) :: s_Hard_t
     integer(kind=c_int) :: dummy
  end type s_Hard_t
  interface set_d_interface
  end interface 
  interface get_d_string
    module procedure get_d_string_p
  end interface 
  contains ! Derived type member access functions
    type(sidl_string_1d) function get_d_string_p(s)
      type(s_Hard_t), intent(in) :: s
    end function get_d_string_p
    subroutine set_d_objectArray_p(s, d_objectArray)
    end subroutine set_d_objectArray_p
end module s_Hard

instead. It shouldn't complain.
Comment 4 Adrian Prantl 2011-03-25 18:59:48 UTC
It is actually possible to combine the test into a single file:

minimal.F03

module sidl_string_array
  type sidl_string_1d
  end type sidl_string_1d
  interface set
    module procedure &
      setg1_p
  end interface
contains
  subroutine setg1_p(array, index, val)
    type(sidl_string_1d), intent(inout) :: array
  end subroutine setg1_p
end module sidl_string_array
module s_Hard
  use sidl_string_array
  type :: s_Hard_t
     integer(8) :: dummy
  end type s_Hard_t
  interface set_d_interface
  end interface 
  interface get_d_string
    module procedure get_d_string_p
  end interface 
  contains ! Derived type member access functions
    type(sidl_string_1d) function get_d_string_p(s)
      type(s_Hard_t), intent(in) :: s
    end function get_d_string_p
    subroutine set_d_objectArray_p(s, d_objectArray)
    end subroutine set_d_objectArray_p
end module s_Hard

subroutine initHard(h, ex)
  use s_Hard
  type(s_Hard_t), intent(inout) :: h
  call set(get_d_string(h), 0, 'Three')
end subroutine initHard

$ gfortran -c minimal.F03
minimal.F03:26:0: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Comment 5 Tobias Burnus 2011-03-28 08:13:02 UTC
(In reply to comment #4)
>   call set(get_d_string(h), 0, 'Three')

With NAG and with GCC 4.5 (and 4.3/4.4) I get the error that no specific function could be found. Thus, I mark this PR now as regression and ICE-on-invalid-code. I have not checked whether the other examples are valid or not.
Comment 6 Tobias Burnus 2011-03-28 13:21:30 UTC
==1823== Invalid read of size 1
==1823==    at 0x4C32E7: gfc_check_vardef_context (expr.c:4377)
==1823==    by 0x4CBC25: compare_actual_formal (interface.c:2291)
==1823==    by 0x4CD48B: gfc_arglist_matches_symbol (interface.c:2813)
==1823==    by 0x4CD6F4: gfc_search_interface (interface.c:2842)
==1823==    by 0x50D2A2: resolve_call (resolve.c:3204)

The issue - or at least cause - for the segfault is the following code in gfc_check_vardef_context:

  if (!pointer && e->expr_type == EXPR_FUNCTION
      && e->symtree->n.sym->result->attr.pointer)

The problem is that e->symtree->n.sym->result == NULL. The symbol itself is "get_d_string". If one uses gdb's "set e->symtree->n.sym->result = e->symtree->n.sym" and continues, one gets the expected error:

  Error: There is no specific subroutine for the generic 'set' at (1)

One problem seems to be that "get_d_string" is a generic interface - and not a specific one:

(gdb) p e->symtree->n.sym->attr.generic
$1 = 1

The specific interface has properly the result variables set:
(gdb) p e->symtree->n.sym->generic->sym->name
$3 = 0x2aaaae876280 "get_d_string_p"
(gdb) p e->symtree->n.sym->generic->sym->result
$4 = (struct gfc_symbol *) 0x1281280

Calling gfc_check_vardef_context for an generic interface seems to be questionable.
Comment 7 janus 2011-03-28 20:39:53 UTC
Reduced/modified test case:


  interface get
    procedure get1
  end interface

  integer :: h
  call set1 (get (h))

contains

  subroutine set1 (a)
    integer, intent(inout) :: a
  end subroutine

  integer function get1 (s)
    integer :: s
  end function

end
Comment 8 Tobias Burnus 2011-03-29 06:26:50 UTC
(In reply to comment #7)
>   call set1 (get (h))

>   subroutine set1 (a)
>     integer, intent(inout) :: a

If one changes the (invalid) INOUT to IN, it compiles.

 * * *

Additionally, for the modified program, I think NAG is correct with the following error - gfortran just compiles it:

   Error: GET1 in generic GET is an internal procedure

From F2008, "12.4.3.4.1 Generic identifiers":
"The PROCEDURE statement lists procedure pointers, external procedures, dummy procedures, or module procedures that have this generic interface."

(However, g95, pgf95 and crayftn also compile it, thus, I might misread F2008.)
Comment 9 Tobias Burnus 2011-04-26 13:36:50 UTC
Works with: 2010-09-28-r164677
Comment 10 Tobias Burnus 2011-04-26 17:06:03 UTC
       Works: 2010-10-15-r165507 (a5b23678e24cec2da289a54ae62f98f7b1301c36)
       Fails: 2010-10-23-r165882 (2dfbcd30bb4e761a9c5144a0656b8dfc6336ed37)
Comment 12 Tobias Burnus 2011-04-26 18:46:15 UTC
Created attachment 24106 [details]
Draft patch for the main issue and for the -std=f2003/f2008 diagnostic

The regression is caused by:

New Revision: 165749
URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=165749
2010-10-21  Tobias Burnus  <burnus@net-b.de>

        PR fortran/46100
        * expr.c (gfc_check_vardef_context): Treat pointer functions
        as variables.

That patch itself was OK - however, generic interfaces were not honoured.

 * * *

Attached is a draft patch for this issue and for the -std=f2003/f2008 diagnostic for comment 7 (cf. comment 8).

 * * *

Using -std=f95, the test case in comment 7 segfaults; I have not checked whether it is due to using an old gfortran (Rev. 165749) - nor whether it is a regression.  This issue is tracked in PR 48776.
Comment 13 Tobias Burnus 2011-04-28 05:48:23 UTC
Author: burnus
Date: Thu Apr 28 05:48:18 2011
New Revision: 173059

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173059
Log:
2011-04-28  Tobias Burnus  <burnus@net-b.de>

        PR fortran/48112
        * resolve.c (resolve_fl_var_and_proc): Print diagnostic of
        function results only once.
        (resolve_symbol): Always resolve function results.

        PR fortran/48279
        * expr.c (gfc_check_vardef_context): Fix handling of generic
        EXPR_FUNCTION.
        * interface.c (check_interface0): Reject internal functions
        in generic interfaces, unless -std=gnu.

2011-04-28  Tobias Burnus  <burnus@net-b.de>

        PR fortran/48112
        PR fortran/48279
        * gfortran.dg/interface_35.f90: New.
        * gfortran.dg/erfc_scaled_1.f90: Don't compile with -pedantic.
        * gfortran.dg/func_result_6.f90: Add dg-warning.
        * gfortran.dg/bessel_1.f90: Ditto.
        * gfortran.dg/hypot_1.f90: Ditto.
        * gfortran.dg/proc_ptr_comp_20.f90: Ditto.
        * gfortran.dg/proc_ptr_comp_21.f90: Ditto.
        * gfortran.dg/interface_assignment_4.f90: Ditto.


Added:
    trunk/gcc/testsuite/gfortran.dg/interface_35.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/bessel_1.f90
    trunk/gcc/testsuite/gfortran.dg/erfc_scaled_1.f90
    trunk/gcc/testsuite/gfortran.dg/func_result_6.f90
    trunk/gcc/testsuite/gfortran.dg/hypot_1.f90
    trunk/gcc/testsuite/gfortran.dg/interface_assignment_4.f90
    trunk/gcc/testsuite/gfortran.dg/proc_ptr_comp_20.f90
    trunk/gcc/testsuite/gfortran.dg/proc_ptr_comp_21.f90
Comment 14 Tobias Burnus 2011-04-28 18:47:31 UTC
Author: burnus
Date: Thu Apr 28 18:47:28 2011
New Revision: 173127

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173127
Log:
2011-04-28  Tobias Burnus  <burnus@net-b.de>

        PR fortran/48112
        * resolve.c (resolve_fl_var_and_proc): Print diagnostic of
        function results only once.
        (resolve_symbol): Always resolve function results.

        PR fortran/48279
        * expr.c (gfc_check_vardef_context): Fix handling of generic
        EXPR_FUNCTION.
        * interface.c (check_interface0): Reject internal functions
        in generic interfaces, unless -std=gnu.

2011-04-28  Tobias Burnus  <burnus@net-b.de>

        PR fortran/48112


Added:
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/interface_35.f90
Modified:
    branches/gcc-4_6-branch/gcc/fortran/ChangeLog
    branches/gcc-4_6-branch/gcc/fortran/expr.c
    branches/gcc-4_6-branch/gcc/fortran/interface.c
    branches/gcc-4_6-branch/gcc/fortran/resolve.c
    branches/gcc-4_6-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/bessel_1.f90
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/erfc_scaled_1.f90
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/func_result_6.f90
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/hypot_1.f90
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/interface_assignment_4.f90
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/proc_ptr_comp_20.f90
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/proc_ptr_comp_21.f90
Comment 15 Tobias Burnus 2011-04-28 18:48:20 UTC
Fixed on the trunk (4.7) and on the 4.6 branch.

Thanks for the report!