Dear Intel Team,
during polishing the user interface of the unit-test framework Fortuno, I came across a weird compiler behavior.
Both, the ifort and the ifx compilers accept the initialization of a procedure pointer with a non-matching procedure target during compilation. As the minimal working example below demonstrates, the same procedure pointer is initialized with two different non-equivalent interfaces. The compilers do not complain, but executing the resulting code results in a segfault, when calling the non-matching procedure. (I agree, that the code is not standard conforming, but I'd have expected the compiler to issue a compile-time error message.)
I am using ifort (IFORT) 2021.7.1 20221019 on x86_64/Linux.
module definit_basetypes implicit none type :: serial_test_base end type serial_test_base type, extends(serial_test_base) :: serial_test procedure(serial_test_testroutine_i), nopass, pointer :: testroutine end type serial_test abstract interface subroutine serial_test_testroutine_i() end subroutine serial_test_testroutine_i end interface end module definit_basetypes program definit_app use definit_basetypes implicit none type, extends(serial_test) :: customized_test integer :: param = -1 end type customized_test type(customized_test), allocatable :: mytest1, mytest2 mytest1 = customized_test(test_without_arg, 1) mytest2 = customized_test(test_with_arg, 2) print *, mytest1%param call mytest1%testroutine() print *, mytest2%param call mytest2%testroutine() contains subroutine test_without_arg() print *, "WITHOUT ARG" end subroutine test_without_arg subroutine test_with_arg(this) class(customized_test), intent(in) :: this print *, "WITH ARG" print *, this%param end subroutine test_with_arg end program definit_app
Does the compiler report error using:
mytest1 = serial_test(test_without_arg) mytest2 = serial_test(test_with_arg)
(not sure if it is permitted to initialize a derived type with a base type)
IOW is the (lack of) error induced by the extended type, or present in base type as well.
No, it is not possible to initialize a child with its base type that way. However, inspired by your question, I could further reduce the example triggering the regression. The example below still compiles, although it should not IMO.
program definit_app implicit none type :: serial_test procedure(serial_test_testroutine_i), nopass, pointer :: testroutine end type serial_test abstract interface subroutine serial_test_testroutine_i() end subroutine serial_test_testroutine_i end interface type(serial_test), allocatable :: mytest1, mytest2 mytest1 = serial_test(test_without_arg) mytest2 = serial_test(test_with_arg) call mytest1%testroutine() call mytest2%testroutine() contains subroutine test_without_arg() print *, "WITHOUT ARG" end subroutine test_without_arg subroutine test_with_arg(this) class(serial_test), intent(in) :: this print *, "WITH ARG" end subroutine test_with_arg end program definit_app
Re: "I'd have expected the compiler to issue a compile-time error message," chances are good Intel Fortran team can oblige and issue compile-time diagnostics because the Intel compilers IFX and IFORT do so with the pointer assignment which is what in effect comes into play with the use of the structure constructor and the intrinsic assignment semantics the structure constructor is supposed to invoke.
However from what I recall, the standard does not include a numbered constraint for the mismatch in the procedure interface and therefore, the processor may not be required to detect and report this.
module m type :: t procedure(Isub), nopass, pointer :: psub end type abstract interface subroutine Isub() end subroutine end interface end module use m type(t) :: x x = t( sub ) ! Processor fails to report this x%psub => sub ! Processor reports this mismatch contains subroutine sub( this ) class(t), intent(in) :: this end subroutine end
C:\temp>ifort /c /standard-semantics p.f90 Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.0 Build 20220726_000000 Copyright (C) 1985-2022 Intel Corporation. All rights reserved. p.f90(13): error #8178: The procedure pointer and the procedure target must have matching arguments. x%psub => sub ! Processor reports this mismatch ---^ compilation aborted for p.f90 (code 1)
Great, thanks, this is an even more compact demonstration of the issue.
I understand, that the compiler might not be obliged to report the mismatch at compile-time, but it would be very helpful. When working with a statically typed compiled language, I'd usually expect the compiler to catch type mismatches instead of generating an eventually segfaulting executable.
I filed a feature request for the Fortran compiler to recognize this, CMPLRLLVM-42232. It's a feature request since it's not required by the standard.
I have no idea when it might be implemented.