Dear great Intel Fortran Developers team,
I would like to report a possible bug in ifort 15.0.3.
I am trying to develop an OOP library that takes advantage of Abstract Calculus Pattern by means of an abstract type definition. In a very few words, the library defines an abstract type with some operators overloading deferred and it provides a procedure that operates on the abstract type. The concrete extensions of the abstract type implement only the type bound procedures deferred whereas the overloaded operators are defined by the abstract type. The real code is here https://github.com/Fortran-FOSS-Programmers/FOODiE/blob/master/src/lib/type_integrand.f90.
A minimal example raising the possible bug is reported below. There are 3 modules and 1 main program: 1) type_abstract_buggy provides the abstract type, 2) lib_abstract_buggy provides a procedure working on the abstract type that raises the possible bug, 3) type_buggy implements a concrete extension of the abstract type defining only the procedures for the operators overloading and 4) is the main program using the last 2 modules.
The expected results are:
Array:
1.00000000
2.00000000
3.00000000
Scalar: 3
Array:
2.00000000
4.00000000
6.00000000
Scalar: 3
Array:
4.00000000
8.00000000
12.0000000
Scalar: 3
but when compiling with ifort 15.0.3 complains with following errors.
ifort-bug.f90(58): error #6633: The type of the actual argument differs from the type of the dum
my argument. [BUG]
bug = scalar * bug
-----------------^
ifort-bug.f90(146): error #7013: This module file was not generated by any release of this compi
ler. [LIB_ABSTRACT_BUGGY]
use lib_abstract_buggy, only : raise_bug
----^
ifort-bug.f90(149): error #6457: This derived type name has not been declared. [BUGGY]
type(buggy) :: bug
-----^
ifort-bug.f90(151): error #6404: This name does not have a type, and must have an explicit type.
[BUG]
bug = buggy(array=[1., 2., 3.], scalar=3)
^
ifort-bug.f90(151): error #6632: Keyword arguments are invalid without an explicit interface.
[ARRAY]
bug = buggy(array=[1., 2., 3.], scalar=3)
------------^
ifort-bug.f90(151): error #6632: Keyword arguments are invalid without an explicit interface.
[SCALAR]
bug = buggy(array=[1., 2., 3.], scalar=3)
--------------------------------^
ifort-bug.f90(152): error #6406: Conflicting attributes or multiple declaration of name. [RAIS
E_BUG]
call raise_bug(bug=bug, scalar=2)
-----^
ifort-bug.f90(146): error #6580: Name in only-list does not exist. [RAISE_BUG]
use lib_abstract_buggy, only : raise_bug
-------------------------------^
ifort-bug.f90(147): error #6580: Name in only-list does not exist. [BUGGY]
use type_buggy, only : buggy
-----------------------^
compilation aborted for ifort-bug.f90 (code 1)
The compilation is done by: ifort -O0 -debug all -check all -warn all -traceback -assume realloc_lhs -std08 ifort-bug.f90
Note that the correct result is obtained by GNU gfortran 5.2.
Minimal example raising the possible compiler bug
module type_abstract_buggy implicit none private public :: abstract_buggy type, abstract :: abstract_buggy contains ! public methods procedure(abstract_printf), public, deferred :: printf generic, public :: operator(*) => buggy_multiply_scalar, scalar_multiply_buggy generic, public :: assignment(=) => buggy_assign_buggy ! private methods procedure(abstract_buggy_multiply_scalar), pass(lhs), private, deferred :: buggy_multiply_scalar procedure(scalar_multiply_abstract_buggy), pass(rhs), private, deferred :: scalar_multiply_buggy procedure(abstract_buggy_assign_abstract_buggy), pass(lhs), private, deferred :: buggy_assign_buggy endtype abstract_buggy abstract interface subroutine abstract_printf(self) import :: abstract_buggy class(abstract_buggy), intent(IN) :: self endsubroutine abstract_printf function abstract_buggy_multiply_scalar(lhs, rhs) result(multy) import :: abstract_buggy class(abstract_buggy), intent(IN) :: lhs integer, intent(IN) :: rhs class(abstract_buggy), allocatable :: multy endfunction abstract_buggy_multiply_scalar function scalar_multiply_abstract_buggy(lhs, rhs) result(multy) import :: abstract_buggy integer, intent(IN) :: lhs class(abstract_buggy), intent(IN) :: rhs class(abstract_buggy), allocatable :: multy endfunction scalar_multiply_abstract_buggy pure subroutine abstract_buggy_assign_abstract_buggy(lhs, rhs) import :: abstract_buggy class(abstract_buggy), intent(INOUT) :: lhs class(abstract_buggy), intent(IN) :: rhs endsubroutine abstract_buggy_assign_abstract_buggy endinterface endmodule type_abstract_buggy module lib_abstract_buggy use type_abstract_buggy, only : abstract_buggy implicit none private public :: raise_bug contains subroutine raise_bug(bug, scalar) class(abstract_buggy), intent(INOUT) :: bug integer, intent(IN) :: scalar call bug%printf() bug = bug * scalar call bug%printf() bug = scalar * bug call bug%printf() endsubroutine raise_bug endmodule lib_abstract_buggy module type_buggy use type_abstract_buggy, only : abstract_buggy implicit none private public :: buggy type, extends(abstract_buggy) :: buggy private real, dimension(:), allocatable :: array integer :: scalar=0 contains ! public methods procedure, pass(self), public :: printf ! private methods procedure, pass(lhs), private :: buggy_multiply_scalar procedure, pass(rhs), private :: scalar_multiply_buggy procedure, pass(lhs), private :: buggy_assign_buggy endtype buggy interface buggy procedure create_buggy endinterface contains pure function create_buggy(array, scalar) result(bug) real, dimension(:), intent(IN) :: array integer, intent(IN) :: scalar type(buggy) :: bug bug%array = array bug%scalar = scalar return endfunction create_buggy subroutine printf(self) class(buggy), intent(IN) :: self integer :: i print "(A)", "Array:" do i=1, size(self%array) print*, self%array(i) enddo print "(A,I5)", "Scalar: ", self%scalar endsubroutine printf function buggy_multiply_scalar(lhs, rhs) result(multy) class(buggy), intent(IN) :: lhs integer, intent(IN) :: rhs class(abstract_buggy), allocatable :: multy type(buggy), allocatable :: multy_tmp allocate(buggy :: multy_tmp) multy_tmp%array = lhs%array * rhs multy_tmp%scalar = lhs%scalar call move_alloc(multy_tmp, multy) return endfunction buggy_multiply_scalar pure function scalar_multiply_buggy(lhs, rhs) result(multy) integer, intent(IN) :: lhs class(buggy), intent(IN) :: rhs class(abstract_buggy), allocatable :: multy type(buggy), allocatable :: multy_tmp allocate(buggy :: multy_tmp) multy_tmp%array = rhs%array * lhs multy_tmp%scalar = rhs%scalar call move_alloc(multy_tmp, multy) return endfunction scalar_multiply_buggy pure subroutine buggy_assign_buggy(lhs, rhs) class(buggy), intent(INOUT) :: lhs class(abstract_buggy), intent(IN) :: rhs select type(rhs) class is(buggy) if (allocated(rhs%array)) lhs%array = rhs%array lhs%scalar = rhs%scalar endselect return endsubroutine buggy_assign_buggy endmodule type_buggy program ifort_bug use lib_abstract_buggy, only : raise_bug use type_buggy, only : buggy implicit none type(buggy) :: bug bug = buggy(array=[1., 2., 3.], scalar=3) call raise_bug(bug=bug, scalar=2) stop endprogram ifort_bug