Quantcast
Channel: Intel® Software - Intel® Fortran Compiler for Linux* and macOS*
Viewing all articles
Browse latest Browse all 2746

Possible bug on abstract type

$
0
0

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

 


Viewing all articles
Browse latest Browse all 2746

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>