- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page