- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello again!
The following abstract derived-type with ABSTRACT INTERFACE causes us (me and the the Intel compiler) some trouble again.
It is about a DEFERRED FUNCTION 'make_array' with an automatic array as return value. The shape of the automatic array is obtained from a call to an other DEFERRED FUNCTION 'get_length'. Since I am not super experienced in Fortran, I am not sure if that is standard-comforming (having function calls as dimension declarator for automatic arrays). However, the compiler wasn't much of help to me this time: It just stopped with a segmentation violation (and kindly asked me to report this). So here it is:
[fortran]
module m
implicit none
type, abstract :: abstract_type
integer :: length
contains
procedure(get_length_interf), deferred :: get_length
procedure(make_array_interf), deferred :: make_array
end type
abstract interface
! returns a dynamic array length
pure function get_length_interf(this)
import abstract_type
implicit none
class(abstract_type), intent(in) :: this
integer :: get_length_interf
end function
! returns automatic array,
! array length is determined by a call to get_length()
function make_array_interf(this)
import abstract_type
implicit none
class(abstract_type), intent(in) :: this
integer :: length
integer, dimension( this%get_length() ) :: make_array_interf ! CRASH
! **Internal compiler error: segmentation violation signal raised**
! however, dimension( get_length_interf(this) ) works fine.
end function
end interface
end module
[/fortran]
Best regards, and thanks for any helpful advice
Ferdinand
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe that the use of a type-bound procedure should work here. I have escalated this to the developers as DPD200241137. While you are correct that substituting the "direct" call to the function allows it to compile, I find that I can't turn this into anything usable as if I extend the type and supply the overriding function with a dimension based on the other overriddn type-bound function, the compiler complains that the shapes of the function results aren't the same. I think this too is incorrect and have asked the developers to fix that.
I will let you know of any progress on this matter. Thanks for the nice example.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for your quick and informative answer again, Steve!
I also didn't find a simple and elegant workaround yet. In my case, the question is:
How to return private array data (from an abstract derived type), having dimension given in an other private type-bound variable? As Fortran doesn't provide the protected attribute (for derived-type components), the only way I found to achieve this is a public get-function as in the example. An other approach, using allocatable arrays, turned out to be much slower over the use of automatic arrays (is this generally true?).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think you will have better luck here with allocatable arrays. Yes, this would be slower if the routine didn't do much work and was called a lot, but it is more likely to work correctly. Array-valued functions where the array size depends on a dummy argument have long been a source of problems.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I stumbled about the same problem as I wanted to make use of such a function in my class hierarchy and can make three comments on this:
1) From my current understanding of the Fortran2003/2008 standard the desired behaviour (unfortunately) is not valid. We have the following requirement for overriding tpbs:
The overriding and overridden type-bound procedures shall satisfy the following conditions:
- ...
- Either both shall be subroutines or both shall be functions having the same result characteristics (12.3.3).
- ...
where a part of the result characteristics appears to be that
If a function result is an array that is not allocatable or a pointer, its shape is a characteristic.
The shape is given by the array's rank plus its extents in the individual dimensions. That rules out use of a specification function which returns a different value for each child class and likely even a function returning a value unknown at compile time (but see commen 3 below).
2) In ifort version 14.0.1 the problem of the internal compiler error appears to be fixed. When I try to compile the above code I get the following error message:
error #8497: Illegal use of a procedure name in an expression, possibly a function call missing parenthesis. [GET_LENGTH]
integer, dimension( this%get_length() ) :: make_array_interf
-------------------------------------^
compilation aborted for Issue-368481.f90 (code 1)
Compiling a slightly different example (given below) I get a more expressive error message:
example.f90(15): error #8280: An overriding binding and its corresponding overridden binding must both be either subroutines or functions with the same result type, kind, and shape. [GET_ARRAY]
procedure :: get_array => get_array_son
------------------^
example.f90(21): error #8280: An overriding binding and its corresponding overridden binding must both be either subroutines or functions with the same result type, kind, and shape. [GET_ARRAY]
procedure :: get_array => get_array_daughter
------------------^
compilation aborted for example.f90 (code 1)
[fortran]module classes
implicit none
type, abstract :: base_class
integer :: varnum
contains
procedure(pvf_get_num), nopass, deferred :: get_num
procedure(pvf_get_array), pass, deferred :: get_array
end type base_class
type, extends(base_class) :: son_class
contains
procedure, nopass :: get_num => get_num_son
procedure :: get_array => get_array_son
end type
type, extends(base_class) :: daughter_class
contains
procedure, nopass :: get_num => get_num_daughter
procedure :: get_array => get_array_daughter
end type daughter_class
abstract interface
pure function pvf_get_num() result(num)
integer :: num
end function pvf_get_num
function pvf_get_array( this ) result(array)
import base_class
class(base_class), intent(in) :: this
! integer, dimension( this%varnum ) :: array
integer, dimension( this%get_num() ) :: array
end function pvf_get_array
end interface
contains
pure function get_num_son() result(num)
integer :: num
num = 4
end function get_num_son
pure function get_num_daughter() result(num)
integer :: num
num = 9
end function get_num_daughter
function get_array_son( this ) result(array)
class(son_class), intent(in) :: this
! integer, dimension( this%varnum ) :: array
integer, dimension( this%get_num() ) :: array
array = 0
array( this%varnum ) = 1
end function get_array_son
function get_array_daughter( this ) result(array)
class(daughter_class), intent(in) :: this
! integer, dimension( this%varnum ) :: array
integer, dimension( this%get_num() ) :: array
array = 0
array( this%varnum ) = 2
end function get_array_daughter
end module classes[/fortran]
3) When I replace this%get_num() in the example above by base class component this%varnum ifort (both 13.1.2 and 14.0.1) compiles without problem and I can also execute a program using the module. Thus, either my interpretation of the standard is incorrect, or ifort is generous here.
Cheers
mmm
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello mmm,
thank you for your investigations! Now what confuses me is that, according to your interpretation, subprograms with automatic arrays (which depend in their shape on dummy arguments) can never be overriden. To me this looks like a serious restriction and surprised me, so I also looked into the standard at the passage (1) you quoted. Especially the following sentence looks promising:
112.2.2 Characteristics of function results[..] If a function result is an array that is not allocatable or a pointer, its shape is a characteristic. If [..] a bound of a function result array is not an initialization expression, the exact dependence on the entities in the expression is a characteristic.[..]
As I understand that second sentence (highlighted by me), the bounds may depend on some entities (like this%length) and only must evaluate to the similar bounds for similar values of those entities, which is exactly the case we encountered here ('this' may be one of parent / extended type).
However, as you pointed out, the first sentence seems to restricts the choice of bounds by fixing the extent (ubound-lbound+1) per dimension? Or does, on the contrary, the second sentence relax the condition of the first?
I'd appreciate some guidance in understanding this part since I 'm not a native Fortran speaker - plus I don't want to rely on the ifort's generosity in that point... ;-)
With regards, Ferdinand
PS: Your workaround with accessing the component (this%varnum) directly instead of using a getter-function is the same I used. However, in that case, all types must be declared in the same module (if this%varnum is private) and one cannot extend the class without modifying the module which contains the abstract parent - since Fortran can only control visibility over modules, not e.g., by 'family'. Which looks like a little design flaw to me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Ferdinand,
thanks for reading the standard more carefully than I did. I think that you might well be right. The second sentence could indicate that what we would like to accomplish is actually valid Fortran. However, like you I do not really dare to attempt a final interpretation as this is too far out off my area of expertise. At least it would explain why the variant with the derived type component works.
Talking of portability (hope we are allowed to mention other compilers here ;-) your sample code as well as my example above compiles with nagfor 5.3.1(907). However, I have problems in my actual code which has a deeper inheritance hierarchy and a rank-3 array. With gfortran (4.7.1 and 4.8.2) both examples also generate an internal compiler error, so I filed a bug report with them.
Concerning your remark on the visibility of components, I wouldn't call that a little design flaw. IMHO the fact that there is no possibility to allow that extended types access private components of their parents, if they are not specified within the same module, is a major design flaw. If we think in terms of large class hierarchies for larger software projects I want to use data hiding for reasons of security/maintainability. However, putting all source code directly or via some form on include (Fortran or preprocessing) into one module as the sole possibility to achieve this, is of little appeal.
Cheers
mmm
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page