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

Possible compiler bug when chaining defined operators

WileyOne
Novice
389 Views

Compiler: ifx (IFX) 2025.0.4

OS: Rock Linux 8.9 (Green Obsidian)

 

I believe the following is a bug for user-defined operators, and I do not see this issue in previous reports.

 

The issues involves using more than 1 defined operator in a row. The in-line, temporary variable created from "d1+d2" should be of type "dummy" and therefore call "add_dummy" when it is added to "d3". However, the output of seems to be of type "base" rather than "dummy" because "add_base" is called instead.

module DummyClass
    implicit none

    type, abstract :: base
        contains
        generic, public :: operator(+) => add_base
        procedure, public :: &
            add_base
    end type

    type, extends(base) :: dummy
        contains
        procedure, public :: &
            add_base => add_dummy
    end type

    contains

    function add_base(lhs,rhs) result(output)
        class(base), intent(in)  :: lhs
        class(base), intent(in)  :: rhs
        class(base), allocatable :: output
        stop 'should not get here'
    end function

    function add_dummy(lhs,rhs) result(output)
        class(dummy), intent(in) :: lhs
        class(base),  intent(in) :: rhs
        class(base), allocatable :: output
        allocate(dummy :: output)
    end function
end module

program main
    use DummyClass
    implicit none
    type(dummy) :: d1, d2, d3
    class(base), allocatable :: b

    b = d1+d2+d3

end program

 

Workaround

The first workaround is to make the "add" procedure deferred; this solves the issue.

module DummyClass
    implicit none

    type, abstract :: base
        contains
        generic, public :: operator(+) => add_base
        procedure(add_interface), deferred, public :: add_base
    end type

    abstract interface
        function add_interface(lhs,rhs) result(output)
            import
            class(base), intent(in)  :: lhs
            class(base), intent(in)  :: rhs
            class(base), allocatable :: output
        end function
    end interface

    type, extends(base) :: dummy
        contains
        procedure, public :: &
            add_base => add_dummy
    end type

    contains

    function add_dummy(lhs,rhs) result(output)
        class(dummy), intent(in) :: lhs
        class(base),  intent(in) :: rhs
        class(base), allocatable :: output
        allocate(dummy :: output)
    end function

end module

program main
    use DummyClass
    implicit none
    type(dummy) :: d1, d2, d3
    class(base), allocatable :: b

    b = d1+d2+d3

end program

 

In the case where we want "add_base" to behave as the default, however, this will not work. Instead, each step of the original in-line operation must be performed individually and saved off; this is the second workaround.

module DummyClass
    implicit none

    type, abstract :: base
        contains
        generic, public :: operator(+) => add_base
        procedure, public :: &
            add_base
    end type

    type, extends(base) :: dummy
        contains
        procedure, public :: &
            add_base => add_dummy
    end type

    contains

    function add_base(lhs,rhs) result(output)
        class(base), intent(in)  :: lhs
        class(base), intent(in)  :: rhs
        class(base), allocatable :: output
        stop 'should not get here'
    end function

    function add_dummy(lhs,rhs) result(output)
        class(dummy), intent(in) :: lhs
        class(base),  intent(in) :: rhs
        class(base), allocatable :: output
        allocate(dummy :: output)
    end function

end module

program main
    use DummyClass
    implicit none
    type(dummy) :: d1, d2, d3
    class(base), allocatable :: b1, b2

	b1 = d1+d2
    b2 = b1+d3

end program

 

Attached are all three sets of source code. Note that gfortran behaves as expected in all 3 cases. More importantly, I see nothing in the 2018 Fortran Standard that indicates chaining user-defined operators is illegal; see Section 15.4.3.4.2.

Labels (1)
0 Kudos
0 Replies
Reply