Gfortran produces Wsurprising warning when TRANSFERing from c_bools

I am attempting to cast a logical(c_bool) to an integer(c_int) with transfer but I get the warning

Warning: Intrinsic TRANSFER at (1) has partly undefined result: source size 1 < result size 4 [-Wsurprising]


program main
use iso_c_binding
implicit none
print*, transfer(.false._c_bool, 1_c_int)
end program main

Removing the _c_bool resolves the warning. Am I missing something or is this a false warning? Shouldn’t transfer be able to initialise all 4 bytes of c_int?

Is there another portable way of converting Fortran (c_bools) to integers?

$gfortran --version
GNU Fortran (GCC) 13.0.0 20220629 (experimental)

Rather than reinterpreting the memory, you could make the conversion explicit

use iso_c_binding
logical(c_bool) :: val(4) = [.true., .false., .false., .true.]
print *, merge(1_c_int, 0_c_int, val)

I get the, 1/=4, but does that mean that only the 1st byte of c_int is initialised? I saw this bug report for char → real (not an apples to apples comparison) that mentioned that only the 1st byte being initialised.

Also, when casting from bool to int, does the kind matter? If not, is there a point in warning the user about the difference in byte length?

It seems to work okay for the transfer from a c_bool to a c_int, because the left-over memory happens to be initialized with zeros, however as your linked char to real example shows this is not generally true.

Reinterpreting memories can be dangerous, because you might rely on an internal representation of the compiler:

❯ cat test.f90
use iso_c_binding
integer(c_int) :: ival
ival = -1_c_int
ival = transfer(.true., 1_c_int)
print *, ival
print *, transfer(.true._c_bool, 1_c_int)
❯ gfortran test.f90 && ./a.out
❯ ifort test.f90 && ./a.out
❯ ifort test.f90 -standard-semantics &&./a.out
1 Like