- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

The following code gives an ICE in ifx 2023.0.0 20221201.

```
program transfer_cstar
class(*), allocatable :: x
integer(4) :: l
integer(1), dimension(:), pointer :: b
allocate(x, source=42_4)
l = storage_size(x)/storage_size(0_1)
allocate(b(1:l))
b = transfer(x, b)
print *,l,b
deallocate(b)
end program transfer_cstar
```

Link Copied

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Transfer requires the source to be a scalar or array of any data type. In your code, x is a class(*), which is an unlimited polymorphic object.

Therefore, therefore, in order to use x within transfer, you must provide the determination of the type of the class that can be of any type. Use SELECT TYPE to provide this determination.

Jim Demspey

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Not a proof, but classical ifort (and btw also gfortran) accept the code and do the expected.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

I duplicated the ICE and filed a bug report, CMPLRLLVM-43735. I also noted in the bug report that ifort accepted the illegal Fortran.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

I might have misunderstood Steve Lionel, but according to the link above, polymorphic variables including class(*) are allowed as arguments to transfer. Hence the code is legal, as far as I can tell!

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

In addition to the comments by @Steve_Lionel , I reckon the following is a standard-conforming program that is indeed accepted by both IFORT and gfortran (it may be worth a check using NAG compiler). Thus IFX can be accepted to yield a conforming program with this case once the ICE is resolved, so perhaps you will look into whether this case will be useful to add to incident for the Intel Fortran compiler developers.

```
class(*), allocatable :: x
allocate( x, source=42 )
blk1: block
integer :: n
print *, "Block 1: TRANSFER to default integer"
n = transfer( source=x, mold=n )
print *, "What is x?", n, "; expected is 42"
end block blk1
print *
blk2: block
use, intrinsic :: iso_fortran_env, only : I1 => int8
integer(I1) :: n(4)
print *, "Block 2: TRANSFER to a rank-1, explicit shape 4 array of 8-bit integers"
n = transfer( source=x, mold=n )
print "(g0,4b8.8)", "What is x? ", n
end block blk2
print *
blk3: block
use, intrinsic :: iso_fortran_env, only : I1 => int8
integer(I1), pointer :: n(:)
print *, "Block 3: TRANSFER to an 8-bit integer pointer of rank-1 with the use of SIZE"
allocate( n(storage_size(x)/storage_size(0_i1)) )
n = transfer( source=x, mold=n, size=size(n) )
print "(g0,4b8.8)", "What is x? ", n
end block blk3
print *
blk4: block
use, intrinsic :: iso_fortran_env, only : I1 => int8
integer(I1), pointer :: n(:)
print *, "Block 4: TRANSFER to an 8-bit integer pointer of rank-1"
allocate( n(storage_size(x)/storage_size(0_i1)) )
n = transfer( source=x, mold=n )
print "(g0,4b8.8)", "What is x? ", n
end block blk4
end
```

```
C:\temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.8.0 Build 20221119_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.34.31937.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:p.exe
-subsystem:console
p.obj
C:\temp>p.exe
Block 1: TRANSFER to default integer
What is x? 42 ; expected is 42
Block 2: TRANSFER to a rank-1, explicit shape 4 array of 8-bit integers
What is x? 00101010000000000000000000000000
Block 3: TRANSFER to an 8-bit integer pointer of rank-1 with the use of SIZE
What is x? 00101010000000000000000000000000
Block 4: TRANSFER to an 8-bit integer pointer of rank-1
What is x? 00101010000000000000000000000000
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

I revisited the interpretation I referenced in 2016 (F03/0047) and agree that "any type" includes unlimited polymorphic. While class(*) items have no *declared type*, they do have a *dynamic type*, and are allowed as the SOURCE argument to TRANSFER (but not MOLD). Therefore, the code shown is valid.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Ok, I'll buy that interpretation.

However note with a polymorphic type for source, the source may have an arbitrary sizeof, and thus the lhs of = may be required to receive a truncated or 0-bit filled result from the transfer. Meaning, it may be required to disambiguate what is being transferred either before the transfer or after the transfer such that the receiving end can make sense of what is valid or missing.

Jim Dempsey

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Thank you, all, for the clarification. This reproducer is legal Fortran.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Interesting warning from nagfor - I will have to ask Malcolm about this.

D:\Projects>nagfor -o t.exe t.f90

NAG Fortran Compiler Release 7.1(Hanzomon) Build 7114

Warning: t.f90, line 6: Intrinsic TRANSFER from polymorphic data object might have partially undefined result

[NAG Fortran Compiler normal termination, 1 warning]

D:\Projects>t.exe

Block 1: TRANSFER to default integer

What is x? 42 ; expected is 42

Block 2: TRANSFER to a rank-1, explicit shape 4 array of 8-bit integers

What is x? 00101010000000000000000000000000

Block 3: TRANSFER to an 8-bit integer pointer of rank-1 with the use of SIZE

What is x? 00101010000000000000000000000000

Block 4: TRANSFER to an 8-bit integer pointer of rank-1

What is x? 00101010000000000000000000000000

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

The standard now has explicit wording as to what happens when the sizes are different. Now it says that if the result is smaller, the result is the "leading part" of SOURCE. If the result is larger, the value of the trailing part is "processor dependent" - it used to say it was undefined, making that usage nonconforming.

Here's the complete text:

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. If the physical representation of the result is longer than that of SOURCE, the physical representation of the leading part is that of SOURCE and the remainder is processor dependent. If the physical representation of the result is shorter than that of SOURCE, the physical representation of the result is the leading part of SOURCE. If D and E are scalar variables such that the physical representation of D is as long as or longer than that of E, the value of TRANSFER (TRANSFER (E, D), E) shall be the value of E. IF D is an array and E is an array of rank one, the value of TRANSFER (TRANSFER (E, D), E, SIZE (E)) shall be the value of E.

Malcolm confirmed that nagfor's warning, whose text is based on F90, is meant to alert the user about the possible size issues.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Thanks for clarifying the subtleties. I am actually using transfer of class(*) to integer(1) because of the abysmal performance of write/read. Instead of having ten or so different routines for writing different type of values into an integer(1) buffer of a few 1000 bytes (already sufficient), there is a single class(*) variant, but only used for rather plain (i.e. intrinsic) data types. With such a buffer and the occasional write/read the IO execution time went from relevant to almost negligible.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

This ICE is melted with the Fortran compilers released this week as part of oneAPI 2023.2 HPC Toolkit.

Please download it and try it!

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page