Problem with parameterized types

Hi,

I try to compile this code :

type mytype(klon,klev)
  integer, len :: klon=1, klev=1
  real a(klon,klev)
end type


integer :: kklon, kklev
character*32 :: clarg

call getarg (1, clarg); read (clarg, *) kklon
call getarg (2, clarg); read (clarg, *) kklev

call toto (kklon, kklev)

contains

subroutine toto (kklon, kklev)

integer :: kklon, kklev

type (mytype (kklon, kklev)) :: x

print '("Component of x has size ", I0)', SIZE(x%a)

end subroutine

end

But I get :

[CNC tmp]$ pgf90 --version

pgf90 (aka nvfortran) 21.5-0 LLVM 64-bit target on x86-64 Linux -tp zen 
PGI Compilers and Tools
Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved.
[CNC tmp]$ pgf90 -o ss.x ss.F90
NVFORTRAN-F-0000-Internal compiler error. mk_mem_ptr_shape: lwb not subs      11  (ss.F90: 25)
NVFORTRAN/x86-64 Linux 21.5-0: compilation aborted

Are parameterized types supported by pgf90/nvfortran ?

Regards,

Philippe

Hi Philippe,

Are parameterized types supported by pgf90/nvfortran ?

Yes, though it looks like we have issue with this code. I filed a problem report, TPR #30383, and sent it to engineering.

Nvfortran is having trouble referencing the parameterized derived type (PDT) “mytype” in the internal procedure, toto. It will compile/run successfully if the mytype definition is moved into the toto internal procedure. However, this may not be a viable work around if x in toto has to be returned to the caller.

For example, this will work:

        program main
       type :: mytype(klon,klev)
          integer, len :: klon=1, klev=1
          real :: a(klon,klev)
       end type mytype

       integer :: kklon, kklev
       character*32 :: clarg

       call getarg (1, clarg); read (clarg, *) kklon
       call getarg (2, clarg); read (clarg, *) kklev

       call toto (kklon, kklev)

       contains

       subroutine toto (kklon, kklev)

       type :: mytype(klon,klev)
          integer, len :: klon=1, klev=1
          real :: a(klon,klev)
       end type mytype

           integer :: kklon, kklev

           type (mytype(kklon, kklev)) :: x

           print '("Component of x has size ", I0)', SIZE(x%a)
           
       end subroutine toto
       end

Another possible work around that avoids the problem if you need to return x to the caller is to use a module for the PDT and the toto subprogram:

      module mod

      type :: mytype(klon,klev)
          integer, len :: klon=1, klev=1
          real :: a(klon,klev)
       end type mytype

       contains

       subroutine toto (kklon, kklev)

           integer :: kklon, kklev

           type (mytype(kklon, kklev)) :: x

           print '("Component of x has size ", I0)', SIZE(x%a)

       end subroutine toto
       end module

        program main
        use mod

       integer :: kklon, kklev
       character*32 :: clarg

       call getarg (1, clarg); read (clarg, *) kklon
       call getarg (2, clarg); read (clarg, *) kklev

       call toto (kklon, kklev)

       end

-Mat

Thank you Mats for your advice.

Another thing which seems to be broken :

$ cat main.F90 
module mod

type :: mytype(klon,klev1,klev2)
    integer, len :: klon=1, klev1=1, klev2=1
    real :: a(klon,klev1:klev2)
end type mytype

contains

subroutine toto (kklon, kklev)

    integer :: kklon, kklev

    type (mytype(kklon, 0, kklev)) :: x

    print '("Component of x has size ", I0)', SIZE(x%a)

end subroutine toto
end module

 program main
 use mod

integer :: kklon, kklev
character*32 :: clarg

call getarg (1, clarg); read (clarg, *) kklon
call getarg (2, clarg); read (clarg, *) kklev

call toto (kklon, kklev)

end


$ gfortran main.F90 
$ ./a.out 12 34
Component of x has size 420
$ pgf90 main.F90 
$ ./a.out 12 34
Component of x has size 408
$ pgf90 --version

pgf90 (aka nvfortran) 21.5-0 LLVM 64-bit target on x86-64 Linux -tp skylake 
PGI Compilers and Tools
Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved.

Philippe

While probably related, this issue is different enough that I created a separate issue report, TPR #30389.

What’s interesting is that it seems that the problem only occurs if the lower bound is zero. Using a negative or positive lbound seems to work ok.

% cat test.f90
#ifndef LBOUND
#define LBOUND 1
#endif


module mod

type :: mytype(klon,klev1,klev2)
    integer, len :: klon=1, klev1=1, klev2=1
    real :: a(klon,klev1:klev2)
end type mytype

contains

subroutine toto (kklon, kklev)

    integer :: kklon, kklev,i,j
    type (mytype(kklon, LBOUND, kklev)) :: x

    print '("Component of x has size ", I0)', SIZE(x%a)

    do i=1,kklon
        do j=LBOUND,kklev
           x%a(i,j) = 1.0
        enddo
    enddo
    print *, x%a(:,LBOUND)


end subroutine toto
end module

 program main
 use mod

integer :: kklon, kklev
character*32 :: clarg

call getarg (1, clarg); read (clarg, *) kklon
call getarg (2, clarg); read (clarg, *) kklev

call toto (kklon, kklev)

end

% nvfortran test.f90 -Mpreprocess -DLBOUND=1 ; a.out 12 34
Component of x has size 408
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
% nvfortran test.f90 -Mpreprocess -DLBOUND=0 ; a.out 12 34
Component of x has size 408
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
Segmentation fault
% nvfortran test.f90 -Mpreprocess -DLBOUND=-1 ; a.out 12 34
Component of x has size 432
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
% nvfortran test.f90 -Mpreprocess -DLBOUND=-2 ; a.out 12 34
Component of x has size 444
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
% nvfortran test.f90 -Mpreprocess -DLBOUND=2 ; a.out 12 34
Component of x has size 396
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000
    1.000000        1.000000        1.000000        1.000000