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
---