Ethan Beyak
2018-09-06 20:17:57 UTC
Hi users and developers of gfortran,
I would like to assign allocatable polymorphic variables, i.e.,
class(foo_t), allocatable :: foo, from a given type, i.e., type(foo_t) ::
foo_type. I can compile this no problem with gfortran 8.1.0, but I
encounter some issues compiling when I try with gfortran 5.5.0. Here's a
simple example module and program.
PROGRAM test_public_assignment.f90
=========
program test_public_assignment
use baz_module
use iso_fortran_env
implicit none
type(vector), parameter :: d = vector(x=4, y=2, z=1)
class(vector), allocatable :: e, wrk, f
call baz(d, e)
wrk = e ! invoking foo
wrk%x = 4*e%x
wrk%y = 3*e%y
wrk%z = 2*e%z
f = wrk ! invoking foo
write(*,*) "Compiler version: ", compiler_version()
write(*,*) "Compiler options: ", compiler_options()
write(*,*) "d: ", d%x, d%y, d%z
write(*,*) "e: ", e%x, e%y, e%z
write(*,*) "f: ", f%x, f%y, f%z
end program test_public_assignment
=========
MODULE baz_module.f90
=========
module baz_module
implicit none
! gfortran 8.1 compiles, but 5.5 does not
private
public baz, vector
! work-around for gfortran 5.5, but not ideal
!public
!private foo
interface assignment (=)
module procedure foo
end interface assignment (=)
type vector
real :: x, y, z
end type vector
contains
subroutine foo(lhs, rhs)
class(vector), intent(in) :: rhs
class(vector), allocatable, intent(out) :: lhs
allocate(lhs, source=rhs)
end subroutine foo
subroutine baz(a, b)
class(vector), intent(in) :: a
class(vector), allocatable, intent(out) :: b
type(vector) :: wrk
wrk%x = 2*a%x
wrk%y = 3*a%y
wrk%z = 4*a%z
b = wrk ! invoking foo
end subroutine baz
end module baz_module
=========
For example, running on gfortran 8.1.0 gives the following output:
OUTPUT 1
=========
$ gfortran baz_module.f90 test_public_assignment.f90 -o test.out
$ ./test.out
Compiler version: GCC version 8.1.0
Compiler options: -mtune=generic -march=x86-64
d: 4.00000000 2.00000000 1.00000000
e: 8.00000000 6.00000000 4.00000000
f: 32.0000000 18.0000000 8.00000000
=========
However, on version 5.5, I get the following errors:
OUTPUT 2
=========
$ gfortran --version
GNU Fortran (Ubuntu 5.5.0-12ubuntu1) 5.5.0 20171010
$ gfortran baz_module.f90 test_public_assignment.f90 -o test.out
test_public_assignment.f90:13:0:
wrk = e ! invoking foo
1
Error: Assignment to an allocatable polymorphic variable at (1) is not yet
supported
test_public_assignment.f90:19:0:
f = wrk ! invoking foo
1
Error: Assignment to an allocatable polymorphic variable at (1) is not yet
supported
=========
Now I did find some workaround by setting the default accessibility of the
module to be public and explicitly declaring the complement of the set of
procedures and variables that I wanted to be private. I'm not sure what
gfortran 5.5.0 is doing to be honest, but the definition of the assignment
can be used in the calling program. Commenting out lines 5,6 and commenting
in lines 8,9 in baz_module.f90 gave me the following output on gfortran
5.5.0
OUTPUT 3
=========
Compiler version: GCC version 5.5.0 20171010
Compiler options: -mtune=generic -march=x86-64
d: 4.00000000 2.00000000 1.00000000
e: 8.00000000 6.00000000 4.00000000
f: 32.0000000 18.0000000 8.00000000
=========
So I have two questions for the gfortran community: 1) do you know why
inverting the module accessibility causes these assignments to work in
gfortran 5.5.0? It seems as if the assignment interface was made public
somehow, but I'm not certain. 2) can you think of any *clean* solutions to
this problem? I'd love backward compatibility while not going against the
recommended standard of private default accessibility.
I look forward to reading what you have to say. Thanks for your time.
Best,
Ethan
I would like to assign allocatable polymorphic variables, i.e.,
class(foo_t), allocatable :: foo, from a given type, i.e., type(foo_t) ::
foo_type. I can compile this no problem with gfortran 8.1.0, but I
encounter some issues compiling when I try with gfortran 5.5.0. Here's a
simple example module and program.
PROGRAM test_public_assignment.f90
=========
program test_public_assignment
use baz_module
use iso_fortran_env
implicit none
type(vector), parameter :: d = vector(x=4, y=2, z=1)
class(vector), allocatable :: e, wrk, f
call baz(d, e)
wrk = e ! invoking foo
wrk%x = 4*e%x
wrk%y = 3*e%y
wrk%z = 2*e%z
f = wrk ! invoking foo
write(*,*) "Compiler version: ", compiler_version()
write(*,*) "Compiler options: ", compiler_options()
write(*,*) "d: ", d%x, d%y, d%z
write(*,*) "e: ", e%x, e%y, e%z
write(*,*) "f: ", f%x, f%y, f%z
end program test_public_assignment
=========
MODULE baz_module.f90
=========
module baz_module
implicit none
! gfortran 8.1 compiles, but 5.5 does not
private
public baz, vector
! work-around for gfortran 5.5, but not ideal
!public
!private foo
interface assignment (=)
module procedure foo
end interface assignment (=)
type vector
real :: x, y, z
end type vector
contains
subroutine foo(lhs, rhs)
class(vector), intent(in) :: rhs
class(vector), allocatable, intent(out) :: lhs
allocate(lhs, source=rhs)
end subroutine foo
subroutine baz(a, b)
class(vector), intent(in) :: a
class(vector), allocatable, intent(out) :: b
type(vector) :: wrk
wrk%x = 2*a%x
wrk%y = 3*a%y
wrk%z = 4*a%z
b = wrk ! invoking foo
end subroutine baz
end module baz_module
=========
For example, running on gfortran 8.1.0 gives the following output:
OUTPUT 1
=========
$ gfortran baz_module.f90 test_public_assignment.f90 -o test.out
$ ./test.out
Compiler version: GCC version 8.1.0
Compiler options: -mtune=generic -march=x86-64
d: 4.00000000 2.00000000 1.00000000
e: 8.00000000 6.00000000 4.00000000
f: 32.0000000 18.0000000 8.00000000
=========
However, on version 5.5, I get the following errors:
OUTPUT 2
=========
$ gfortran --version
GNU Fortran (Ubuntu 5.5.0-12ubuntu1) 5.5.0 20171010
$ gfortran baz_module.f90 test_public_assignment.f90 -o test.out
test_public_assignment.f90:13:0:
wrk = e ! invoking foo
1
Error: Assignment to an allocatable polymorphic variable at (1) is not yet
supported
test_public_assignment.f90:19:0:
f = wrk ! invoking foo
1
Error: Assignment to an allocatable polymorphic variable at (1) is not yet
supported
=========
Now I did find some workaround by setting the default accessibility of the
module to be public and explicitly declaring the complement of the set of
procedures and variables that I wanted to be private. I'm not sure what
gfortran 5.5.0 is doing to be honest, but the definition of the assignment
can be used in the calling program. Commenting out lines 5,6 and commenting
in lines 8,9 in baz_module.f90 gave me the following output on gfortran
5.5.0
OUTPUT 3
=========
Compiler version: GCC version 5.5.0 20171010
Compiler options: -mtune=generic -march=x86-64
d: 4.00000000 2.00000000 1.00000000
e: 8.00000000 6.00000000 4.00000000
f: 32.0000000 18.0000000 8.00000000
=========
So I have two questions for the gfortran community: 1) do you know why
inverting the module accessibility causes these assignments to work in
gfortran 5.5.0? It seems as if the assignment interface was made public
somehow, but I'm not certain. 2) can you think of any *clean* solutions to
this problem? I'd love backward compatibility while not going against the
recommended standard of private default accessibility.
I look forward to reading what you have to say. Thanks for your time.
Best,
Ethan