casting derived-type data with allocatable components

Here’s a code that attempts to do what the title says:

module Increments

  TYPE :: structure
    real s
    integer q
    real, allocatable :: flt1d(:)
  END TYPE structure

contains

  subroutine IncrementAndPrintReal(data)
    character(len=1) :: data(:)
    real             :: r
    r = transfer(data, r)
    r = r + 1.0 
    print *,r
    data = transfer(r, data)
  end subroutine

  subroutine IncrementAndPrintInteger(data)
    character(len=1) :: data(:) 
    integer          :: i    
    i = transfer(data, i)
    i = i + 1 
    print *,i
    data = transfer(i, data)
  end subroutine

  subroutine IncrementTenTimes(incrFunc, data)
    character(len=1) :: data(:) 
    integer :: i
    interface
      subroutine incrFunc(data)
        character(len=1) :: data(:) 
      end subroutine
    end interface
    do i = 1, 10 
      call incrFunc(data)
    enddo   
  end subroutine

  subroutine IncrementAndPrintStructure(data)
    character(len=1) :: data(:)
    type(structure) :: t0
    t0 = transfer(data, t0)
    print *, t0%flt1d
    t0%flt1d = t0%flt1d(1) + 1
    print*
    data = transfer(t0, data)
  end subroutine

end module

program main
  use Increments
  character(len=1), allocatable :: data(:) 
  integer                       :: lengthData
  real                          :: r = 5.0 
  integer                       :: i = 10
  type(structure)               :: t

  t%s = 1
  t%q = 2
  allocate(t%flt1d(11))
  t%flt1d = 3

  lengthData = size(transfer(r, data))
  allocate(data(lengthData))
  data = transfer(r, data)
  call IncrementTenTimes(IncrementAndPrintReal, data)
  deallocate(data)

  lengthData = size(transfer(i, data))
  allocate(data(lengthData))
  data = transfer(i, data)
  call IncrementTenTimes(IncrementAndPrintInteger, data)
  deallocate(data)

  lengthData = size(transfer(t, data))
  allocate(data(lengthData))
  data = transfer(t, data)
  call IncrementTenTimes(IncrementAndPrintStructure, data)
  deallocate(data)

end program

And here are the results for a few compilers:

ifort (v11.1 and v12.1.5):
==============


   6.000000    
   7.000000    
   8.000000    
   9.000000    
   10.00000    
   11.00000    
   12.00000    
   13.00000    
   14.00000    
   15.00000    
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
   3.000000       3.000000       3.000000       3.000000       3.000000    
   3.000000       3.000000       3.000000       3.000000       3.000000    
   3.000000    

  0.0000000E+00  0.0000000E+00   4.000000       4.000000       4.000000    
   4.000000       4.000000       4.000000       4.000000       4.000000    
   4.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    

  0.0000000E+00  0.0000000E+00   1.000000       1.000000       1.000000    
   1.000000       1.000000       1.000000       1.000000       1.000000    
   1.000000    



gfortran (gcc version 4.4.3):
=============================


   6.0000000    
   7.0000000    
   8.0000000    
   9.0000000    
   10.000000    
   11.000000    
   12.000000    
   13.000000    
   14.000000    
   15.000000    
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
   3.0000000       3.0000000       3.0000000       3.0000000       3.0000000       3.0000000       3.0000000       3.0000000       3.0000000       3.0000000       3.0000000    

  1.82795013E-38   0.0000000       4.0000000       4.0000000       4.0000000       4.0000000      1.54142831E-44  1.12103877E-44  2.80259693E-45   4.0000000       4.0000000    

*** glibc detected *** ./tr: double free or corruption (fasttop): 0x0000000000c70b20 ***
======= Backtrace: =========
/lib/libc.so.6(+0x77806)[0x7f9fb0e59806]
/lib/libc.so.6(cfree+0x73)[0x7f9fb0e600d3]
./tr[0x4010af]
./tr[0x401175]
./tr[0x40262e]
./tr[0x4026ea]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f9fb0e00c4d]
./tr[0x400a59]
======= Memory map: ========
00400000-00403000 r-xp 00000000 00:16 123                                /home/stefanos/Documents/dig/progs/other/transfer/tr
00602000-00603000 r--p 00002000 00:16 123                                /home/stefanos/Documents/dig/progs/other/transfer/tr
00603000-00604000 rw-p 00003000 00:16 123                                /home/stefanos/Documents/dig/progs/other/transfer/tr
00c70000-00c91000 rw-p 00000000 00:00 0                                  [heap]
7f9fac000000-7f9fac021000 rw-p 00000000 00:00 0 
7f9fac021000-7f9fb0000000 ---p 00000000 00:00 0 
7f9fb0de2000-7f9fb0f5c000 r-xp 00000000 08:01 5512795                    /lib/libc-2.11.1.so
7f9fb0f5c000-7f9fb115b000 ---p 0017a000 08:01 5512795                    /lib/libc-2.11.1.so
7f9fb115b000-7f9fb115f000 r--p 00179000 08:01 5512795                    /lib/libc-2.11.1.so
7f9fb115f000-7f9fb1160000 rw-p 0017d000 08:01 5512795                    /lib/libc-2.11.1.so
7f9fb1160000-7f9fb1165000 rw-p 00000000 00:00 0 
7f9fb1165000-7f9fb117b000 r-xp 00000000 08:01 5505258                    /lib/libgcc_s.so.1
7f9fb117b000-7f9fb137a000 ---p 00016000 08:01 5505258                    /lib/libgcc_s.so.1
7f9fb137a000-7f9fb137b000 r--p 00015000 08:01 5505258                    /lib/libgcc_s.so.1
7f9fb137b000-7f9fb137c000 rw-p 00016000 08:01 5505258                    /lib/libgcc_s.so.1
7f9fb137c000-7f9fb13fe000 r-xp 00000000 08:01 5505028                    /lib/libm-2.11.1.so
7f9fb13fe000-7f9fb15fd000 ---p 00082000 08:01 5505028                    /lib/libm-2.11.1.so
7f9fb15fd000-7f9fb15fe000 r--p 00081000 08:01 5505028                    /lib/libm-2.11.1.so
7f9fb15fe000-7f9fb15ff000 rw-p 00082000 08:01 5505028                    /lib/libm-2.11.1.so
7f9fb15ff000-7f9fb16ea000 r-xp 00000000 08:01 787983                     /usr/lib/libgfortran.so.3.0.0
7f9fb16ea000-7f9fb18e9000 ---p 000eb000 08:01 787983                     /usr/lib/libgfortran.so.3.0.0
7f9fb18e9000-7f9fb18ea000 r--p 000ea000 08:01 787983                     /usr/lib/libgfortran.so.3.0.0
7f9fb18ea000-7f9fb18eb000 rw-p 000eb000 08:01 787983                     /usr/lib/libgfortran.so.3.0.0
7f9fb18eb000-7f9fb18ec000 rw-p 00000000 00:00 0 
7f9fb18ec000-7f9fb190c000 r-xp 00000000 08:01 5512780                    /lib/ld-2.11.1.so
7f9fb1ad9000-7f9fb1add000 rw-p 00000000 00:00 0 
7f9fb1b09000-7f9fb1b0b000 rw-p 00000000 00:00 0 
7f9fb1b0b000-7f9fb1b0c000 r--p 0001f000 08:01 5512780                    /lib/ld-2.11.1.so
7f9fb1b0c000-7f9fb1b0d000 rw-p 00020000 08:01 5512780                    /lib/ld-2.11.1.so
7f9fb1b0d000-7f9fb1b0e000 rw-p 00000000 00:00 0 
7fff5e340000-7fff5e356000 rw-p 00000000 00:00 0                          [stack]
7fff5e396000-7fff5e397000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted



pgfortran (v12.5):
==================


    6.000000    
    7.000000    
    8.000000    
    9.000000    
    10.00000    
    11.00000    
    12.00000    
    13.00000    
    14.00000    
    15.00000    
           11
           12
           13
           14
           15
           16
           17
           18
           19
           20
    3.000000        3.000000        3.000000        3.000000     
    3.000000        3.000000        3.000000        3.000000     
    3.000000        3.000000        3.000000    

    4.000000        4.000000        4.000000        4.000000     
    4.000000        4.000000        4.000000        4.000000     
    4.000000        4.000000        4.000000    

    5.000000        5.000000        5.000000        5.000000     
    5.000000        5.000000        5.000000        5.000000     
    5.000000        5.000000        5.000000    

    6.000000        6.000000        6.000000        6.000000     
    6.000000        6.000000        6.000000        6.000000     
    6.000000        6.000000        6.000000    

    7.000000        7.000000        7.000000        7.000000     
    7.000000        7.000000        7.000000        7.000000     
    7.000000        7.000000        7.000000    

    8.000000        8.000000        8.000000        8.000000     
    8.000000        8.000000        8.000000        8.000000     
    8.000000        8.000000        8.000000    

    9.000000        9.000000        9.000000        9.000000     
    9.000000        9.000000        9.000000        9.000000     
    9.000000        9.000000        9.000000    

    10.00000        10.00000        10.00000        10.00000     
    10.00000        10.00000        10.00000        10.00000     
    10.00000        10.00000        10.00000    

    11.00000        11.00000        11.00000        11.00000     
    11.00000        11.00000        11.00000        11.00000     
    11.00000        11.00000        11.00000    

    12.00000        12.00000        12.00000        12.00000     
    12.00000        12.00000        12.00000        12.00000     
    12.00000        12.00000        12.00000

The PGI compiler shows the desired behaviour, but the code is clearly non-trivial. I am trying to understand why this is so and what the standard-conforming behaviour is.

On a more general note, I was wondering it there is any other way to pass derived-type variables with allocatable components to a procedure, without the procedure knowing the type definition.

Can anyone help?

Hi delete000,

We took a look at your code and didn’t find anything illegal. Though, you may investigate to instead use unlimited polymorphic objects ( e.g., class(*) ) to allow them to pass an object to a procedure without the procedure knowing what the type is. This can also work for allocatables.

For example

subroutine foo(this)
class(*), allocatable :: this
:
end subroutine

Though, you may want to determine the type using the “select type” construct

For example,

subroutine foo(this)
class(*), allocatable :: this

select type(this)
type is (integer)
    ! integer specific code
type is(real)
    ! real specific code
type is (complex)
   ! complex specific code
class is (my_type)
   ! code for derived type "my_type" and all of its type extensions
class default
   ! default case - any other type executes this code
end select

end subroutine

For additional examples and more details about these constructs, please take a look at the PGInsider articles Object-Oriented Programming in Fortran 2003 Part 1: Code Reusability and Object-Oriented Programming in Fortran 2003 Part 2: Data Polymorphism.

Best Regards,
Mat

Hi Mat,

thanks, this seems to be exactly what I’m looking for.

delete000