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

This array or function or substring is invalid in constant expressions. [C_SIZEOF]

Long_Qu
Beginner
1,583 Views

i want to compute the size of an interoperable type and register its value into an integer parameter, here is the code

 

module m_constant

  use, intrinsic :: iso_c_binding
  
  implicit none

  type,bind (c) :: t_mytype
     integer(kind=c_int) :: a
     integer(kind=c_int) :: b
     integer(kind=c_int) :: c
     real(kind=c_double) :: d
  end type t_mytype

  type(t_mytype), private :: tmp_mytype
  
  integer,parameter :: MYTYPE_CSIZE = c_sizeof(tmp_mytype)
  
end module m_constant

program test
  use m_constant

  use,intrinsic :: iso_c_binding

  write(6,'(a,i4)') 'my type csize',MYTYPE_CIZE
  
end program test

The compiler ifort 17.0.1 can not compile the code and show:

qu@debian:~/Desktop/test/test_csize_of$ ifort test.f90
test.f90(16): error #6259: This array or function or substring is invalid in constant expressions.   [C_SIZEOF]
  integer,parameter :: MYTYPE_CSIZE = c_sizeof(tmp_mytype)

I test also on a gfortran 5.2.0, i get MYTYPE_CIZE=24, and everything seems OK.

Is that a compiler bug ?

 

0 Kudos
4 Replies
Steve_Lionel
Honored Contributor III
1,583 Views

Not a bug, but a feature of Fortran 2008 that is not yet implemented.

0 Kudos
JVanB
Valued Contributor II
1,583 Views

There is a possible workaround:

module M1
   use, intrinsic :: ISO_C_BINDING
   use, intrinsic :: ISO_C_BINDING, only: nothing=>C_SIZEOF
   implicit none
   private nothing
end module M1

module M2
   implicit none
   intrinsic SIZEOF
end module M2

module ISO_C_BINDING_1
   use M1
   use M2, only: C_SIZEOF=>SIZEOF
   implicit none
end module ISO_C_BINDING_1

module M3
   use ISO_C_BINDING_1
   implicit none
   type, BIND(C) :: T
      integer(C_INT) i
      real(C_DOUBLE) x
   end type T
   type(T), private :: T1
   integer, parameter :: Tsize = C_SIZEOF(T1)
end module M3

program P
   use ISO_C_BINDING_1
   use M3
   implicit none
   write(*,'(*(g0))') 'Tsize = ',Tsize
end program P

Then you would have to change ISO_C_BINDING to ISO_C_BINDING_1. With gfortran, the distinction between the INTRINSIC and NON_INTRINSIC versions of module ISO_C_BINDING means that you don't need to rename to ISO_C_BINDING_1, but of course gfortran has already implemented this feature of f2008 anyhow, so this workaround isn't necessary in that case. Later, when ifort gets around to supporting this f2008 feature, you could rename ISO_C_BINDING_1 back to ISO_C_BINDING and get rid of module ISO_C_BINDING_1.

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,583 Views

RO,

Excellent!

You might add:

!DIR$ IF DEFINED(__INTEL_COMPILER)
...
!DIR$ ELSE
...
!DIR$ ENDIF

 

or something like that.

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
1,583 Views

Repeat Offender wrote:

There is a possible workaround: ..

Why go through all that and employ a non-standard feature of SIZEOF when the Fortran standard also offers STORAGE_SIZE and is supported by Intel Fortran.

module m_constant

   use, intrinsic :: iso_c_binding, only : c_int, c_double, c_sizeof, c_size_t
   use, intrinsic :: iso_fortran_env, only : character_storage_size

   implicit none

   type,bind (c) :: t_mytype
      integer(kind=c_int) :: a
      integer(kind=c_int) :: b
      integer(kind=c_int) :: c
      real(kind=c_double) :: d
   end type t_mytype

   type(t_mytype), private :: tmp_mytype

   integer(c_size_t), parameter :: MYTYPE_CSIZE = c_sizeof(tmp_mytype)
   ! if size desired in bytes, use named constant from ISO_FORTRAN_ENV to tranform the result in bits
   integer, parameter :: MYTYPE_SIZE = storage_size(tmp_mytype)/character_storage_size

end module m_constant

program test

   use, intrinsic :: iso_fortran_env, only : output_unit
   use m_constant, only : MYTYPE_CSIZE, MYTYPE_SIZE

   write ( output_unit, "(*(g0))") "MYTYPE_CSIZE = ", MYTYPE_CSIZE
   write ( output_unit, "(*(g0))") "MYTYPE_SIZE = ", MYTYPE_SIZE

   stop

end program test

Since gfortran supports both, here's the execution output using that compiler:

MYTYPE_CSIZE = 24
MYTYPE_SIZE = 24

 

0 Kudos
Reply