Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
17 Views

Nested allocatable type with allocatable components

Jump to solution

Hi all,

I am trying to use an allocatable type whose component is a type with an allocatable component. I report an example of the issue:

module module_try 
    implicit none
    
    type A_type
        character(len=5) :: A_char      
        double precision, dimension(:), allocatable :: A_double
    endtype A_type
    
    type B_type
        character(len=5) :: B_char
        type(A_type)     :: A
    end type B_type
    
    type(B_type), dimension(:), allocatable :: B
    
contains
    
    subroutine try
        allocate(B(2))              ! no errors
        allocate(B%A%A_double(3))   ! no errors
        B(1)%A%A_double(:) = 1.d0   ! no errros
        B(2)%A%A_double(:) = 2.d0   ! no errors
        print*, 'Hello World_1'
        print*, B(1)%A%A_double(:)
        print*, 'Hello World_2'
        print*, B(2)%A%A_double(:)  ! nothing printed
        print*, 'Hello World_3' 
        !B(2)%A%A_double(1) = 2.d0   ! gives error
    end subroutine try

end module module_try

The problem is that the allocation of the variables seems to work but during debugging the debugger shows 'Undefined pointer/array' when watching the nested allocated types and printing the variables does not correspond to the code instructions.
I attached the .f90 file.

0 Kudos

Accepted Solutions
Highlighted
17 Views

Here is a complete reproducer

Jump to solution

Here is a complete reproducer for you to submit.

module module_try 
    implicit none
    
    type A_type
        character(len=15) :: A_char      
        double precision, dimension(:), allocatable :: A_double
    endtype A_type
    
    type B_type
        character(len=15) :: B_char
        type(A_type)     :: A
    end type B_type
    
    type(B_type), dimension(:), allocatable :: B
    
contains
    subroutine peek_A(A)
        type(A_type) :: A
        ! when needing to debug, break on following line
        if(.not. allocated(A%A_double) )print *,"Bug"
    end subroutine peek_A
    subroutine try
        allocate(B(2))               ! no errors
        B(1)%B_char = 'B(1)'
        B(2)%B_char = 'B(2)'
        !allocate(B%A%A_double(3))   ! wrong allocation
        print *,allocated(B(1)%A%A_double)
        allocate(B(1)%A%A_double(3)) ! no errors, correct allocation
        B(1)%A%A_char = 'B(1)%A'        ! *** B(1)%A%A_char Visible in Debugger
        B(1)%A%A_double(1) = 123.456    ! *** B(1)%A%A_double .NOT. Visible in Debugger
! ********** VS integration error *********
! unable to view B(1)%A%A_double in debugger
! Microsoft Visual Studio Professional 2013
! Version 12.0.40629.00 Update 5
! Intel® Parallel Studio XE 2019 Update 3 Composer Edition for Fortran Windows*   Package ID: w_comp_lib_2019.3.203
        call peek_A(B(1)%A)             ! For debugging you can insert something like this
        print *,allocated(B(1)%A%A_double)
        print *,size(B(1)%A%A_double)
        allocate(B(2)%A%A_double(3)) ! no errors, correct allocation
        B(1)%A%A_double(:) = 1.d0    ! no errros
        B(2)%A%A_double(:) = 2.d0    ! no errors
        print*, 'Hello World_1'
        print*, B(1)%A%A_double(:)
        print*, 'Hello World_2'
        print*, B(2)%A%A_double(:)
        print*, 'Hello World_3' 
        !B(2)%A%A_double(1) = 2.d0
    end subroutine try

end module module_try

program Nested
    use module_try
    call try
end program Nested

Note to Intel, the nested allocatable array is not visible in both Win32 and x64 Debug builds.

Jim Dempsey

View solution in original post

0 Kudos
10 Replies
Highlighted
Valued Contributor III
17 Views

You should follow up with

Jump to solution

You should follow up with Intel Support about this, a good compiler system will issue a diagnostic re: line 20 in the code you show which is not allowed in the language.  It has to be like so:

    subroutine try
        allocate(B(2))              ! no errors
        allocate(B(1)%A%A_double(3))   ! no errors
        allocate(B(2)%A%A_double(3))   ! no errors
        B(1)%A%A_double(:) = 1.d0   ! no errros
        B(2)%A%A_double(:) = 2.d0   ! no errors
        print*, 'Hello World_1'
        print*, B(1)%A%A_double(:)
        print*, 'Hello World_2'
        print*, B(2)%A%A_double(:)  ! nothing printed
        print*, 'Hello World_3'
        !B(2)%A%A_double(1) = 2.d0   ! gives error
    end subroutine try

 

0 Kudos
Highlighted
17 Views

Good reproducer. My Comments:

Jump to solution

Good reproducer. My Comments:

module module_try 
    implicit none
    
    type A_type
        character(len=5) :: A_char      
        double precision, dimension(:), allocatable :: A_double
    endtype A_type
    
    type B_type
        character(len=5) :: B_char
        type(A_type)     :: A
    end type B_type
    
    type(B_type), dimension(:), allocatable :: B
    
contains
    
    subroutine try
        allocate(B(2))              ! no errors *** valid statement, good result
        allocate(B%A%A_double(3))   ! no errors *** invalid statement, bad result
*** should have been:
***  allocate(B(1)%A%A_double(3))
***  allocate(B(2)%A%A_double(3))   
        B(1)%A%A_double(:) = 1.d0   ! no errros *** see below
        B(2)%A%A_double(:) = 2.d0   ! no errors *** see below
*** Had the correct  allocate(B(1)%A%A_double(3))... occurred, then no error is OK
*** Had incorrect allocate(B%A%A_double(3)) NOT occurred and thus A_double not be allocated
*** then (I could not see this in the F2003 spec, Steve help please)
*** it appears undefined (F2003) as to what happens with assignment of scalar to
*** unallocated allocatable array as there is no shape. ?Error or NO-OP?
        print*, 'Hello World_1'
        print*, B(1)%A%A_double(:)
        print*, 'Hello World_2'
        print*, B(2)%A%A_double(:)  ! nothing printed
        print*, 'Hello World_3' 
        !B(2)%A%A_double(1) = 2.d0   ! gives error
    end subroutine try

end module module_try

Jim Dempsey

0 Kudos
Highlighted
17 Views

Thank you very much, I didn't

Jump to solution

Thank you very much, I didn't get any compilation error/warnings but I changed the code following your suggestion and now the value are printed correctly on the screen as expected. Still, I cannot see the value of the allocated and assigned variables in the watchlist during debugging.

module module_try 
    implicit none
    
    type A_type
        character(len=5) :: A_char      
        double precision, dimension(:), allocatable :: A_double
    endtype A_type
    
    type B_type
        character(len=5) :: B_char
        type(A_type)     :: A
    end type B_type
    
    type(B_type), dimension(:), allocatable :: B
    
contains
    
    subroutine try
        allocate(B(2))               ! no errors
        !allocate(B%A%A_double(3))   ! wrong allocation
        allocate(B(1)%A%A_double(3)) ! no errors, correct allocation
        allocate(B(2)%A%A_double(3)) ! no errors, correct allocation
        B(1)%A%A_double(:) = 1.d0    ! no errros
        B(2)%A%A_double(:) = 2.d0    ! no errors
        print*, 'Hello World_1'
        print*, B(1)%A%A_double(:)
        print*, 'Hello World_2'
        print*, B(2)%A%A_double(:)
        print*, 'Hello World_3' 
        !B(2)%A%A_double(1) = 2.d0
    end subroutine try

end module module_try

I report the modified code and attach what I see from the debugger watch at the end of the routine. As depicted in the picture the debugger cannot show the allocated variables. Do I miss any instruction ?

Thanks in advance, Andrea.

0 Kudos
Highlighted
Valued Contributor II
17 Views

That last point is a debugger

Jump to solution

That last point is a debugger bug, What VS/Fortran versions are you using. I think that is fixed now.

0 Kudos
Highlighted
17 Views

Keep in mind that: "The lack

Jump to solution

Keep in mind that: "The lack of a compile time error is an error" for the commented out statement, and should be filed as a bug report with Intel.

Andrew's point of compiler version is pertinent when you post forum messages. I do recall having such errors on older versions (with debug finding members of nested user defined types).

Jim Dempsey 

0 Kudos
Highlighted
17 Views

Hi all,Thank you for your

Jump to solution

Hi all,
Thank you for your suggestions. I will report the lack of compile time error. I am using VS Enterprise 2019 16.2.5 and Intel(R) Visual Fortran Compiler 19.0.5.281 [IA-32], these should also be the latest releases.
Andrea.

0 Kudos
Highlighted
Valued Contributor II
17 Views

Yes, i made a test,  there

Jump to solution

Yes, i made a test,  there still seems to be a bug relating the debugger for allocatables in derived types. The code can runs ok it is just the debugger not identifying the target status correctly.

0 Kudos
Highlighted
18 Views

Here is a complete reproducer

Jump to solution

Here is a complete reproducer for you to submit.

module module_try 
    implicit none
    
    type A_type
        character(len=15) :: A_char      
        double precision, dimension(:), allocatable :: A_double
    endtype A_type
    
    type B_type
        character(len=15) :: B_char
        type(A_type)     :: A
    end type B_type
    
    type(B_type), dimension(:), allocatable :: B
    
contains
    subroutine peek_A(A)
        type(A_type) :: A
        ! when needing to debug, break on following line
        if(.not. allocated(A%A_double) )print *,"Bug"
    end subroutine peek_A
    subroutine try
        allocate(B(2))               ! no errors
        B(1)%B_char = 'B(1)'
        B(2)%B_char = 'B(2)'
        !allocate(B%A%A_double(3))   ! wrong allocation
        print *,allocated(B(1)%A%A_double)
        allocate(B(1)%A%A_double(3)) ! no errors, correct allocation
        B(1)%A%A_char = 'B(1)%A'        ! *** B(1)%A%A_char Visible in Debugger
        B(1)%A%A_double(1) = 123.456    ! *** B(1)%A%A_double .NOT. Visible in Debugger
! ********** VS integration error *********
! unable to view B(1)%A%A_double in debugger
! Microsoft Visual Studio Professional 2013
! Version 12.0.40629.00 Update 5
! Intel® Parallel Studio XE 2019 Update 3 Composer Edition for Fortran Windows*   Package ID: w_comp_lib_2019.3.203
        call peek_A(B(1)%A)             ! For debugging you can insert something like this
        print *,allocated(B(1)%A%A_double)
        print *,size(B(1)%A%A_double)
        allocate(B(2)%A%A_double(3)) ! no errors, correct allocation
        B(1)%A%A_double(:) = 1.d0    ! no errros
        B(2)%A%A_double(:) = 2.d0    ! no errors
        print*, 'Hello World_1'
        print*, B(1)%A%A_double(:)
        print*, 'Hello World_2'
        print*, B(2)%A%A_double(:)
        print*, 'Hello World_3' 
        !B(2)%A%A_double(1) = 2.d0
    end subroutine try

end module module_try

program Nested
    use module_try
    call try
end program Nested

Note to Intel, the nested allocatable array is not visible in both Win32 and x64 Debug builds.

Jim Dempsey

View solution in original post

0 Kudos
Highlighted
Valued Contributor III
17 Views

Another in situ option to the

Jump to solution

Another in situ option to the workaround the Intel Fortran deficiency in its integration with Visual Studio integration is to use the ASSOCIATE construct:

bug.PNG

0 Kudos
Highlighted
17 Views

FortranFan, excellent

Jump to solution

FortranFan, excellent suggestion (you earn the best response). This avoids writing peek functions.

The only additional suggestion would be to include the "never true" IF test that the compiler cannot determine is never true. This would permit you to have working code with little overhead when not debugging as well as not having the compiler optimize out the desired code. Andrea, be aware that inserting this/these statement(s) will disable vectorization for this section of code.

Also,

If you use the FPP (preprocessor), you could #define an FPP macro to conditionally insert the inspection helper.

! *** compile with FPP enabled

subroutine PEEK_HACK
end subroutine PEEK_HACK
! then at break, use Call Stack window to focus on caller

#define PEEK(a) \
   associate(PEEK_AT => a) ; CALL PEEK_HACK ; end associate

module module_try 
    implicit none
    
    type A_type
        character(len=15) :: A_char      
        double precision, dimension(:), allocatable :: A_double
    endtype A_type
    
    type B_type
        character(len=15) :: B_char
        type(A_type)     :: A
    end type B_type
    
    type(B_type), dimension(:), allocatable :: B
    
contains
    subroutine try
        allocate(B(2))               ! no errors
        B(1)%B_char = 'B(1)'
        B(2)%B_char = 'B(2)'
        !allocate(B%A%A_double(3))   ! wrong allocation
        print *,allocated(B(1)%A%A_double)
        allocate(B(1)%A%A_double(3)) ! no errors, correct allocation
        B(1)%A%A_char = 'B(1)%A'        ! *** B(1)%A%A_char Visible in Debugger
        B(1)%A%A_double(1) = 123.456    ! *** B(1)%A%A_double .NOT. Visible in Debugger
! ********** VS integration error *********
! unable to view B(1)%A%A_double in debugger
! Microsoft Visual Studio Professional 2013
! Version 12.0.40629.00 Update 5
! Intel® Parallel Studio XE 2019 Update 3 Composer Edition for Fortran Windows*   Package ID: w_comp_lib_2019.3.203
        PEEK(B(1)%A)             ! For debugging you can insert something like this, use step into
        print *,allocated(B(1)%A%A_double)
        print *,size(B(1)%A%A_double)
        allocate(B(2)%A%A_double(3)) ! no errors, correct allocation
        B(1)%A%A_double(:) = 1.d0    ! no errros
        B(2)%A%A_double(:) = 2.d0    ! no errors
        print*, 'Hello World_1'
        print*, B(1)%A%A_double(:)
        print*, 'Hello World_2'
        print*, B(2)%A%A_double(:)
        print*, 'Hello World_3' 
        !B(2)%A%A_double(1) = 2.d0
    end subroutine try

end module module_try

program Nested
    use module_try
    call try
end program Nested

Feel free to derive something from the above. Note, you may have multiple such places to perform this workaround.

To use:

1) When interested in debugging, place Break Point on the PEEK of interest
2) Use Step Into
3) In Call Stack window, set focus on caller

Jim Dempsey

Jim Dempsey

0 Kudos