动态(可分配)向量的 gfortran 编译器错误
gfortran compiler error with dynamic (allocatable) vector
我正在处理由多个模块组成并使用 OOP 功能的大型 Fortran 代码。我在使用 gfortran 版本 7 到 9 编译此代码时遇到错误。
- 我在下面提供了一个最小的工作示例来重现该错误。可以保存为
test.f95
,用gfortran -fcheck=all -c test.f95
. 编译
- 当
-fcheck=all
传递给编译器时会触发错误。
- 该错误出现在 gfortran 7、8 和 9 中,但在以前的版本中没有出现(使用 gfortran 5 和 6 测试)。请参阅下面的编译器输出。
- 我正在使用 Ubuntu 18.04.3 LTS,4.15.0-65-generic x86_64
有人可以尝试重现并确认这个错误吗?我查看了不同的错误跟踪系统,但找不到任何类似的东西。我还没有报告过它,并且想在报告之前确保它值得报告。
此外,是否有解决此编译器错误的方法?
最小工作示例:
module buggy
implicit none
type :: par
contains
procedure, public :: fun => fun_par
end type par
type comp
class(par), allocatable :: p
end type comp
type foo
type(comp), allocatable :: m(:)
contains
procedure, public :: init => init_foo
procedure, public :: update => update_foo
end type foo
contains
function fun_par(this, x) result(y)
implicit none
class(par) :: this
integer, intent(in) :: x(:)
integer :: y(size(x))
end function fun_par
subroutine init_foo(this, n)
implicit none
class(foo) :: this
integer, intent(in) :: n
integer :: k
allocate(this%m(n))
do k = 1, n
allocate(par :: this%m(k)%p)
end do
end subroutine init_foo
subroutine update_foo(this, x)
implicit none
class(foo) :: this
integer, intent(in) :: x(:)
integer :: k
do k = 1, size(this%m)
write(*,*) this%m(k)%p%fun(x)
end do
end subroutine update_foo
end module buggy
一些评论,来自反复试验:
- 在
foo
的定义中,如果将 m
指定为固定长度向量(例如 type(comp) :: m(10)
),则会触发相同的错误。 allocatable
似乎不是这里的罪魁祸首。
- 使用
type(par)
而不是 class(par)
在 comp
中定义 p
不会触发错误。但是我需要 p
在我的代码中是多态的。
- 当
p
被指定为指针而不是可分配向量时出现相同错误。
fun_par()
中结果 y
的维数似乎有问题:例如当它是标量时(y
而不是 y(size(x))
),错误未触发。
编译器错误消息
使用 gfortran 9.2.1:
$ /usr/bin/gfortran-9 -fcheck=all -c test.f95
test.f95:50:0:
50 | write(*,*) this%m(k)%p%fun(x)
|
internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:6785
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-9/README.Bugs> for instructions.
使用 gfortran 8.3.0:
$ /usr/bin/gfortran-8 -fcheck=all -c test.f95
test.f95:50:0:
write(*,*) this%m(k)%p%fun(x)
internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:6410
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-8/README.Bugs> for instructions.
使用 gfortran 7.4.0:
$ /usr/bin/gfortran-7 -fcheck=all -c test.f95
test.f95:50:0:
write(*,*) this%m(k)%p%fun(x)
internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:6290
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-7/README.Bugs> for instructions.
使用 gfortran 6.5.0 和 gfortran 5.5.0:没有错误。
未知的内部编译器错误总是值得报告。在这种情况下,我也找不到报告,但更熟悉 gcc 历史的人可能会找到报告。
要解决此编译器错误,您似乎可以直接引用函数 fun_par
而不是组件 p
:
的绑定 fun
write(*,*) fun_par(this%m(1)%p, x)
最后,我们可以让这个例子稍微简单一点:
module buggy
implicit none
type :: par
contains
procedure, public :: fun => fun_par
end type par
type comp
class(par), allocatable :: p
end type comp
type foo
type(comp), allocatable :: m(:)
end type foo
contains
function fun_par(this)
class(par) :: this
integer :: fun_par(1)
fun_par=0
end function fun_par
subroutine update_foo(this)
class(foo) :: this
write(*,*) this%m(1)%p%fun()
end subroutine update_foo
end module buggy
我正在处理由多个模块组成并使用 OOP 功能的大型 Fortran 代码。我在使用 gfortran 版本 7 到 9 编译此代码时遇到错误。
- 我在下面提供了一个最小的工作示例来重现该错误。可以保存为
test.f95
,用gfortran -fcheck=all -c test.f95
. 编译
- 当
-fcheck=all
传递给编译器时会触发错误。 - 该错误出现在 gfortran 7、8 和 9 中,但在以前的版本中没有出现(使用 gfortran 5 和 6 测试)。请参阅下面的编译器输出。
- 我正在使用 Ubuntu 18.04.3 LTS,4.15.0-65-generic x86_64
有人可以尝试重现并确认这个错误吗?我查看了不同的错误跟踪系统,但找不到任何类似的东西。我还没有报告过它,并且想在报告之前确保它值得报告。
此外,是否有解决此编译器错误的方法?
最小工作示例:
module buggy
implicit none
type :: par
contains
procedure, public :: fun => fun_par
end type par
type comp
class(par), allocatable :: p
end type comp
type foo
type(comp), allocatable :: m(:)
contains
procedure, public :: init => init_foo
procedure, public :: update => update_foo
end type foo
contains
function fun_par(this, x) result(y)
implicit none
class(par) :: this
integer, intent(in) :: x(:)
integer :: y(size(x))
end function fun_par
subroutine init_foo(this, n)
implicit none
class(foo) :: this
integer, intent(in) :: n
integer :: k
allocate(this%m(n))
do k = 1, n
allocate(par :: this%m(k)%p)
end do
end subroutine init_foo
subroutine update_foo(this, x)
implicit none
class(foo) :: this
integer, intent(in) :: x(:)
integer :: k
do k = 1, size(this%m)
write(*,*) this%m(k)%p%fun(x)
end do
end subroutine update_foo
end module buggy
一些评论,来自反复试验:
- 在
foo
的定义中,如果将m
指定为固定长度向量(例如type(comp) :: m(10)
),则会触发相同的错误。allocatable
似乎不是这里的罪魁祸首。 - 使用
type(par)
而不是class(par)
在comp
中定义p
不会触发错误。但是我需要p
在我的代码中是多态的。 - 当
p
被指定为指针而不是可分配向量时出现相同错误。 fun_par()
中结果y
的维数似乎有问题:例如当它是标量时(y
而不是y(size(x))
),错误未触发。
编译器错误消息
使用 gfortran 9.2.1:
$ /usr/bin/gfortran-9 -fcheck=all -c test.f95
test.f95:50:0:
50 | write(*,*) this%m(k)%p%fun(x)
|
internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:6785
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-9/README.Bugs> for instructions.
使用 gfortran 8.3.0:
$ /usr/bin/gfortran-8 -fcheck=all -c test.f95
test.f95:50:0:
write(*,*) this%m(k)%p%fun(x)
internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:6410
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-8/README.Bugs> for instructions.
使用 gfortran 7.4.0:
$ /usr/bin/gfortran-7 -fcheck=all -c test.f95
test.f95:50:0:
write(*,*) this%m(k)%p%fun(x)
internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:6290
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-7/README.Bugs> for instructions.
使用 gfortran 6.5.0 和 gfortran 5.5.0:没有错误。
未知的内部编译器错误总是值得报告。在这种情况下,我也找不到报告,但更熟悉 gcc 历史的人可能会找到报告。
要解决此编译器错误,您似乎可以直接引用函数 fun_par
而不是组件 p
:
fun
write(*,*) fun_par(this%m(1)%p, x)
最后,我们可以让这个例子稍微简单一点:
module buggy
implicit none
type :: par
contains
procedure, public :: fun => fun_par
end type par
type comp
class(par), allocatable :: p
end type comp
type foo
type(comp), allocatable :: m(:)
end type foo
contains
function fun_par(this)
class(par) :: this
integer :: fun_par(1)
fun_par=0
end function fun_par
subroutine update_foo(this)
class(foo) :: this
write(*,*) this%m(1)%p%fun()
end subroutine update_foo
end module buggy