Skip to content

Instantly share code, notes, and snippets.

@szaghi
Created January 7, 2016 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save szaghi/f4f521b6130ee911348f to your computer and use it in GitHub Desktop.
Save szaghi/f4f521b6130ee911348f to your computer and use it in GitHub Desktop.
A (hopefully) simple test of mismatched abstract/concrete interfaces of Fortran abstract type. This should not compile at all
module adt_foo_class
implicit none
private
type, abstract, public :: adt_foo
private
contains
private
procedure(sym_operator), pass(lhs), deferred :: foo_multiply_foo
procedure(assignment), pass(lhs), deferred :: assign_foo
generic, public :: operator(*) => foo_multiply_foo
generic, public :: assignment(=) => assign_foo
endtype adt_foo
abstract interface
function sym_operator(lhs, rhs) result(operator_result)
import :: adt_foo
class(adt_foo), intent(IN) :: lhs
class(adt_foo), intent(IN) :: rhs
class(adt_foo), allocatable :: operator_result
endfunction sym_operator
subroutine assignment(lhs, rhs)
import :: adt_foo
class(adt_foo), intent(INOUT) :: lhs
class(adt_foo), intent(IN) :: rhs
endsubroutine assignment
endinterface
endmodule adt_foo_class
module foo_class
use adt_foo_class, only : adt_foo
implicit none
private
type, extends(adt_foo), public :: foo
private
integer, public :: a = 0
contains
private
procedure, pass(lhs) :: foo_multiply_foo
procedure, pass(lhs) :: assign_foo
endtype foo
contains
pure function foo_multiply_foo(lhs, rhs) result(opr)
class(foo), intent(IN) :: lhs
class(adt_foo), intent(IN) :: rhs
class(adt_foo), allocatable :: opr
allocate(foo :: opr)
select type(opr)
class is(foo)
opr = lhs
select type(rhs)
class is (foo)
opr%a = lhs%a * rhs%a
endselect
endselect
return
endfunction foo_multiply_foo
pure subroutine assign_foo(lhs, rhs)
class(foo), intent(INOUT) :: lhs
class(adt_foo), intent(IN) :: rhs
select type(rhs)
class is (foo)
lhs%a = rhs%a
endselect
return
endsubroutine assign_foo
endmodule foo_class
program foo_adt_test
use foo_class, only : foo
implicit none
type(foo) :: foo1, foo2, foo3
foo1 = foo(2)
foo2 = foo(3)
foo3 = foo1 * foo2
print "(I2)", foo3%a
stop
contains
endprogram foo_adt_test
@szaghi
Copy link
Author

szaghi commented Jan 7, 2016

In this example, both operator and assignment are mismatched between the abstract definition and the corresponding concrete extension: the abstract procedures are defined impure while the concrete extensions are defined pure.

GNU gfortran 5.2

Compiling with GNU gfortran (gcc v5.2), the compiler does not compile and provides:

→ gfortran foo_adt_test.f90
foo_adt_test.f90:52:13:

     opr = lhs
             1
Error: Subroutine call to ‘assignment’ at (1) is not PURE
foo_adt_test.f90:74:4:

 use foo_class, only : foo
    1
Fatal Error: Can't open module file ‘foo_class.mod’ for reading at (1): No such file or directory
compilation terminated.

Intel ifort 15.0.3

Compiling with Intel Fortran Compiler (v15.0.3), the compiler compile and provides the expected result (6):

→ ifort foo_adt_test.f90
→ a.out
 6

Which is the correct behavior?

Note

If you modify the example declaring pure the abstract assignment procedure, GNU gfrotran behaves like Intel Compiler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment