<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/122216>122216</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [Flang] `transfer` of a derived type with a pointer component
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            flang:runtime
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          kawashima-fj
      </td>
    </tr>
</table>

<pre>
    When an object of a derived type with a pointer component is used as source of the `transfer` function, the result object has a size of the pointee but contains the pointer address .

```fortran
    type :: box
        type(data), pointer :: ptr
    end type

    type(box) :: box1

    dest = transfer(box1, dest)
```

Full reproducer:

```fortran
program main

 use, intrinsic :: iso_c_binding
    use, intrinsic :: iso_fortran_env
 implicit none

    type :: data
        integer(kind=4), dimension(10) :: array
    end type

    type :: box
        type(data), pointer :: ptr
 end type

    integer :: i, len
    integer(kind=4), pointer :: ptr1
 type(data), target :: data1
    type(box) :: box1
    integer(kind=4), dimension(:), allocatable :: dest

    do i = 1, 10
        data1%array(i) = i
    end do
    box1%ptr => data1
    len = size(transfer(box1, dest))
    allocate(dest(len))
    dest = transfer(box1, dest)

 write(6, *) '# len'
    write(6, '(I4)') len
    write(6, *) '# ptr1 data1 box1'
    write(6, '(I4)') storage_size(ptr1)
    write(6, '(I4)') storage_size(data1)
    write(6, '(I4)') storage_size(box1)
    write(6, *) '# transfer'
    write(6, '(I4)') storage_size(transfer(box1, dest))
 write(6, '(I4)') size(transfer(box1, dest))
    write(6, *) '# dest'
 write(6, '(I4)') storage_size(dest)
    write(6, '(I4)') size(dest)
 write(6, *) '# data1'
    write(*, '(Z17.16)') transfer(c_loc(data1), 0_int64)
    write(6, *) '# array'
    do i = 1, len
        write(*, '(Z9.8)') dest(i)
    end do

end program
```

Output of Flang (20.0.0git f4230b4332262dffb0bd3b7a2f8d6deb2e96488e) on AArch64:

```
 # len                 
  10                   
 # ptr1 data1 box1     
 32
 320
 320  **(3)**
 # transfer
  32
  10
 # dest
  32
  10 **(1)**
 # data1
 0000AAAACC920580
 # array
 CC920580  **(2)**
 0000AAAA **(2)**
 00000028
 00000000
 0134D94F
 01012A00
 CC91E7D0
 0000AAAA
 00000000
 00000000
```

Please see (1) and (2). (1) `size(transfer(box1, dest))` is 10, which is the size of the pointee array. (2) `dest(1)`+`dest(2)` is an address.

Output of GFortran (13.2.0) on AArch64:

```
 # len
   2
 # ptr1 data1 box1
  32
 320
  64 **(3)**
 # transfer
  32
   2  **(1)**
 # dest
  32
   2
 # data1
 0000FFFFF67F9728
 # array
 F67F9728  **(2)**
 0000FFFF  **(2)**
```

In GFortran, (1) `size(transfer(box1, dest))` is 64, which is the size of an address.

The Fortran standards defines:

> **Result Value.** If the physical representation of the result has the same length as that of SOURCE, the physical representation of the result is that of SOURCE.

Though I don't know what "physical representation" exactly means, the result of GFortran seems correct. At least, the current result of Flang is inconsistent (size is that of pointee but content is a pointer).

Also, (3) `storage_size(box1)` differs. Flang includes the pointee but GFortran includes only the pointer itself.

</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJykWElv27oW_jX05qACRdkaFl6odvyQVR_6hgvcTUBLRzZbmTJIKmnur7_goCF24rq9QZDIPPN3PlI85lqLg0Rck9VnstoueG-OnVp_5y9cH8WJf2q-LfZd_br-44gSuIRu_w0rA10DHGpU4hlrMK9nhBdhjsDh3AlpUEHVnc6dRGlAaOg11sA16K5XFVpjc0QgKTWKS92gIimFppeVEZ0kbOPECnXfmiHgkWvgoMVfo7mPhLDvDVSdNFxIPRMo4HWtUGuICC3tb0r9b9MpG5fQEgB88iQpSVLCvvsRVgcJYXnNDSessGkNnoP62aigjtKj4CPNjK1HVsz8x5NKjdoASbYwouD0YxvJymzQWdrecNe3LSg8q67uK1TW8UfVnVV3UPwEJy5kiNprtN6FNEpILaohMaG7p-ppL2Qt5CGkd0s3BHlC-Wy1xencikoYkJ28wGCwcihO2FocD67i70LWJNkuA8S1OKHUjgZ5TGfYcaX46024_1kXr32GHMe6rW2L8q30uoJr97bn7-RhuDqgmQMU30Geu9GzZn6Vt21XccP37dQOy6-JiR0Ix0THvZjO4PNpsZWHn-XCZ7QFMetF3YUPnr6rs7Hlb0ny8KasFqUztbuYsPwG7R3zrUlI3SHnZLntwFzjzl1ES3hRwjlKrYiw0lXCMsIS11aWBY8Xehlh-aMHOLMmEwVuOLRd97UHTO50rk2n-AGfAkSOPGOpv2YbOvd7xj7pD2znhU6o_16FPyXBz9zdz6UbVXjd7J54FyCPDLun9CubWyn59l2i6pQG53_GWRSnU4AZCtVT21VzFrAN0CchTbq8C5Gw37N3T4hpC3ycWhHlU2Jh74op9HhsEFra5_Cyun7hfenNuXcXjl3L5QEIyxmNaEQPwkCzZAndL5OEsZTVTbOn-zrZZ5w1eZ3WuGdYpMs8R5tDJ6EsVXVMl9cvTZtUOAfg8sclHNOrdS95Z7OPsoT5vzT8A49xSVieOGzch-Bk7J0N5y3DSTwS9I1k8hVf-RoPXUopLcuy3GwKRlf56G58mQ6CWWrsjbvBwy05pSyfnqmLQuNkuS2WO_9MY1b69c2miB-yLZ37vrKdni_I8O8WuUbQiBAKBy5rCFlF4yJJ6V0HQ0rt9dTeMzbwchTV0X60d8j3LpoOtGgIZmMEWsfeFWGfpzU2uedyuIpGl5T-185fpFziScQi-gtM9TuJfcDCGVsCAyFd_ioBgcFNnl2wckrmDQN39ifNdkXmefKGgYPgJgOtg48ULijyKEdU_Wn0O4ywh-QHjLjq5n-PCEMbteGy5qrWUGMjJOqpgclDyP-rn2v-z9seI78Ej4Fpx1ctKu4v-KhRGm4nooGIYSKyo5DLiJ_Q8uBgBy-7xB2n_vPlf183D8MUdZ9LcWk-1tb1hyM8Qm2vlJmB77J7gRerShj7wDdhDPAHr0z7CifkUl9OdDPea8SThqpTCisTQWnA7nAzWFS9UnaGnCz9S0BoELLqpBbaWDlhuevPrI7L8TCMouOEas8LX2TZ6i5QJRmo8v5tKKVQi6ZBpaMhEVm1fY36aiIdKxw1Otm-vplPhdHYNjaJRb1O6iIp-ALXcZakSZGyrFgc1xSTJqc055znRRbndRonWDc5ZsiKfb5ciDWjbEVjWtBlnK2KaFUVSVYUcZblWNUxkiXFExdt1LbPp6hTh4XQusd1zBiL00XL99hqN_0z1tiSSFKqXhpxQsIYWW0Xam1NP-37gyZL2gpt9OTMCNO6Lw8cHGS1vZzq7_-iYNGrdn005uw2DdsRtjsIc-z3UdWdCNvZmOHfp7PqvmFlCNu5ajRhu1DQ85r9HQAA__9KR7iW">