Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28794 Discussions

ICE in ifx with transfer for a class(*) variable

martinmath
New Contributor II
1,497 Views

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
0 Kudos
12 Replies
jimdempseyatthecove
Honored Contributor III
1,472 Views

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

0 Kudos
martinmath
New Contributor II
1,456 Views
There should be no ICE, even if it is wrong code. However, see for example here: community.intel.com/t5/Intel-Fortran-Compiler/unlimited-polymorphic-parameter-and-transfer-intrinsic/m-p/1062114#M117747

Not a proof, but classical ifort (and btw also gfortran) accept the code and do the expected.
0 Kudos
Barbara_P_Intel
Employee
1,413 Views

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


0 Kudos
martinmath
New Contributor II
1,408 Views

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!

0 Kudos
FortranFan
Honored Contributor III
1,393 Views

@Barbara_P_Intel ,

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
0 Kudos
Steve_Lionel
Honored Contributor III
1,400 Views

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.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,362 Views

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

0 Kudos
Barbara_P_Intel
Employee
1,383 Views

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


0 Kudos
Steve_Lionel
Honored Contributor III
1,372 Views

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

0 Kudos
Steve_Lionel
Honored Contributor III
1,350 Views

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.

0 Kudos
martinmath
New Contributor II
1,346 Views

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.

0 Kudos
Barbara_P_Intel
Employee
1,076 Views

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!



0 Kudos
Reply