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

LEN_TRIM and PROTECTED issues

John4
Valued Contributor I
1,006 Views

Hi, I have a couple of questions:

When I try to compile the code below, I get the an error related to the declaration of b. Is the diagnostic correct? LEN_TRIM is an elemental function, so there shouldn't be a problem with that.

!---------------------------------------------------------------------------------------------------
module mod1
implicit none
type :: whatever
character(:), allocatable :: a
end type
contains
subroutine sub1(arg)
type(whatever), intent(IN) :: arg(:)
integer :: i
character(LEN = MAXVAL([(LEN_TRIM(arg(i)%a), i = 1, SIZE(arg))])) :: a
! character(LEN = MAXVAL(LEN_TRIM(arg%a))) :: b
end subroutine
end module mod1

!---------------------------------------------------------------------------------------------------

Also, I am getting an error related to the PROTECTED attribute (in the code below). I don't know much about interpretation of the standard, but I checked and the "variable definition context" restriction doesn't mention the FILE specifier in the OPEN statement ---it seems to me that the compiler is taking it as an INQUIRE statement.

!---------------------------------------------------------------------------------------------------

module mod1
implicit none
character(5), protected :: filename = 'afile'
end module mod1
module mod2
use mod1
implicit none
contains
subroutine readSomething()
continue
open (unit = 12345, file = filename, status = 'unknown', action = 'read')
close (12345)
end subroutine
end module mod2

0 Kudos
1 Solution
IanH
Honored Contributor III
1,006 Views
Quoting - John

character(:), allocatable :: array(:)


Here's my take - in the above, you've got one data object ("array"), which is of a single, specific type. That specific type has a single type name (CHARACTER) and also a single set of type parameters, which includes a single LEN type parameter represented by the first (:). It happens to be a deferred length type parameter, so it can change at run time, but there's still only one value for that LEN type parameter at an instant in time for that particular data object.

That object happens to be an array. Each element in that array has the same type as the array itself, so all elements have the same LEN type parameter at an instant in time in program execution.

For arrays of strings with lengths that vary within the array, consider something along the lines of:

TYPE string_wrapper
CHARACTER(:), ALLOCATABLE :: contents
END TYPE string_wrapper

TYPE(string_wrapper), ALLOCATABLE :: array(:)
ALLOCATE(array(4))
array(1)%contents = 'iso_varying_string'
array(2)%contents = 'still'
array(3)%contents = 'lives!'
array(4)%contents = '(sort of...)'

If you wanted to, with a bit of data hiding, some appropriate structure constructors, user defined operators and assignment, a few "forwarding" procedures as equivalents for the various intrinsics and a dash of user defined type io (when supported) you'd get something similar to what you were originally expecting in a relatively seamless way, including (if you really wanted) an elemental equivalent of TRIM.

What I'm describing is essentially an updated implementation of varying_string from iso_varying_string, that wraps a scalar deferred length character component rather than the customary array of single characters and, as a result, could be much more "natural". Someone may have already done it.

View solution in original post

0 Kudos
11 Replies
TimP
Honored Contributor III
1,006 Views
I don't see any error in the first segment when using the current ifort ia32 release. For the second, the message "....shall not appear as a definable variable in an INQUIRE statement..." does appear to show a bug.

0 Kudos
John4
Valued Contributor I
1,006 Views
Quoting - tim18
I don't see any error in the first segment when using the current ifort ia32 release. For the second, the message "....shall not appear as a definable variable in an INQUIRE statement..." does appear to show a bug.

Ups, sorry. I forgot to remove the comment in the line that causes the error. I should be:


!---------------------------------------------------------------------------------------------------
module mod1
implicit none
type :: whatever
character(:), allocatable :: a
end type
contains
subroutine sub1(arg)
type(whatever), intent(IN) :: arg(:)
integer :: i
character(LEN = MAXVAL([(LEN_TRIM(arg(i)%a), i = 1, SIZE(arg))])) :: a
character(LEN = MAXVAL(LEN_TRIM(arg%a))) :: b
end subroutine
end module mod1

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,006 Views

Try

character(LEN = MAXVAL(LEN_TRIM(arg(:)%a))) :: b

Jim Dempsey
0 Kudos
Steven_L_Intel1
Employee
1,006 Views
I'll report the PROTECTED issue to the developers.
0 Kudos
John4
Valued Contributor I
1,006 Views

Try

character(LEN = MAXVAL(LEN_TRIM(arg(:)%a))) :: b

Jim Dempsey

Using a slice, instead of the whole array, doesn't make any difference ---besides, I don't need a workaround (since my sample code already includes one, when declaring a); just a confirmation that the error thrown by the compiler is wrong... Or that the code is invalid and the compiler is free to do whatever it wants.

But thanks anyway for the "tip".

0 Kudos
Steven_L_Intel1
Employee
1,006 Views
In the first example, the compiler is dutifully enforcing a constraint of the standard. The error message wording comes directly from the standard. It makes perfect sense - until you bring allocatable scalars into the picture. I'll have to see if F2008 changes the wording here.
0 Kudos
John4
Valued Contributor I
1,006 Views
In the first example, the compiler is dutifully enforcing a constraint of the standard. The error message wording comes directly from the standard. It makes perfect sense - until you bring allocatable scalars into the picture. I'll have to see if F2008 changes the wording here.

That's fine... And regarding weird constraints in the standard, I have an additional question: I've found that if I declare an allocatable array of deferred length characters, the length of every component remains fixed, as in:

!----
character(:), allocatable :: array(:)
allocate (array(5), source = '')
do i = 1, 5

array(i) = 'something'
print *, array(i) !nothing is printed, since length is still zero
enddo
end

!----

It wouldn't surprise me if it's something required by the standard, just like (I suppose, the reason of) TRIM not being elemental, because the resulting arrays would have elements with different lengths. I vaguely remember having read a rule stating that array elements cannot have the allocatable attribute. But, is it true also in this case, or is it just a bug in the current version of the compiler?

0 Kudos
IanH
Honored Contributor III
1,007 Views
Quoting - John

character(:), allocatable :: array(:)


Here's my take - in the above, you've got one data object ("array"), which is of a single, specific type. That specific type has a single type name (CHARACTER) and also a single set of type parameters, which includes a single LEN type parameter represented by the first (:). It happens to be a deferred length type parameter, so it can change at run time, but there's still only one value for that LEN type parameter at an instant in time for that particular data object.

That object happens to be an array. Each element in that array has the same type as the array itself, so all elements have the same LEN type parameter at an instant in time in program execution.

For arrays of strings with lengths that vary within the array, consider something along the lines of:

TYPE string_wrapper
CHARACTER(:), ALLOCATABLE :: contents
END TYPE string_wrapper

TYPE(string_wrapper), ALLOCATABLE :: array(:)
ALLOCATE(array(4))
array(1)%contents = 'iso_varying_string'
array(2)%contents = 'still'
array(3)%contents = 'lives!'
array(4)%contents = '(sort of...)'

If you wanted to, with a bit of data hiding, some appropriate structure constructors, user defined operators and assignment, a few "forwarding" procedures as equivalents for the various intrinsics and a dash of user defined type io (when supported) you'd get something similar to what you were originally expecting in a relatively seamless way, including (if you really wanted) an elemental equivalent of TRIM.

What I'm describing is essentially an updated implementation of varying_string from iso_varying_string, that wraps a scalar deferred length character component rather than the customary array of single characters and, as a result, could be much more "natural". Someone may have already done it.

0 Kudos
Steven_L_Intel1
Employee
1,006 Views
Ian has it right.
0 Kudos
John4
Valued Contributor I
1,006 Views
Ian has it right.

So, as Ian said, we're going to need an updated version of iso_varying_string for that purpose (my suggested name is iso_module_for_yet_another_incomplete_feature)... Hopefully, it will be added to the language by the Fortran 2022 standard.

Thanks for the help!

0 Kudos
Steven_L_Intel1
Employee
1,006 Views
ISO_VARYING_STRING has been removed from the Fortran standard and will not return. Deferred-length character variables are in F2003 and supported by Intel Fortran 11.1. These are better than ISO_VARYING_STRING.
0 Kudos
Reply