- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please take a look at the two simple module pairs as follows:
module test1
implicit none
private
public :: tp1
type, abstract :: tp1
private
! <Nothing.>
contains
private
procedure(isub), nopass, deferred :: sub
end type tp1
abstract interface
subroutine isub(var)
integer :: var
end subroutine isub
end interface
end module test1
module test2
use test1, only: tp1
implicit none
private
public :: tp2
type, extends(tp1) :: tp2
private
integer :: t
contains
private
procedure, nopass :: sub => mysub
end type tp2
contains
subroutine mysub(var)
integer :: var
print*, var
end subroutine mysub
end module test2
================================================
module test3
implicit none
private
public :: tp3
type, abstract :: tp3
private
! <Nothing.>
contains
private
procedure(ifunc), nopass, deferred :: ifunc
end type tp3
abstract interface
function ifunc(var)
integer :: ifunc
integer :: var
end function ifunc
end interface
end module test3
module test4
use test3, only: tp3
implicit none
private
public :: tp4
type, extends(tp3) :: tp4
private
integer :: t
contains
private
procedure, nopass :: func => myfunc
end type tp4
contains
function myfunc(var)
integer :: myfunc
integer :: var
myfunc = var
end function myfunc
end module test4
The only difference between the upper pair(test1 & test2) and the lower(test3 & test4) is the type-bound procedure: tp1 & tp2 has the subroutine while tp3 & tp4 has the function. The problem is the upper pair can be compiled without any warning or error but the lower cannot, the compiler says for the lower:
error #8322: A deferred binding is inherited by non-abstract type; It must be overridden. [IFUNC]
Notice that PRIVATE statement is set for all the CONTAINS block of the derived types(tp1& tp2 & tp3 & tp4), so why subroutine can override while function cannot ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan wrote:
Quote:
Blane J. wrote:
..The listdirected and DT-formed input and output (indicate by comment line 2,3,4,5 and 7.8.9.10) still generate the same error message I presented previously, but comment line 1 and 6 are just OK.
It looks to me like a bug in the Intel Fortran compiler, your code is alright.
Yes, I think so. I've reported this failure to OSC and wait for replies.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have not tried it, but in tp4 you define a function func, not ifunc. So the ifunc entry inherited from tp3 is not satisfied.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Note also, that in the subroutine case (where the binding names are the same) an error should also be reported - a private binding effectively cannot be overridden outside of the module that defines the type with the private binding. This behaviour has been discussed on the forums in the last year or two - the specified behaviour resulted in-part from a language interp, and it is possible compiler may not have caught up with the results of that interp and subsequent bug reports yet.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Arjen Markus wrote:
I have not tried it, but in tp4 you define a function func, not ifunc. So the ifunc entry inherited from tp3 is not satisfied.
The procedure name in tp3 is a mistake, it should be func, thanks Arjen Markus. correct it but the problem still exist...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ianh wrote:
Note also, that in the subroutine case (where the binding names are the same) an error should also be reported - a private binding effectively cannot be overridden outside of the module that defines the type with the private binding. This behaviour has been discussed on the forums in the last year or two - the specified behaviour resulted in-part from a language interp, and it is possible compiler may not have caught up with the results of that interp and subsequent bug reports yet.
Yes, lanH, there's something more I would wonder. In the subroutine case, if the PRIVATE keyword in tp1 is an attribute as:
procedure(isub), private, nopass, deferred :: sub
rather than a statement, the compiler can recognize the error and report:
error #8322: A deferred binding is inherited by non-abstract type; It must be overridden.
further more, If the PRIVATE statement in tp1 remains, but the PRIVATE in tp2 is omitted(which means all the type-bound procedures in tp2 is PUBLIC), the subroutine case can be compiled as well. Private bindings in abstract type would never be override, so I wonder if the DEFERRED attribute impilies PUBLIC attribute for the specified procedure regradless of PRIVATE statement ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Blane J. wrote:If you are seeing a difference based on whether PRIVATE for a bindings is explicitly specified for the binding or based on the default accessibility for bindings of the type, then that would be a compiler bug.
Yes, lanH, there's something more I would wonder. In the subroutine case, if the PRIVATE keyword in tp1 is an attribute as:
procedure(isub), private, nopass, deferred :: subrather than a statement, the compiler can recognize the error and report:
error #8322: A deferred binding is inherited by non-abstract type; It must be overridden.
further more, If the PRIVATE statement in tp1 remains, but the PRIVATE in tp2 is omitted(which means all the type-bound procedures in tp2 is PUBLIC), the subroutine case can be compiled as well. Private bindings in abstract type would never be override, so I wonder if the DEFERRED attribute impilies PUBLIC attribute for the specified procedure regradless of PRIVATE statement ?
Private bindings can be overridden within the module (or its submodule descendants) that defines the type, they just cannot be overridden outside of the defining module.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think so, may someone from Intel can see this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Blane J.,
I think there are one or more issues with Intel Fortran compiler for which you can submit incidents at the Intel's Online Service Center (OSC): https://supporttickets.intel.com/?lang=en-US in addition to a possible typo in one line of your code:
- On line 12 of your second example involving a FUNCTION scenario, did you mean a DEFERRED PROCEDURE of 'func' instead of 'func' i.e., "procedure(ifunc), nopass, deferred :: func"?
- See this thread: https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/681705.
Perhaps Intel Fortran team can update readers here on the status of the implementation of the findings from interp F08/0052
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan wrote:
@Blane J.,
I think there are one or more issues with Intel Fortran compiler for which you can submit incidents at the Intel's Online Service Center (OSC): https://supporttickets.intel.com/?lang=en-US in addition to a possible typo in one line of your code:
- On line 12 of your second example involving a FUNCTION scenario, did you mean a DEFERRED PROCEDURE of 'func' instead of 'func' i.e., "procedure(ifunc), nopass, deferred :: func"?
- See this thread: https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux....
Perhaps Intel Fortran team can update readers here on the status of the implementation of the findings from interp F08/0052
For the first issue, yes, it is a mistake as I mentioned in Quote #4.
For the second, I have read about the thread and it has the question and discuession I'm just confusing. Unfortunately it seems the problem has not been fixed yet, thanks FortranFan.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In addition, I'd like to ask if the generic binding which bind user-defined I/O procedures cannot be inherited ?
module test1
implicit none
private
public :: tp1
type, abstract :: tp1
private
! <Nothing.>
contains
private
generic, public :: write(unformatted) => unformattedwrite
procedure(iunformattedwrite), public, pass, deferred :: unformattedwrite
end type tp1
abstract interface
subroutine iunformattedwrite (var,unit,iostat,iomsg)
import tp1
class(tp1), intent(in) :: var
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*),intent(inout) :: iomsg
end subroutine iunformattedwrite
end interface
end module test1
module test2
use test1, only: tp1
implicit none
private
public :: tp2
type, extends(tp1) :: tp2
private
integer :: t
contains
private
procedure, public, pass :: unformattedwrite => output
end type tp2
contains
subroutine output (var,unit,iostat,iomsg)
implicit none
class(tp2), intent(in) :: var
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*),intent(inout) :: iomsg
write(unit, IOSTAT=iostat, IOMSG=iomsg) var % t
end subroutine output
end module test2
program main
use test2, only: tp2
implicit none
type(tp2) :: s
write(*,*) s
end program main
tp1 has a generic unformatted output binding( write(unformatted) ), it refers to the public binding procedure(unformattedwrite) which is deferred and implemented concreate in the extended type tp2. Note tp1 and tp2 both have the unforamttedwrite procedure PUBLIC. If this is correct, tp2 should have inherited the generic binding from tp1 and output an instance of tp2 should be OK. but the compile time error message says:
error #5521: A derived-type object in an input/output list cannot have inaccessible components unless a suitable user-defined input/output procedure is available.
Is the generic binding not inherited or something else ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The list directed write statement in the main program is a formatted write statement. The provided binding is only for unformatted writes.
("Formatted" means "formatted so humans can read it". The format specification for the list directed write statement is `*`. An unformatted write statement has no format specification, and produces "binary stuff" in the file that is generally not considered human readable.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try:
write(*,'(DT)') s
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
Try:
write(*,'(DT)') s
Jim Dempsey
Jim,
What IanH in his own inimitable, cryptic style was informing the OP was to include a defined output procedure binding for WRITE(FORMATTED) that is missing in the derived type shown in Quote #10 and which will be needed whether it is "write(*,*) s" or "write(*,'(dt)') s" statements.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks lanH, Jim and FortranFan. I see the clerical mistake. I then implemented all the input/output procedures in case of failure, show as below:
module test1
implicit none
private
public :: tp1
type, abstract :: tp1
private
! <nothing.>
contains
private
generic, public :: read(formatted) => formattedread
procedure(iformattedread), public, pass, deferred :: formattedread
generic, public :: read(unformatted) => unformattedread
procedure(iunformattedread), public, pass, deferred :: unformattedread
generic, public :: write(formatted) => formattedwrite
procedure(iformattedwrite), public, pass, deferred :: formattedwrite
generic, public :: write(unformatted) => unformattedwrite
procedure(iunformattedwrite), public, pass, deferred :: unformattedwrite
end type tp1
abstract interface
subroutine iformattedread(var, unit, iotype, list, iostat, iomsg)
import tp1
class(tp1), intent(inout) :: var
integer, intent(in) :: unit
character(*), intent(in) :: iotype
integer, dimension(:), intent(in) :: list
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
end subroutine iformattedread
subroutine iunformattedread(var, unit, iostat, iomsg)
import tp1
class(tp1), intent(inout) :: var
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
end subroutine iunformattedread
subroutine iformattedwrite(var, unit, iotype, list, iostat, iomsg)
import tp1
class(tp1), intent(in) :: var
integer, intent(in) :: unit
character(*), intent(in) :: iotype
integer, dimension(:), intent(in) :: list
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
end subroutine iformattedwrite
subroutine iunformattedwrite(var,unit,iostat,iomsg)
import tp1
class(tp1), intent(in) :: var
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
end subroutine iunformattedwrite
end interface
end module test1
module test2
use test1, only: tp1
implicit none
private
public :: tp2
type, extends(tp1) :: tp2
private
integer :: t
contains
private
procedure, public, pass :: formattedread => formattedreadsub
procedure, public, pass :: unformattedread => unformattedreadsub
procedure, public, pass :: formattedwrite => formattedwritesub
procedure, public, pass :: unformattedwrite => unformattedwritesub
end type tp2
contains
subroutine formattedreadsub(var, unit, iotype, list, iostat, iomsg)
implicit none
class(tp2), intent(inout) :: var
integer, intent(in) :: unit
character(*), intent(in) :: iotype
integer, dimension(:), intent(in) :: list
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
if(iotype == 'listdirected' .or. iotype == 'dt')then
read(unit, *, IOSTAT=iostat, IOMSG=iomsg) var % t
end if
end subroutine formattedreadsub
subroutine unformattedreadsub(var, unit, iostat, iomsg)
implicit none
class(tp2), intent(inout) :: var
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
read(unit, IOSTAT=iostat, IOMSG=iomsg) var % t
end subroutine unformattedreadsub
subroutine formattedwritesub(var, unit, iotype, list, iostat, iomsg)
implicit none
class(tp2), intent(in) :: var
integer, intent(in) :: unit
character(*), intent(in) :: iotype
integer, dimension(:), intent(in) :: list
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
if(iotype == 'listdirected' .or. iotype == 'dt')then
write(unit, *, IOSTAT=iostat, IOMSG=iomsg) var % t
end if
end subroutine formattedwritesub
subroutine unformattedwritesub(var,unit,iostat,iomsg)
implicit none
class(tp2), intent(in) :: var
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
write(unit, IOSTAT=iostat, IOMSG=iomsg) var % t
end subroutine unformattedwritesub
end module test2
program main
use test2, only: tp2
implicit none
type(tp2) :: s
open(unit=100, file="100.txt", form="unformatted", status = "replace")
open(unit=101, file="101.txt", form="formatted", status = "replace")
write(100) s ! <-- 1.
write(*,*) s ! <-- 2.
write(*,"(DT)") s ! <-- 3.
write(101,*) s ! <-- 4.
write(101,"(DT)") s ! <-- 5.
close(100)
close(101)
open(unit=100, file="100.txt", form="unformatted", status = "old")
open(unit=101, file="101.txt", form="formatted", status = "old")
read(100) s ! <-- 6.
read(*,*) s ! <-- 7.
read(*,"(DT)") s ! <-- 8.
read(101,*) s ! <-- 9.
read(101,"(DT)") s ! <-- 10.
close(100)
close(101)
end program main
Point me out if I'm wrong. The listdirected and DT-formed input and output (indicate by comment line 2,3,4,5 and 7.8.9.10) still generate the same error message I presented previously, but comment line 1 and 6 are just OK.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Blane J. wrote:
..The listdirected and DT-formed input and output (indicate by comment line 2,3,4,5 and 7.8.9.10) still generate the same error message I presented previously, but comment line 1 and 6 are just OK.
It looks to me like a bug in the Intel Fortran compiler, your code is alright.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan wrote:
Quote:
Blane J. wrote:
..The listdirected and DT-formed input and output (indicate by comment line 2,3,4,5 and 7.8.9.10) still generate the same error message I presented previously, but comment line 1 and 6 are just OK.
It looks to me like a bug in the Intel Fortran compiler, your code is alright.
Yes, I think so. I've reported this failure to OSC and wait for replies.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page