I'm experimenting with polymorphism and when writing a module for managing dynamic lists, I sometimes got an ICE, sometimes it worked. I discovered that when using class(*) on type structures, it somehow requires the presence of at least one allocatable array.
module testclass type tClass class(*), pointer :: X contains procedure :: getX,setX end type contains function getX(this) class(*),pointer :: getX class(tClass) :: this getX => this%X end function subroutine setX(this,x) class(*) :: x class(tClass) :: this allocate(this%X,source=x) end subroutine end module program bugtest use testclass type :: tTest integer :: A ! uncommenting 'dummy' resolves the ICE !integer, allocatable,dimension(:) :: dummy end type type(tClass) :: myClass type(tTest) :: myA myA .A = 42 call myClass.setX(myA) myA .A = 43 myA = myClass.getX() print *, myA.A end program
ifort -O1 does work, O2 and O3 gives an ICE.
Alternatively, uncommenting "dummy" compiles fine for O2 and O3 as well.
ifort Version 188.8.131.52 Build 20190416
openSUSE Leap 15.1
AMD Opteron 2376, Intel Xeon E5620 (tested on both).
As advised upthread, please report the ICE to Intel if you are able to.
But please do note
- the use of unlimited polymorphic types (CLASS(*) and also TYPE(*) which is more toward interoperation with C) are fraught,
- Moreover, there are severe gaps when it comes to GENERICS in Fortran and an attempt to employ unlimited polymorphism to overcome the limitations with generics in Fortran can be an exercise in futility.
- Additionally, there are other limitations in Fortran when it comes to lack of adequate support in the language standard itself with certain aspects of OO in the form of no required copy elision, no move semantics, etc. and given the typical issues with pointers of dangling ones and memory leaks, extreme care is needed to achieve functioning OO 'classes' using pointer components.
- There is no easy facility for 'casting' in Fortran and you'll need to use the more verbose SELECT TYPE construct to consume your OO 'classes' unless you expend further effort to study OO patterns to avoid such needs.
- Finally, you'll need to be always mindful of the "=>" syntax with pointer assignments in the language.
To overcome the first point above and thus making it easy on a compiler and help it overcome an ICE, you can consider a 'base' Class, a "homebrew" of a superobject the way Java does it. See a modified example below which also addresses a few of the above issues.
module baseClass type, abstract :: b_t end type end module module testclass use baseClass, only : b_t type :: tClass class(b_t), pointer :: X contains procedure, pass(this) :: getX, setX end type contains function getX(this) class(b_t), pointer :: getX class(tClass), intent(in) :: this getX => this%X end function subroutine setX(this, x) class(b_t), intent(in) :: x class(tClass), intent(inout) :: this allocate(this%X, source=x) end subroutine end module program bugtest use baseClass, only : b_t use testclass type, extends(b_t) :: tTest integer :: A = 0 end type type(tClass) :: myClass type(tTest) :: myA class(b_t), pointer :: myB myA%A = 42 call myClass%setX( myA ) myA%A = 43 myB => myClass%getX() !<-- Note this select type ( B => myB ) !<-- mimic casting type is ( tTest ) print *, "myB%A = ", B%A, "; expected is 42" class default ! flag error? end select end program
C:\temp>ifort /standard-semantics /stand:f18 /warn:all p.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1 Beta Build 20200827 Copyright (C) 1985-2020 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 14.27.29112.0 Copyright (C) Microsoft Corporation. All rights reserved. -out:p.exe -subsystem:console p.obj C:\temp>p.exe myB%A = 42 ; expected is 42 C:\temp>