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

Standard violation in generic type bound procedure

may_ka
Beginner
474 Views

Hi all.

This code:

Module Mod_LL_DT
  Implicit None
  Private
  Type, Public :: LLCont_DT
  contains
    Generic :: GetElement => GetElementByType,GetElementByPosition
    Procedure, PAss :: GetElementByType => SubGetElementByType
    Procedure, PAss :: GetElementByPosition => SubGetElementByPosition
  End type LLCont_DT
contains
  Subroutine SubGetElementByType(this,TSIn,TSOut)
    Implicit None
    Class(LLCont_DT), Intent(InOut) :: this
    Class(*), Intent(InOut), Pointer :: TSIn
    Class(*), Intent(Out), Pointer :: TSOut
  End Subroutine SubGetElementByType
  Subroutine SubGetElementByPosition(this,TSC,ISPos)
    Implicit None
    Class(LLCont_DT), Intent(InOut) :: this
    Class(*), Intent(InOut), Pointer :: TSC
    Integer(kind=8), Intent(In) :: ISPos
  End Subroutine SubGetElementByPosition
End Module Mod_LL_DT

compiles without error using ifort 17.07 and standard checking f08, f15, and f03

However, it does not compile with gfortran 8.1. I get the error message:

Generic :: GetElement => GetElementByType,GetElementByPosition
                            1
Error: ‘subgetelementbytype’ and ‘subgetelementbyposition’ for GENERIC ‘getelement’ at (1) are ambiguous

I filed a bug report to gcc and now the discussion is whether the standard should cover the function argument resolution or not.

If gcc is right, then ifort has a bug and I would have to adjust the code anticipating that upcoming versions of ifort will eliminate it.

Any suggestion appreciated.

Cheers

Karl

0 Kudos
9 Replies
FortranFan
Honored Contributor II
474 Views

@Karl,

My hunch is gfortran is correct from the standard point-of-view, that as far as I can tell, the standard does not offer a means to disambiguate the two procedures with respect to the GENERIC binding.  I suggest submitting a support request at the Intel OSC and have them review this closely; chances are a bug resolution will occur in Intel Fortran.

0 Kudos
may_ka
Beginner
474 Views

@FortranFan

Thanks. I am a bit supprised about the inability to contrast because if one where calling the bound routines directly, but with the wrong arguments (integer insteald of pointer and vice versa), the compiler picks that up as an error. I thought the generic bounding is resolved at compile time. That seems odd to me.

Cheers

0 Kudos
Harald
Beginner
474 Views

When checking for standard conformance, I tend to rely on NAG, and it accepts the code sample.

(Of course it tells you that kind=8 is not necessarily a valid kind, even if the value is commonly interpreted as the number of bytes of the representation.)

 

0 Kudos
IanH
Honored Contributor II
474 Views

The code is not conforming. 

Consider the case where the third argument is an integer pointer - the compiler wouldn't know which specific procedure to pick.

An integer is type compatible with CLASS(*), so the third argument is not distinguishable on type.  Pointer arguments are distinguishable from allocatable arguments, but they are not distinguishable from non-pointer arguments.


 

0 Kudos
may_ka
Beginner
474 Views

I am getting lost here. If the compiler cannot contrast between an unlimited polymorphic pointer and an integer pointer, the code below should compile

Module Mod_Test
  Implicit None
  Private
  Type, Public :: test
  contains
    Generic :: Get => GetA,GetB
    Procedure, PAss :: GetA => SubGetA
    Procedure, PAss :: GetB => SubGetB
  End type test
contains
  Subroutine SubGetA(this,TSInOut)
    Implicit None
    Class(test), Intent(InOut) :: this
    Class(*), Intent(InOut), Pointer :: TSInOut
  End Subroutine SubGetA
  Subroutine SubGetB(this,ISinout)
    Implicit None
    Class(test), Intent(InOut) :: this
    Integer(kind=8), Intent(InOut), Pointer :: ISinout
  End Subroutine SubGetB
End Module Mod_Test
Program AA
  use Mod_Test, only: Test
  Type(Test) :: x
  Class(*), pointer :: b
  integer(kind=8), pointer :: c
  call x%geta(b)
  call x%geta(c)
end Program AA

But it does not because the second subroutine call yields a compile time error

error #8300: If a dummy argument is allocatable or a pointer, and the dummy or its associated actual argument is polymorphic, both dummy and actual must be polymorphic with the same declared type or both must be unlimited polymorphic.   
  call x%geta(c)

It seems that the compiler destinguishes between an integer pointer and an unlimited polymorphic pointer. This should also hold when generic bindings are resolved??!!

0 Kudos
IanH
Honored Contributor II
474 Views

No.

There is a set of rules for how specific procedures must be distinguishable behind a generic interface, and a different set of rules for argument association.

The example in #6 breaks both sets.

The compiler is complaining about the latter - the argument association rules. Note that the error message talks about the property of an actual argument.

The requirements for how specific procedures must be distinguishable only consider the properties of the procedure definitions - when talking about arguments they only talk about dummy arguments.

 

 

0 Kudos
may_ka
Beginner
474 Views

Hi,

so pointer arguments are contrastable from allocatable arguments?? Then this code may reveal a bug in 17.07 and 18.03

Module Mod_Test
  Implicit None
  Private
  Type, Public :: test
  contains
    Generic :: Get => GetA,GetB
    Procedure, PAss :: GetA => SubGetA
    Procedure, PAss :: GetB => SubGetB
  End type test
contains
  Subroutine SubGetA(this,iin)
    Implicit None
    Class(test), Intent(InOut) :: this
    Integer(kind=8), Intent(In), Pointer :: iin
    write(*,*) "a"
  End Subroutine SubGetA
  Subroutine SubGetB(this,iin)
    Implicit None
    Class(test), Intent(InOut) :: this
    integer(kind=8), Intent(InOut), allocatable :: iin
    write(*,*) "b"
  End Subroutine SubGetB
End Module Mod_Test
Program AA
  use Mod_Test, only: Test
  Type(Test) :: x
  integer(kind=8), pointer :: c
  integer(kind=8), allocatable :: d
  call x%get(c)
  call x%get(d)
end Program AA

It compiles and runs with gfortran, but not with ifort 17.07 and 18.03

Cheers

0 Kudos
IanH
Honored Contributor II
474 Views

The pointer dummy argument is required to not have the INTENT(IN) attribute to be distinguishable from an allocatable argument (otherwise a potential ambiguity exists in the face of Fortran 2008's ability for pointer dummy arguments to be automatically pointer associated with an actual argument with the TARGET attribute). This requirement was introduced via a corrigenda.

If gfortran accepts the code as shown, then that is a bug in gfortran.

0 Kudos
may_ka
Beginner
474 Views

Thanks

0 Kudos
Reply