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

            Bug ID: 71544
           Summary: gfortran compiler optimization bug when dealing with
                    c-style pointers
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: fortranbug at gmail dot com
  Target Milestone: ---

The code below produces different results with gfortran with -O1 as
compared with -O0, -O2, and -O3. We've tested this with gfortran
versions 4.8, 4.9, 5.2 and 5.3 and seen the same behavior in all
cases.  An even older version, 4.4.7 shipped with CentOS 6, works
as expected for all optimization levels.

A local pointer "a" in subroutine init() is used to allocate memory
and its location is stored in a c-pointer "cptr", which is saved
in a module.  An assignment "a=100" at the end of the init() routine
is apparently removed by the -O1 optimizer as dead code, but kept for
-O0, -O2 and -O3.   When it works (-O0, -O2, -O3), the initialization takes
effect and the program prints “100" in its second line.  When it doesn't (-O1),
it prints 0.

We discussed this behavior on comp.lang.fortran
   https://groups.google.com/forum/#!topic/comp.lang.fortran/wyMy8PqeVxA
and the consensus was that this is indeed an optimization bug.  The
bottom line is that there does not appear to be any reason in the
standard to expect that the data pointed to by ‘a' would become invalid
at the end of init(), and the compiler should detect that the call
to save_cptr() _can_ be creating an alias (and in fact it is), and
not treat the "a = 100" statement as dead code to be eliminated.
The specific parts of the standard that support this interpretation
are best summarized in Richard Maine's Jun 11 post in the
aforementioned  comp.lang.fortran thread.

---------------------------

module store_cptr
    use, intrinsic :: iso_c_binding
    implicit none
    public
    type(c_ptr), save :: cptr
end module store_cptr

subroutine init()
    use, intrinsic :: iso_c_binding
    implicit none
    integer(c_int), pointer :: a
    allocate(a)
    call save_cptr(c_loc(a))
    a = 100
end subroutine init

subroutine save_cptr(cptr_in)
    use store_cptr
    implicit none
    type(c_ptr), intent(in) :: cptr_in
    cptr = cptr_in
end subroutine save_cptr

program init_fails
    use store_cptr
    implicit none
    integer(c_int), pointer :: val
    call init()
    call c_f_pointer(cptr,val)
    print *,'The following line should print 100'
    print *,val
end program init_fails

---------------------------

Reply via email to