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

Structure constructors for parameterized derived types in output item lists

IanH
Honored Contributor II
383 Views

I think this is legit, if perhaps a little silly.

program p
  implicit none
  
  type :: my_type(l)
    integer, len :: l
    real :: comp(l)
  end type my_type
  
  type(my_type(2)) :: x
  integer :: iolen
  
  ! ok
  x = my_type(2)([1.0, 2.0])
  print *, x
  inquire(iolength = iolen) x
  print *, iolen
  
  ! neither ok.
  print *, my_type(2)([1.0, 2.0])
  inquire(iolength = iolen) my_type(2)([1.0, 2.0])
  print *, iolen
end program p

 

>ifort /check:all /warn:all /standard-semantics /traceback "2016-07-01 len-param-constructor.f90" && "2016-07-01 len-param-constructor.exe"
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 16.0.3.207 Build 20160415
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.00.23918.0
Copyright (C) Microsoft Corporation.  All rights reserved.

"-out:2016-07-01 len-param-constructor.exe"
-subsystem:console
-incremental:no
"2016-07-01 len-param-constructor.obj"
 1.000000 2.000000
 160
forrtl: severe (408): fort: (7): Attempt to use pointer COMP when it is not associated with a target

Image              PC                Routine            Line        Source
2016-07-01 len-pa  000000013F97EA7E  Unknown               Unknown  Unknown
2016-07-01 len-pa  000000013F9714D0  MAIN__                     19  2016-07-01 len-param-constructor.f90
2016-07-01 len-pa  000000013F9BFCBE  Unknown               Unknown  Unknown
2016-07-01 len-pa  000000013F9C05B0  Unknown               Unknown  Unknown
kernel32.dll       0000000076B059BD  Unknown               Unknown  Unknown
ntdll.dll          0000000076D3A2E1  Unknown               Unknown  Unknown

(In the other contemporary thread, my "will depend on the type and kind of ..." should have been "will depend on the type and type parameters of ...".)

0 Kudos
13 Replies
Steven_L_Intel1
Employee
383 Views

Thanks - we'll take a look.

0 Kudos
jimdempseyatthecove
Honored Contributor III
383 Views

IanH, Steve,

When pasting IanH's source code into new project (VS 2013, IVF 16.0.3), *** but using default options ***

The code runs in 32-bit and 64-bit modes. However, the INQUIRE returns different sizes.

32-bit:

   1.000000       2.000000
          20
   1.000000       2.000000
          20
Press any key to continue . . .

64-bit:

   1.000000       2.000000
          40
   1.000000       2.000000
          40
Press any key to continue . . .

Adding /standard-semantics

32-bit:

 1.000000 2.000000
 80
 1.000000 2.000000
 80
Press any key to continue . . .

*** INQUIRE length now 80??

64-bit:

 1.000000 2.000000
 160
 1.000000 2.000000
 160
Press any key to continue . . .

*** INQUIRE length now 160

Although the program does not crash, why the size differences???

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
383 Views

/standard-semantics includes /assume:byterecl, changing the return from INQUIRE(IOLENGTH=)  The 32-64 bit difference is due to an address-sized value used for the type parameter.

0 Kudos
Steven_L_Intel1
Employee
383 Views

Escalated as issue DPD200412338. I've seen a few other cases where enabling /check:pointer causes inappropriate errors for PDTs.

0 Kudos
jimdempseyatthecove
Honored Contributor III
383 Views

>>The 32-64 bit difference is due to an address-sized value used for the type parameter.

But then why 4 different values?

If the my_type were written to an unformatted file, then the record size (and file size) would be any of 4 different values depending on options and therefore would not be portable.

To help us understand, can you explain what is actually written to the unformatted file? I expected something like:

integer(4) :: recordLengthFollowing
integer :: L ! 4 bytes, possibly followed by 4-byte pad depending on 32/64-bit and absence/presence of SEQUENCE
real :: comp(L) ! 2x4 bytes
integer(4) :: recordLengthPreceding

32-bit would expect to be 20 (in agreement)
64-bit would expect to be 20 with SEQUENCE, 24 without sequence...
or (if record lengths of 8) 28 with SEQUENCE, 32 without sequence

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
383 Views

The type parameters, in this case, aren't formally part of the value of the object, and they aren't required to be written to an unformatted file.  (They could be written to permit the compiler to do some sort of consistency check when the data is read as a debugging aid, but the requirement to have consistent output and input item lists is on the head of the programmer.)

While the unformatted representation of an object of derived type is entirely up to the compiler, the reported record length does seem rather strange - I'd expect it to be the same as required for two default real values.

(The record book-keeping information (preceding and trailing record length fields) isn't considered part of the length of the record itself - consider an unformatted stream or unformatted direct file where there isn't (or may not be) such book-keeping information.)

Type parameters of pointer or allocatable components are part of the value of the derived type object that has the pointer or allocatable component, but if an object has a pointer or allocatable component, its going to be written out under the control of a user defined derived type input/output procedure, and INQUIRE doesn't cover that case (which is a gap in language capability - UDDTIO could have provided bindings or whatever for the author of a derived type to report required record length back to INQUIRE)

0 Kudos
Steven_L_Intel1
Employee
383 Views

Thanks for the reminder that IOLENGTH shouldn't be different.I'll look at that closer next week.

0 Kudos
jimdempseyatthecove
Honored Contributor III
383 Views

IanH, Steve,

Test program:

program p
  implicit none
  
  type :: my_type(l)
      sequence
    integer, len :: l
    real :: comp(l)
  end type my_type
  
  type(my_type(2)) :: x
  integer :: iolen
  
  ! ok
  x = my_type(2)([1.0, 2.0])
  print *, x
  inquire(iolength = iolen) x
  print *, iolen
  
  ! neither ok.
  print *, my_type(2)([1.0, 2.0])
  inquire(iolength = iolen) my_type(2)([1.0, 2.0])
  print *, iolen
  print *,'sizeof=',sizeof(my_type(2)([1.0, 2.0]))
  
  open(10,file="test.dat", form="unformatted",status="replace")
  write(10) x ! my_type(2)([1.0, 2.0])
  close(10)
  call execute_command_line('dir test.dat')
end program p

Build in permutations of 32-bit, 64-bit, without standard-symantics, with standard-symantics, with SEQUENCE, without SEQUENCE
... and perform Debug | Start without debugging for each.

Note not only the report of the INQUIRE, but also of the file size produced.

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
383 Views

Unrelated question about this program.

    integer, len :: l

The above inclusion of "len" attribute/clause to integer type is not documented (in 16.0.3).

Can you provide a proper definition here?

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
383 Views

jimdempseyatthecove wrote:

Unrelated question about this program.

    integer, len :: l

The above inclusion of "len" attribute/clause to integer type is not documented (in 16.0.3).

Can you provide a proper definition here?

Jim Dempsey

See this: https://software.intel.com/en-us/node/579828

0 Kudos
jimdempseyatthecove
Honored Contributor III
383 Views

Thanks for the link.

Steve, in the IVF document (on my system file:///C:/Program%20Files%20(x86)/IntelSWTools/documentation_2016/en/compiler_f/common/core/index.htm#GUID-16C62528-69C0-4637-97E2-F15DE46B2A2D.htm)

Using the Index, under INTEGER, there is no reference to use of KIND or LEN when used in parameter derived type declarations of INTEGER. Could this be added? (or add a See also ...)

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
383 Views

Adding LEN or KIND under INTEGER isn't appropriate - there are LOTS of other attributes you can put there in certain cases. Use of KIND and LEN is specific to component declarations in parameterized types, not something one would discuss generically under INTEGER.

0 Kudos
jimdempseyatthecove
Honored Contributor III
383 Views

Then how about adding a note like: Other attributes can be added under certain cases, see: link, link, ...

When looking at IanH's post, and having ?? on the len added to the integer statement.

I looked at how INTEGER is declared. There is no clue as to where to look elsewhere in the documentation for the LEN syntax. The next thing I looked at was to look a LEN, and how it is used. This too did not yield the desired information.

There was a see also for Type Declarations, and I looked there. No success there....

There was a see also for Type Declarations for Derived Types, and looked there. No success there... and at which point there appeared to be no potential link to locate its use in IanH's code.

I do not know about you, but I find it frustrating to not be able to find the desired information without having it indexed in some manner. Your documentation is generally excellent. The point of my gripe is to help make it better.

N.B. Performing a Search on all of these words for "integer len" produces 350 hits! The timely task of weeding down the list 140 items yields Parameterized TYPE Statements, and missing that weeding down the list to 318 we find Parameterized Derived-Type Declarations. While the LEN on INTEGER information can be found that way, I'd rather it not take that much time.

Jim Dempsey

0 Kudos
Reply