- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a code with using nested derived types where some "leaf" variables have rather long names. To keep the code readable I often copy scalar variables to much shorter local variables and use "associate" statement to do the same with the arrays. That works great except for "allocated" function which does not seem to work with associated variables.
For example, in the code:
program associate_test
implicit none
integer, allocatable :: ivec(:)
allocate ( ivec(5) )
associate ( jvec => ivec )
if (allocated(jvec)) then
jvec = 0
end if
end associate
end program
the variable "ivec" is really some very long name with couple "%" symbols. The above code does not compile, giving me the following errors:
1>------ Build started: Project: line_test (IFX), Configuration: Release x64 ------
Compiling with Intel® Fortran Compiler 2024.2.1 [Intel(R) 64]...
test.f90
test.f90(7): error #7397: The argument of the ALLOCATED inquiry intrinsic function should have the ALLOCATABLE attribute. [JVEC]
test.f90(7): error #8306: Associate name defined in ASSOCIATE or SELECT TYPE statements doesn't have ALLOCATABLE or POINTER attribute. [JVEC]
compilation aborted for test.f90 (code 1)
In this toy example I can easily change "allocated(jvec)" to "allocated(ivec)" and it will compile, but I am trying to understand if I am doing something wrong here. The message "Associate name defined in ASSOCIATE [] statement doesn't have ALLOCATABLE [] attribute. [JVEC]" suggests that I can add allocatable attribute to associate variable "jvec" somehow. How do I do that?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, it doesn't suggest that. The standard says that associate names don't have ALLOCATABLE or POINTER even if the selector does, and you can't change that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, so you are saying that it is by design (standard) that I can use my new short name ("jvec") with any other intrinsic array function like SIZE, MAXVAL, SHAPE, RESHAPE, MATMUL, etc. but for ALLOCATED I need to use the original long variable name ("ivec"). It is odd that one function will be singled out like that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's not one function - there are many other things that being allocatable or pointer allow, such as reallocation on intrinsic assignment or pointer assignment. The wording in the standard is as follows (emphasis mine):
Within an ASSOCIATE, CHANGE TEAM, or SELECT TYPE construct, each associating entity has the same rank as its associated selector. The lower bound of each dimension is the result of the intrinsic function LBOUND (16.9.119) applied to the corresponding dimension of selector. The upper bound of each dimension is one less than the sum of the lower bound and the extent. The associating entity does not have the ALLOCATABLE or POINTER attributes; it has the TARGET attribute if and only if the selector is a variable and has either the TARGET or POINTER attribute.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maybe the logic of the program is flawed and you should not ever be associating something is is not allocated ? So ...
program associate_test
implicit none
integer, allocatable :: ivec(:)
allocate ( ivec(5) )
if (allocated(ivec)) then
associate ( jvec => ivec )
jvec = 0
end associate
end if
end program
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I guess my issue is that I am using associate statement to give short names for variables where using full name makes code hard to read. Since I very rarely use array-slices or other more complicated associations, in most cases the behavior is as if I was using C macro expansion, with this single exception (that I found) of allocated function.
I guess I should stop thinking about it as a macro, and than 5his behavior would not be surprising.
Thank you all for help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In light of @Steve_Lionel reply I suggest you consider using contained functions to perform the non-associated query and allocate/deallocate
associate(ivec => through%the%woods%and%over%the%hill%ivec)
...
if(ivecIsAllocate()) then
! do this
else
if(ivecAllocate(nThings) /=0) stop "allocation error"
endif
contains
function ivecIsAllocate() result(ret)
ret = isAllocated(through%the%woods%and%over%the%hill%ivec)
end function ivecIsAllocate()
function ivecAllocate(n) result(ret)
integer :: ret
allocate(through%the%woods%and%over%the%hill%ivec(n), stat=ret)
end function ivecAllocate
...
Or place these functions in a module.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As andrew_4619 perhaps subtly says, if the selector is not allocated, you must not execute any part of an associate construct with that selector (F2023 19.5.1.6p2). Testing the allocation status from within the construct is pointless - if the selector is not associated then the program is already exploding from a conformance point of view.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page