"Procedure(intf) :: proc" where intf is another procedure is recursive?

"Procedure(intf) :: proc" where intf is another procedure is recursive?

An OOP sort of question. Consider the following snippet, where out of laziness I used the name of an existing procedure as the interface in a procedure statement in the contains bit of a abstract type definition. With 12.0.1.127 I get an error 6437 about a recursive call.

MODULE UsingAProcedureAsAnInterface
  IMPLICIT NONE  
  PRIVATE
  
  TYPE, PUBLIC, ABSTRACT :: Parent
    INTEGER :: comp
  CONTAINS
    PROCEDURE(one_proc_intf), DEFERRED :: OneProc
  END TYPE Parent
  
  TYPE, PUBLIC, EXTENDS(Parent), ABSTRACT :: Relay      
  CONTAINS
    PROCEDURE, NON_OVERRIDABLE :: OneProc => relay_proc    
    PROCEDURE(relay_proc), DEFERRED :: TwoProc        ! #A
    !PROCEDURE(two_proc_intf), DEFERRED :: TwoProc    ! #B    
  END TYPE Relay
  
  TYPE, PUBLIC, EXTENDS(Relay) :: EndPoint    
  CONTAINS
    PROCEDURE :: TwoProc => end_proc
  END TYPE EndPoint

  ABSTRACT INTERFACE
    SUBROUTINE one_proc_intf(obj)
      IMPORT :: Parent
      IMPLICIT NONE
      CLASS(Parent), INTENT(IN) :: obj
    END SUBROUTINE one_proc_intf

   ! (for use when #B is substituted for #A)
   SUBROUTINE two_proc_intf(obj)
      IMPORT :: Relay
      IMPLICIT NONE
      CLASS(Relay), INTENT(IN) :: obj
    END SUBROUTINE two_proc_intf
  END INTERFACE  
CONTAINS
  SUBROUTINE relay_proc(obj)
    CLASS(Relay), INTENT(IN) :: obj
    !****
    ! Some behaviour that we want common to all extensions of Relay.
    PRINT "('Relay::OneProc')"
    CALL obj%TwoProc
  END SUBROUTINE relay_proc
  
  SUBROUTINE end_proc(obj)
    CLASS(EndPoint), INTENT(IN) :: obj
    !****
    PRINT "('EndPoint::TwoProc')"
  END SUBROUTINE end_proc
END MODULE UsingAProcedureAsAnInterface

But my understanding (which might be wrong - note that recent gfortran 4.6 also complains about the same thing) is that this isn't a recursive call. "CALL obj%TwoProc" doesn't call relay_proc, it is a call to something that has to look like relay_proc which will be implemented by a extension of Relay.

Maybe? The work-around is simple (switch #A and #B), but I am lazy...

2 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

A very interesting question. If the binding wasn't deferred, then it could be recursive as the compiler could not guarantee that the binding was overridden. I was also thinking that one might declare another type extending Relay and overriding TwoProc with relay_proc, but that runs into other issues.

I don't see wording in the standard that excuses this case. You can also add RECURSIVE to the declaration of relay_proc and it will compile - that seems the simplest course to me.

Steve - Intel Developer Support

Leave a Comment

Please sign in to add a comment. Not a member? Join today