Array sliced by property of derived type

Array sliced by property of derived type

Samuel D.'s picture

Hello, I'm having a hard time understanding what is wrong with the following code that slices an array by property of derived type and I'm suspecting a compiler bug :

module crash
  type foo
    integer :: i
  end type foo
  type bar
    type(foo) :: foos(5)
  end type bar
contains
  subroutine print_foos(arg)
    type(foo), intent(in) :: arg(:)
    call print_int(arg%i)
  end subroutine print_foos
  subroutine print_int(arg)
    integer, intent(in) :: arg(:)
    integer :: i
    do i=lbound(arg, 1), ubound(arg, 1)
      print '(I)', arg(i)
    end do
  end subroutine print_int

end module crash

program crash_test
  use :: crash
  type(bar) :: a
  do i=lbound(a%foos, 1), ubound(a%foos, 1)
    a%foos(i)%i = i
  end do
  call print_int(a%foos%i) ! OK
  call print_foos(a%foos) ! KO
end program crash_test

The call to print_int correctly prints 1, 2, 3, 4, 5 while print_foos prints unitialized values (zeros). Am I doing anything non standard ? Note that the compiler does not complain nor ICE but gives IMHO wrong results.

Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 13.1.1.171 Build 20130313

Thank you for you help.

6 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Samuel D.'s picture

The same code compiled with gfortran 4.7.2 runs fine, so its seems to be an Intel fortran bug. Could anyone confirm this ? 

I should have say "component" rather than "property" in the title, sorry about that.

Steve Lionel (Intel)'s picture

It does look like a bug to me - we will investigate. Thanks.

Steve
Samuel D.'s picture

Hello Steve, thank you for your investigation. It's a pattern that I use surprisingly often in my code... My current workaround is to make a local copy of the data in the intermediate function (print_foos in my example code). If someone has a better one, I'd appreciate.

Steve Lionel (Intel)'s picture

I have escalated this as issue DPD200243231. I observed a few things. 1) This worked in 12.1.5 but broke in 13.0.0. 2) It seems to work fine when built for x64 (not IA-32). 3) It works if the dummy argument to print_int is not an assumed-shape array, but that's not a reasonable workaround.

Here is a more reasonable workaround that doesn't involve making a copy. Add an intermediate routine that takes an adjustable array, like this:

  subroutine print_foos(arg)
    type(foo), intent(in) :: arg(:)
    call print_ints(arg%i, size(arg))
  end subroutine print_foos
  subroutine print_ints(arg, n)
  integer, intent(in) :: n, arg(n)
  call print_int(arg)
  end subroutine print_ints

Lastly, in passing, I'll note that your lbound call will always return 1, no matter how the actual argument was declared in the caller. This is the way the language defines it with assumed-shape dummy arguments.

Steve
Steve Lionel (Intel)'s picture

We have fixed this for a release later this year.

Steve

Login to leave a comment.