- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The following code demonstrates a regression of Fortran 2008's polymorphic assignment, in both ifx and ifort, that wasn't present in Version 2021.4.0 of both compilers.
module interface
private
type, public, abstract :: IGrid
contains
procedure(dimens), deferred :: dimens
end type IGrid
abstract interface
function dimens(self) result(dims)
import; implicit none
class(IGrid), intent(in) :: self
integer, allocatable :: dims(:)
end function dimens
end interface
end module interface
module implementation
use interface, only: IGrid
implicit none
private
type, public, extends(IGrid) :: Grid
contains
procedure :: dimens
end type Grid
contains
function dimens(self) result(dims)
class(Grid), intent(in) :: self
integer, allocatable :: dims(:)
dims = [400,200]
end function dimens
end module implementation
module test
use interface, only: IGrid
use implementation, only: Grid
implicit none
contains
subroutine grid_array_builder(grids)
!
! Demonstrates polymorphic assignment regression.
!
class(IGrid), allocatable, intent(out) :: grids(:)
integer :: i
integer, parameter :: ngrids = 5
allocate( Grid :: grids(ngrids) )
do i = 1, ngrids
grids(i) = Grid()
end do
end subroutine grid_array_builder
end module test
Here's the output after trying to compile this code with ifx Version 2023.0.0:
ifx -c test.f90
test.f90(65): error #8304: In an intrinsic assignment statement, variable shall not be a non-allocatable polymorphic. [GRIDS]
grids(i) = Grid()
---------^
compilation aborted for test.f90 (code 1)
Ifort Version 2021.8.0 Build 20221119_000000 (that is included in oneAPI 2023.0.0) gives exactly the same "error". This is clearly a compiler bug, because variable "grids" is explicitly declared to be "allocatable" in the above code, and both compilers simply ignore the "allocatable" attribute.
The above code compiled fine with both ifx and ifort Version 2021.4.0.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes. The assignment instruction can have a whole object that is an allocatable, polymorphic and the semantics of intrinsic assignment in the standard informs the processor on the suitable steps it needs to take. Or the assignment can have an element (like your grids(i)) which is nonpolymorphic such as with a SELECT TYPE construct. Working with whole objects, in situations like this I advise, is better in the long-term as processors get better.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Rather than a regression, this is a case where the latest versions of IFX and IFORT now conform to the Fortran standard whereas the earlier versions failed to do so. Per the standard, a reference to an element (or an array section) is not supported in an assignment with a polymorphic variable on the left-hand side and an extended type as the result of the expression on the right. You will need to refactor your code to conform, a possible option you can consider with 2023.0.0 version (I have not tried it myself, thus untested):
..
allocate( Grid :: grids(ngrids) )
select type ( grids )
type is ( Grid )
do i = 1, ngrids
grids(i) = Grid()
end do
class default
end select
..
A better option will be to consider the functional programming support in the language and make use of much of the built-in elemental facility and simply go with:
..
allocate( Grid :: grids(ngrids) )
grids = Grid()
..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your reply.
So what you're basically saying is that, in order to conform to the standard, one has to use an array (or elemental) expression to initialize the "grids" array as a whole (if one wishes to avoid the use of a "select type" statement).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes. The assignment instruction can have a whole object that is an allocatable, polymorphic and the semantics of intrinsic assignment in the standard informs the processor on the suitable steps it needs to take. Or the assignment can have an element (like your grids(i)) which is nonpolymorphic such as with a SELECT TYPE construct. Working with whole objects, in situations like this I advise, is better in the long-term as processors get better.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Gfortran 12.0.1, a superb Fortran compiler, also catches this Standard violation. It is helpful to have a copy of a recent gfortran handy for cross checking code against the Standard. Also, the NAG compiler is amazing at diagnostics for Standards violations.
gfortran qnew2.f90
qnew2.f90:65:9:
65 | grids(i) = Grid()
| 1
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator
rwgreen@orcsle153:~/quad$ gfortran --version
GNU Fortran (GCC) 12.0.1 20220413 (Red Hat 12.0.1-0)
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page