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

Overridden procedure ignored at runtime

Andrew_Smith
New Contributor III
408 Views

I have a class structure 4 deep, with an abstract type at the top two levels.

I have a deffered contained procedure in the abtract type that has a concrete implementation at levels 3 and 4.

I create instances of both level 3 and 4 types. If I call the procedure on both types [ using object%procecdure(), where object is class(BaseLevel) object ], only the procedure defined on level 3 is called. It means overriding has not taken on objects of type 4.

I have thousands of similar overridden procedures that work. Only this combination of structure fails.

I first encountered this compiler error in XE 2016 and it is still present in the XE 2019 update 5.

It is not possible to work around it without going back to pre-object oriented code.

I am not sure if I can reproduce it in a small piece of code, but I am going to try as I know Steves first question will be that.

0 Kudos
3 Replies
Andrew_Smith
New Contributor III
408 Views

I created the same structure in a simple example but it did not fail. I deleted all of the data and extra procedures contained in each type as part of the simplification. Could that have influenced it?

The actual code fails in both relase and fully debugged mode so hopefully its not a case of data trampling over descriptors.

0 Kudos
FortranFan
Honored Contributor II
408 Views

Andrew Smith wrote:

.. I am not sure if I can reproduce it in a small piece of code, but I am going to try as I know Steves first question will be that.

@Andrew Smith,

Re: "I am not sure if I can reproduce it in a small piece of code, but I am going to try as I know Steves first question will be that," yes that's likely your best bet for a successful resolution to your issue.

And keep in mind the American proverb: "if you don't succeed at first, try, try again"!

You can find an instance of it in this thread, see Quote #5: https://software.intel.com/en-us/node/685154#comment-form.  A simple reproducer that ultimately 'modeled' closely the pattern of the actual code reproduced the issue which then helped the Intel compiler team develop a fix.

0 Kudos
FortranFan
Honored Contributor II
408 Views

Andrew Smith wrote:

I created the same structure in a simple example but it did not fail. I deleted all of the data and extra procedures contained in each type as part of the simplification. Could that have influenced it?

The actual code fails in both relase and fully debugged mode so hopefully its not a case of data trampling over descriptors.

If it's of any help, you can take something like this and adapt it your situation: keep an eye on aspects such as how the caller allocates the objects, compiler settings (any use of /assume options), basically every little detail:

module b_m
   type, abstract :: b_t
      integer :: i = 0
   contains
      procedure(Isub), pass(this), deferred :: sub
   end type
   abstract interface
      subroutine Isub( this )
         import :: b_t
         class(b_t), intent(in) :: this
      end subroutine
   end interface
end module
module e_m
   use b_m, only : b_t
   type, extends(b_t), abstract :: e_t
   end type
end module
module c_m
   use e_m, only : e_t
   type, extends(e_t) :: c_t
   contains
      procedure, pass(this) :: sub => csub
   end type
contains
   subroutine csub( this )
      class(c_t), intent(in) :: this
      print *, "In csub: this%i = ", this%i
   end subroutine
end module
module d_m
   use c_m, only : c_t
   type, extends(c_t) :: d_t
   contains
      procedure, pass(this) :: sub => dsub
   end type
contains
   subroutine dsub( this )
      class(d_t), intent(in) :: this
      print *, "In dsub: this%i = ", this%i
   end subroutine
end module
program p
   use b_m, only : b_t
   use c_m, only : c_t
   use d_m, only : d_t
   class(b_t), allocatable :: foo
   class(b_t), allocatable :: bar
   allocate( c_t :: foo ) ; foo%i = 1
   call foo%sub()
   allocate( d_t :: bar ) ; bar%i = 2
   call bar%sub()
   stop
end program

As you indicated, a simple example like this won't reproduce the problem at first, the program output will be as expected - see below.  Thus refining the details further to mimic the exact pattern in your actual code is key.

 In csub: this%i =  1
 In dsub: this%i =  2

 

0 Kudos
Reply