Bug 56691 - [OOP] Allocatable array: wrong offset when passing to CLASS dummy
Summary: [OOP] Allocatable array: wrong offset when passing to CLASS dummy
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: 8.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2013-03-22 16:39 UTC by mrestelli
Modified: 2018-02-10 18:41 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.9.0, 5.4.1, 6.2.0
Last reconfirmed: 2013-03-23 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description mrestelli 2013-03-22 16:39:13 UTC
The attached code should display

Show: f1    1.0000000    
Show: f1    2.0000000    
Show: f1    3.0000000    
Show: f1    4.0000000   

three times - however the last call shows

Show: f1    2.0000000    
Show: f1    3.0000000    
Show: f1    4.0000000    
Show: f1    0.0000000    

i.e. all the array elements seem to be off by 1 (zero based
indexing?). Notice that:

1) the problem only shows up when the call to LCB uses array slices,
not when using the whole array

2) the problem disappears if the array WORK has explicit size.

I am using

gfortran --version
GNU Fortran (GCC) 4.9.0 20130322 (experimental)

Regards,
   Marco Restelli




module m1
 implicit none
 public :: c_stv
 private

 type, abstract :: c_stv
 contains
  procedure, pass(z) :: lcb
  procedure, pass(x) :: show
 end type c_stv

contains
 subroutine lcb(z,y)
  class(c_stv), intent(in) :: y(:)
  class(c_stv), intent(inout) :: z
  integer :: k
    write(*,*) 'Inside LCB: size is ',size(y)
    do k=1,size(y)
      call y(k)%show()
    enddo
 end subroutine lcb
 subroutine show(x)
  class(c_stv), intent(in) :: x
 end subroutine show
end module m1

module m2
 use m1, only: c_stv
 implicit none
 public :: t_stv
 private
 type, extends(c_stv) :: t_stv
  real :: f1
 contains
  procedure, pass(x) :: show
 end type t_stv
contains
 subroutine show(x)
  class(t_stv), intent(in) :: x
   write(*,*) 'Show: f1 ', x%f1
 end subroutine show
end module m2

program test
 use m1, only: c_stv
 use m2, only: t_stv

 implicit none

 integer :: k
 type(t_stv) :: x
 !type(t_stv) :: work(4) ! works fine
 type(t_stv), allocatable :: work(:)

  allocate(work(4))
  do k=1,4
    work(k)%f1 = real(k)
  enddo
  write(*,*) 'Values in work are:'
  do k=1,4
    call work(k)%show()
  enddo

  write(*,*) 'Call with whole array: works fine'
  call x%lcb(work)
  write(*,*) 'Call with array slice: off by 1'
  call x%lcb(work(:4))

end program test
Comment 1 carlo 2013-03-22 17:15:59 UTC
It does indeed look as if 0-based indexing is being erroneously used:

  call x%lcb(work(0:3))

prints:

 Call with array slice: off by 1
 Inside LCB: size is            4
 Show: f1    1.00000000    
 Show: f1    2.00000000    
 Show: f1    3.00000000    
 Show: f1    4.00000000
Comment 2 Tobias Burnus 2013-03-23 09:36:39 UTC
Interesting test case - it also fails with crayftn 8.1 and pgi 12.10 (for those: both calls), but works with ifort 13.0.

The whole array call has (-fdump-tree-original):
          work.dim[0].lbound = 1;
          work.offset = -1;
          class.6._data = work;
while for the failing, off-by-one call one has
          parm.9.dim[0].lbound = 1;
          parm.9.offset = 0;
          class.8._data = parm.9;
Due to offset == -1 vs. 0, the off-by-one error occurs.
Comment 3 janus 2013-03-23 13:10:41 UTC
Reduced test case which shows that the problem is CLASS-specific:


module m2
 implicit none
 type :: t_stv
  real :: f1
 end type
contains
 subroutine lcb(y)
  class(t_stv), intent(in) :: y(:)
   write(*,*) 'Inside LCB: size is ',size(y)
   print *,y(1:size(y))%f1
 end subroutine
end module

program test
 use m2
 implicit none

 type(t_stv), allocatable :: work(:)

  allocate(work(4))
  work(:)%f1 = (/ 1.,2.,3.,4./)
  write(*,*) 'Values in work are:'
  print *, work(1:4)%f1

  write(*,*) 'Call with whole array: works fine'
  call lcb(work)
  write(*,*) 'Call with array slice: off by 1'
  call lcb(work(:4))

end program


When making 'y' a TYPE instead of CLASS, the output is as expected.
Comment 4 physiker 2016-12-16 21:21:50 UTC
When I use gfortran version 7 to compile the code listed in comment 3, executing the resulting binary yields the following output:

./pr56691 
 Values in work are:
   1.00000000       2.00000000       3.00000000       4.00000000    
 Call with whole array: works fine
 Inside LCB: size is            4
   1.00000000       2.00000000       3.00000000       4.00000000    
 Call with array slice: off by 1
 Inside LCB: size is            4
   1.00000000       2.00000000       3.00000000       4.00000000

This is the expected result. The bug might be fixed.

LANG=C gfortran-7 -o pr56691 pr56691.f90 -v -W -Wall
Driving: gfortran-7 -o pr56691 pr56691.f90 -v -W -Wall -mmacosx-version-min=10.11.6 -asm_macosx_version_min=10.11 -l gfortran -shared-libgcc
Using built-in specs.
COLLECT_GCC=gfortran-7
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-apple-darwin15.6.0/7.0.0/lto-wrapper
Target: x86_64-apple-darwin15.6.0
Configured with: ../gcc/configure --enable-languages=c,c++,fortran,lto --with-gmp=/sw --with-libiconv-prefix=/sw --with-isl=/sw --with-mpc=/sw --with-system-zlib --program-suffix=-7
Thread model: posix
gcc version 7.0.0 20161215 (experimental) [trunk revision 243680] (GCC) 
COLLECT_GCC_OPTIONS='-o' 'pr56691' '-v' '-Wextra' '-Wall' '-mmacosx-version-min=10.11.6' '-asm_macosx_version_min=10.11' '-shared-libgcc' '-mtune=core2'
 /usr/local/libexec/gcc/x86_64-apple-darwin15.6.0/7.0.0/f951 pr56691.f90 -fPIC -quiet -dumpbase pr56691.f90 -mmacosx-version-min=10.11.6 -mtune=core2 -auxbase pr56691 -Wextra -Wall -version -fintrinsic-modules-path /usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0/finclude -o /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccv54gNH.s
GNU Fortran (GCC) version 7.0.0 20161215 (experimental) [trunk revision 243680] (x86_64-apple-darwin15.6.0)
	compiled by GNU C version 7.0.0 20161215 (experimental) [trunk revision 243680], GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version 0.15
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU Fortran2008 (GCC) version 7.0.0 20161215 (experimental) [trunk revision 243680] (x86_64-apple-darwin15.6.0)
	compiled by GNU C version 7.0.0 20161215 (experimental) [trunk revision 243680], GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version 0.15
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
COLLECT_GCC_OPTIONS='-o' 'pr56691' '-v' '-Wextra' '-Wall' '-mmacosx-version-min=10.11.6'  '-shared-libgcc' '-mtune=core2'
 as -arch x86_64 -v -force_cpusubtype_ALL -mmacosx-version-min=10.11 -o /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccSNEf1F.o /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccv54gNH.s
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
 "/Library/Developer/CommandLineTools/usr/bin/clang" -cc1as -triple x86_64-apple-macosx10.11.0 -filetype obj -main-file-name ccv54gNH.s -target-cpu core2 -fdebug-compilation-dir /Users/Peter/Devel/f90 -dwarf-debug-producer Apple LLVM version 8.0.0 (clang-800.0.42.1) -dwarf-version=2 -mrelocation-model pic -o /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccSNEf1F.o /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccv54gNH.s
Reading specs from /usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0/../../../libgfortran.spec
rename spec lib to liborig
COLLECT_GCC_OPTIONS='-o' 'pr56691' '-v' '-Wextra' '-Wall' '-mmacosx-version-min=10.11.6'  '-shared-libgcc' '-mtune=core2'
COMPILER_PATH=/usr/local/libexec/gcc/x86_64-apple-darwin15.6.0/7.0.0/:/usr/local/libexec/gcc/x86_64-apple-darwin15.6.0/7.0.0/:/usr/local/libexec/gcc/x86_64-apple-darwin15.6.0/:/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0/:/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/
LIBRARY_PATH=/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0/:/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0/../../../
COLLECT_GCC_OPTIONS='-o' 'pr56691' '-v' '-Wextra' '-Wall' '-mmacosx-version-min=10.11.6'  '-shared-libgcc' '-mtune=core2'
 /usr/local/libexec/gcc/x86_64-apple-darwin15.6.0/7.0.0/collect2 -dynamic -arch x86_64 -macosx_version_min 10.11.6 -weak_reference_mismatches non-weak -o pr56691 -L/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0 -L/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0/../../.. /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccSNEf1F.o -lgfortran -no_compact_unwind -lSystem -lgcc_ext.10.5 -lgcc -lquadmath -lm -lgcc_ext.10.5 -lgcc -lSystem -v
collect2 version 7.0.0 20161215 (experimental) [trunk revision 243680]
/usr/bin/ld -dynamic -arch x86_64 -macosx_version_min 10.11.6 -weak_reference_mismatches non-weak -o pr56691 -L/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0 -L/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0/../../.. /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccSNEf1F.o -lgfortran -no_compact_unwind -lSystem -lgcc_ext.10.5 -lgcc -lquadmath -lm -lgcc_ext.10.5 -lgcc -lSystem -v
@(#)PROGRAM:ld  PROJECT:ld64-274.2
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em (tvOS)
Library search paths:
	/usr/local/lib/gcc/x86_64-apple-darwin15.6.0/7.0.0
	/usr/local/lib
	/usr/lib
	/usr/local/lib
Framework search paths:
	/Library/Frameworks/
	/System/Library/Frameworks/
 /usr/bin/nm -n /var/folders/97/4qnhjhtn25s86s9hkz0h37_m0000gn/T//ccSNEf1F.o
Comment 5 janus 2016-12-16 22:15:56 UTC
(In reply to physiker from comment #4)
> When I use gfortran version 7 to compile the code listed in comment 3,
> executing the resulting binary yields the following output:
> 
> ./pr56691 
>  Values in work are:
>    1.00000000       2.00000000       3.00000000       4.00000000    
>  Call with whole array: works fine
>  Inside LCB: size is            4
>    1.00000000       2.00000000       3.00000000       4.00000000    
>  Call with array slice: off by 1
>  Inside LCB: size is            4
>    1.00000000       2.00000000       3.00000000       4.00000000
> 
> This is the expected result. The bug might be fixed.

Confirmed. In fact I see it working already in 6.2. It can definitely be closed.
Comment 6 Dominique d'Humieres 2016-12-16 22:25:42 UTC
The test in comment 0 is still giving an off by 1 result (7.0 at r243758):

 Call with array slice: off by 1
 Inside LCB: size is            4
 Show: f1    2.00000000    
 Show: f1    3.00000000    
 Show: f1    4.00000000    
 Show: f1    0.00000000
Comment 7 janus 2016-12-16 23:07:34 UTC
(In reply to Dominique d'Humieres from comment #6)
> The test in comment 0 is still giving an off by 1 result (7.0 at r243758):

Right, I missed that. Sorry for closing too early. Reduced test case for the remaining failure:


module m2
  implicit none
  type :: t_stv
    real :: f1
  end type
contains
  subroutine lcb(y)
    class(t_stv), intent(in) :: y(:)
    integer :: k
    write(*,*) 'Inside LCB: size is ',size(y)
    do k=1,size(y)
      write(*,*) 'f1: ', k, y(k)%f1
    enddo
  end subroutine
end module

program test
 use m2
 implicit none

 type(t_stv), allocatable :: work(:)

  allocate(work(4))
  work(:)%f1 = (/ 1.,2.,3.,4./)

  write(*,*) 'Call with whole array: works fine'
  call lcb(work)
  write(*,*) 'Call with array slice: off by 1'
  call lcb(work(:4))

end program


Prints:

 Call with whole array: works fine
 Inside LCB: size is            4
 f1:            1   1.00000000    
 f1:            2   2.00000000    
 f1:            3   3.00000000    
 f1:            4   4.00000000    
 Call with array slice: off by 1
 Inside LCB: size is            4
 f1:            1   2.00000000    
 f1:            2   3.00000000    
 f1:            3   4.00000000    
 f1:            4   0.00000000
Comment 8 Jakub Jelinek 2017-05-02 15:56:01 UTC
GCC 7.1 has been released.
Comment 9 Dominique d'Humieres 2018-01-27 00:37:42 UTC
*** Bug 84074 has been marked as a duplicate of this bug. ***
Comment 10 Dominique d'Humieres 2018-01-27 00:42:06 UTC
The test in comment 3 has likely been fixed by revision r222361 (pr60322).
Comment 11 Paul Thomas 2018-02-10 18:16:47 UTC
Author: pault
Date: Sat Feb 10 18:16:14 2018
New Revision: 257550

URL: https://gcc.gnu.org/viewcvs?rev=257550&root=gcc&view=rev
Log:
2018-02-10  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/84141
	PR fortran/84155
	* trans-array.c (gfc_array_init_size): Revert the change made
	in revision 257356 setting the dtype.
	* trans-types.c (gfc_get_dtype): Do not use the cached dtype.
	Call gfc_get_dtype_rank_type every time.

	PR fortran/56691
	* trans-array.c (gfc_conv_expr_descriptor): If the source array
	is a descriptor type, use its offset, removing the condition
	that is be a class expression.

2018-02-10  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/56691
	* gfortran.dg/type_to_class_4.f03: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/type_to_class_4.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-types.c
    trunk/gcc/testsuite/ChangeLog
Comment 12 Paul Thomas 2018-02-10 18:41:59 UTC
Fixed on trunk.

Thanks for the report, Marco.

Paul