Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
27982 Discussions

Procedure ptr initialized with mismatching procedure

BalintAradi
Novice
426 Views

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

 

 

0 Kudos
6 Replies
jimdempseyatthecove
Black Belt
422 Views

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.

Jim Dempsey

0 Kudos
BalintAradi
Novice
399 Views

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

 

 

0 Kudos
jimdempseyatthecove
Black Belt
378 Views

Happy you were able to produce an alternate reproducer, It should help Intel developers track down the problem.

 

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
344 Views

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)

 

0 Kudos
BalintAradi
Novice
307 Views

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.

0 Kudos
Barbara_P_Intel
Moderator
241 Views

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.


0 Kudos
Reply