Silverfrost Forums

Welcome to our forums

Array lost in derived type

8 Dec 2022 12:23 #29674

The following program defines a derived type at3 in terms of another derived type (at2), which in turn is defined as an array of yet another derived type (at1). Subroutine s is called to initialise an instance of at3, and then at3 is printed. However, only at3%c is printed, and at3%at2 appears to be missing.

Module m
!
   Type t1
      Integer :: i1
      Integer :: i2
   End Type t1
!
   Type t2
      Type(t1), Dimension(2) :: at1
   End Type t2
!
   Type t3
      Type(t2) :: at2
      Character  :: c
   End Type t3
!
   Type(t3), Dimension(:), Pointer, Public :: at3
!
Contains
!
!
 Subroutine s ()
!
   Allocate (at3(1))
   at3(1)%at2%at1(:)%i1 = 1
   at3(1)%at2%at1(:)%i2 = 1
   at3(1)%c = 'A'
!
   Return
 End Subroutine s
End Module m

Program p
   Use m
!
   Call s ()
   Print*, at3
End Program p
8 Dec 2022 7:26 #29676

Simon

I have logged this for investigation.

On initial investigation it appears that it is only the PRINT that is not working correctly. At the moment for the other components you need

   Print*, at3(1)%c
   Print*, at3(1)%at2%at1
8 Dec 2022 2:12 #29679

Hi Paul, Indeed, in this case, it appears that only Print is not working, and printing individual components works, as in your example. However, I detected this problem in my much larger program because the components were getting lost when I was trying to use them for something else. If you need an example program to illustrate that problem I will try to create one, but I'd prefer to wait to see what you find out with the one already submitted, since it will take me a few hours. But I'll start on it asap if you are confident it will be helpful. Thanks.

8 Dec 2022 3:13 #29681

Simon

I think that it is unlikely that the error in the context of PRINT will reveal a more general error.

The issue is logged but it could be a few weeks before it is investigated.

14 Dec 2022 8:06 #29702

For what it's worth, the same problem occurs if the pointer is converted to an allocatable array:

Module m
!
   Type t1
      Integer :: i1
      Integer :: i2
   End Type t1
!
   Type t2
      Type(t1), Dimension(2) :: at1
   End Type t2
!
   Type t3
      Type(t2) :: at2
      Character  :: c
   End Type t3
!
   Type(t3), Dimension(:), Allocatable, Public :: at3
   Type(t3), Dimension(:), Pointer,     Public :: pt3
!
Contains
!
!
 Subroutine s ()
!
   Allocate (at3(1))
   at3(1)%at2%at1(:)%i1 = 1
   at3(1)%at2%at1(:)%i2 = 2
   at3(1)%c = 'A'
!
   Allocate (pt3(1))
   pt3(1)%at2%at1(:)%i1 = 3
   pt3(1)%at2%at1(:)%i2 = 4
   pt3(1)%c = 'B'
!
   Return
 End Subroutine s
End Module m

Program p
   Use m
   Integer :: i
!
   Call s ()
   Print*, at3
   Print*, pt3
   i = at3(1)%at2%at1(1)%i1
   Print*, i
   i = pt3(1)%at2%at1(1)%i1
   Print*, i
End Program p

It may also be worth noting that if Type t3 is redefined as:

   Type t3
      Character  :: c
      Type(t2) :: at2
   End Type t3

Some of the initalized data are now output correctly, but that others appear to have random values, suggesting that they are unitialized.

I am very keen to get this problem resolved asap so I will work on trying to provide an example that applies to more than just Print ...

15 Dec 2022 8:06 #29703

Thank you for the additional feedback.

16 Dec 2022 6:46 #29705

Simon,

There are some approaches that might get around some of the problems you may have. I have not needed extended derived types in my coding, while some allocatable components are acceptable.

I do find a general printed output of derived type to be problematic.

Do the following examples help ? If not I would be interested in your comments as to why not.

Module m
!
   Type t2
      Character  :: c
      Integer :: i1(2)
      Integer :: i2(2)
   End Type t2
!
   Type tn
      Character  :: c
      integer :: n
      Integer,allocatable :: i1(:)
      Integer,allocatable :: i2(:)
   End Type tn
!
   Type(t2), Dimension(:), Allocatable, Public :: at3
   Type(tn), Dimension(:), Allocatable, Public :: pt3
!
Contains
!
!
 Subroutine s ()
!
   Allocate (at3(1))
   at3(1)%i1 = 1
   at3(1)%i2 = 2
   at3(1)%c = 'A'
!
   Allocate (pt3(1))
    Allocate ( pt3(1)%i1(4) )
    Allocate ( pt3(1)%i2(4) )
   pt3(1)%n = 4
   pt3(1)%c = 'B'
   pt3(1)%i1 = 3
   pt3(1)%i2 = 4
!
   Return
 End Subroutine s
End Module m

Program p
   Use m
   Integer :: i
!
   Call s ()

   Print*, at3
   i = at3(1)%i1(1)
   Print*, 'at3(1)%i1(1) =', i

!   Print*, pt3(1)     ! this is not allowed
   Print*, pt3(1)%c, pt3(1)%i2
   Print*, pt3(1)%n, pt3(1)%c, pt3(1)%i1 
   i = pt3(1)%i1(2)
   Print*, 'pt3(1)%i1(2) =', i
End Program p
16 Dec 2022 4:55 #29707

John, Your comments have set me thinking. First, let's remove c from the definition of t3, for simplification. Consider the following (I include all the code for ease of following):

Module m
!
   Type t1
      Integer :: i1
      Integer :: i2
   End Type t1
!
   Type t2
      Type(t1), Dimension(2) :: at1
   End Type t2
!
   Type t3
      Type(t2) :: at2
   End Type t3
!
   Type(t3), Dimension(:), Pointer, Public :: pt3
!
Contains
!
!
 Subroutine s ()
!
   Allocate (pt3(1))
   pt3(1)%at2%at1(:)%i1 = 3
   pt3(1)%at2%at1(:)%i2 = 4
!
   Return
 End Subroutine s
End Module m

Program p
   Use m
!
   Call s ()
   Print*, 'Output 1',pt3
   Print*, 'Output 2',pt3(1)
   Print*, 'Output 3',pt3(1)%at2%at1(1:2)
   Print*, 'Output 4',pt3(1)%at2%at1(:)
   Print*, 'Output 5',pt3(:)%at2%at1(1)
!   Print*, 'Output 6',pt3(:)%at2%at1(:)
!   Print*, 'Output 7',pt3(1:1)
End Program p

The code fails to compile at 'Output 6' in FTN95 if it is uncommented, and in at least one other compiler. But Outputs 1-5 compile, and all run correctly, except for Output 1 in FTN95. I would (naively?) expect Output6 to print everything but t3%c, which, to me, makes it a bit surprising that Output 1 works at all. The fact that Outputs 2-5 work, suggests to me that FTN95 has not resolved how to deal with the two implicit array components in Output 1.

The code at Output 7 also fails to compile, but other compilers accept this line and run as expected.

Maybe some of the above gives Paul a clearer clue as to what the problem might be.

17 Dec 2022 4:28 #29708

Simon

I have had an initial look at this and I can see the failure for 'Output 1'.

The FTN95 processing at this point is specifically for PRINT. Given time it should be possible to fix it but it seems very unlikely that it will reveal any errors in a wider context.

Until we can provide a fix for this PRINT, I suggest that you avoid this particular form and let us know if you experience any failures in contexts other than I/O.

19 Dec 2022 7:36 #29709

This issue relates to PRINT/WRITE when printing a whole array of user type where the elements of the type include an array of user type.

At the moment it remains on the short list of known issues that need fixing.

It illustrates the complexities of Fortran compiler writing in that you can program horrendously complex processes in very short statements.

As far as I know there is no limit to the nesting of user TYPEs and their array members and you can write code that presents whole arrays (or array sections) at any of the nesting levels.

A Fortran programmer might assume that, the shorter the expression, the faster it will run. This is not always the case and (as illustrated in this context) could prove to be a 'bridge too far'.

19 Dec 2022 4:07 #29710

Hi Paul, I'm sorry this is so complex. However, I believe that because John's response gave me a better sense of how to avoid the problem, I have a satisfactory work around. So I no longer consider this an urgent issue. If I can isolate a case where the problem occurs outside of PRINT / WRITE, I will forward it. Thanks.

25 Jan 2023 6:41 #29875

This bug has now been fixed for the next release of FTN95.

Please login to reply.