Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Use of deferred type parameter and ALLOCATE

93 views
Skip to first unread message

kar...@comcast.net

unread,
Jun 7, 2009, 2:30:43 PM6/7/09
to
All,

I've been working on an implementation of the Fortran 2003 ALLOCATE
statement
for inclusion in gfortran. This adds both the typespec and SOURCE=
features. To
complete the implementation, it appears that I need to first
implement the deferred
type parameter. In reading through Metcalf, Reid, and Cohen, they
give the example

character(:), allocatable :: x(:)
....
allocate(character(n) :: x(m))

where n and m are presumably previously defined. They state that
after ALLOCATE,
x is an array of m strings with length n. This, I understand. I was
wondering if the
following code is valid Fortran 2003

program test
implicit none
character(:), allocatable :: fmt, str
allocate(character(3) :: fmt)
fmt = 'abcdef'
str = 'zyx'
print *, trim(fmt), trim (str) ! 'abczyx'
deallocate(fmt)
allocate(character(len=6) :: fmt)
fmt = 'abcdef'
str = 'zyxwvu'
print *, trim(fmt), trim (str) ! 'abcdefzyxwvu'
end program test

Any insight would be appreciate.

--
steve

Richard Maine

unread,
Jun 7, 2009, 2:57:19 PM6/7/09
to
<kar...@comcast.net> wrote:

> I was wondering if the
> following code is valid Fortran 2003
>
> program test
> implicit none
> character(:), allocatable :: fmt, str
> allocate(character(3) :: fmt)
> fmt = 'abcdef'
> str = 'zyx'
> print *, trim(fmt), trim (str) ! 'abczyx'
> deallocate(fmt)
> allocate(character(len=6) :: fmt)
> fmt = 'abcdef'
> str = 'zyxwvu'
> print *, trim(fmt), trim (str) ! 'abcdefzyxwvu'
> end program test
>
> Any insight would be appreciate.

Looks fine and relatively straightforward (in terms of the standard) to
me. I might note that the TRIM() invocations are superfluous- valid, but
superfluous.

Besides the feature of allowing allocation of character length at all,
the other "interesting" thing illustrated here is the f2003 feature of
allocation on assignment. The assignment statement will allocate or
reallocate an allocatable variable on the left-hand side to match the
expression.

Thus, when you assign 'abcdef' to fmt, fmt is reallocated to length 6.
The fact that it was previously allocated to length 3 does not matter.

Note that this reallocation on assignment applies to allocatable arrays
as well.

Since you asked for insight, let me note what I think is an insightful
case that the code above does not illustrate. Consider

...
allocate(character(16):: fmt)
fmt(:) = 'abc'
write (*,*) fmt
fmt = 'abc'
write (*,*) fmt

In the first assignment, the left-hand side is not allocatable. Fmt is
allocatable, but a substring of it is not. Fmt(:) is a substring; it is
a substring that has all of the characters, but is still a substring and
thus is not allocatable. Thus, the "old" rules for character assignment
still apply; fmt is blank-padded to the previously allocated length of
16 characters.

In the second assignment, the left-hand side is allocatable and thus is
reallocated to the length of the expression - namely 3.

This reallocation behavior is compatable with previous standards because
it applies only to allocatable length strings, which did not exist in
previous standards.

This behavior makes allocatable-length strings behave much more in
accordance with widespread intuition about how strings ought to behave:
if you assign 'abc' to such a string, then the string ends up with the
value 'abc' rather than some truncated or padded value.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain

Richard Maine

unread,
Jun 7, 2009, 3:09:56 PM6/7/09
to
Richard Maine <nos...@see.signature> wrote:

> Besides the feature of allowing allocation of character length at all,
> the other "interesting" thing illustrated here is the f2003 feature of
> allocation on assignment. The assignment statement will allocate or
> reallocate an allocatable variable on the left-hand side to match the
> expression.

...


> Since you asked for insight, let me note what I think is an insightful
> case that the code above does not illustrate.

Oh. And another case that an implementor needs to note is the case where
the left-hand side and the expression agree on length and thus
reallocation is not needed. Do not be tempted to simplify things to the
point of just always doing a reallocation anyway. In addition to the
reallocation being superfluous and thus inefficient when the length is
already correct, the standard actually forbids the superfluous
reallocation (not quite in those terms, but in effect) in some cases. In
particular, if the allocatable variable has the TARGET attribute and is
the target of some pointers, it is required to still remain the target
of those pointers in the case where reallocation is not needed.

If reallocation is needed, then "of course", any such pointers would get
an undefined allocation status, just as they would for any other case of
their target becoming deallocated (and subsequently allocated again, but
that doesn't matter) other than via the pointer.

glen herrmannsfeldt

unread,
Jun 7, 2009, 4:29:43 PM6/7/09
to
Richard Maine <nos...@see.signature> wrote:
< Richard Maine <nos...@see.signature> wrote:

<> Besides the feature of allowing allocation of character length at all,
<> the other "interesting" thing illustrated here is the f2003 feature of
<> allocation on assignment. The assignment statement will allocate or
<> reallocate an allocatable variable on the left-hand side to match the
<> expression.

<> Since you asked for insight, let me note what I think is an insightful


<> case that the code above does not illustrate.

< Oh. And another case that an implementor needs to note is the case where
< the left-hand side and the expression agree on length and thus
< reallocation is not needed. Do not be tempted to simplify things to the
< point of just always doing a reallocation anyway. In addition to the
< reallocation being superfluous and thus inefficient when the length is
< already correct, the standard actually forbids the superfluous
< reallocation (not quite in those terms, but in effect) in some cases.

As usual, it is too late, but I find reallocate on assignment without
any hint that it is being done confusing and likely to cause problems.

The explicit substring to avoid it would seem to work, but again
is confusing and not especially obvious. I might have suggested that
variables have the REALLOCATABLE attribute such that they were available
for allocate on assignment, otherwise they weren't. That adds only
two letters, yet affirms that the programmer expects allocate on
assignment. Oh well. Also, there is extra overhead on all such
assignments to check that the size did or didn't change, and
to reallocate appropriately.

For comparison, the C realloc() function explicitly asks for
reallocation. It is given the old pointer (or NULL in which case
a normal malloc() is done), and returns the new pointer (or NULL
if realloc failed). The implementation is allowed to, but not
required to, reallocate in place. On many systems if the allocation
is at the end of allocated memory it can be extended in place,
avoiding a copy of the data. (In a read/realloc loop of a large
array it is likely that after a few iterations the space will be
at the end and realloc() in place.) Even in the case of the same
or smaller size, the returned pointer might be different. One is
not allowed to compare the returned pointer to the previous
(now deallocated) pointer. (No operations, including compare,
are allowed for pointers to previously allocated space.)

-- glen

kar...@comcast.net

unread,
Jun 7, 2009, 4:50:48 PM6/7/09
to
On Jun 7, 12:09 pm, nos...@see.signature (Richard Maine) wrote:
> Richard Maine <nos...@see.signature> wrote:
> > Besides the feature of allowing allocation of character length at all,
> > the other "interesting" thing illustrated here is the f2003 feature of
> > allocation on assignment. The assignment statement will allocate or
> > reallocate an allocatable variable on the left-hand side to match the
> > expression.
> ...
> > Since you asked for insight, let me note what I think is an insightful
> > case that the code above does not illustrate.
>
> Oh. And another case that an implementor needs to note is the case where
> the left-hand side and the expression agree on length and thus
> reallocation is not needed. Do not be tempted to simplify things to the
> point of just always doing a reallocation anyway. In addition to the
> reallocation being superfluous and thus inefficient when the length is
> already correct, the standard actually forbids the superfluous
> reallocation (not quite in those terms, but in effect) in some cases. In
> particular, if the allocatable variable has the TARGET attribute and is
> the target of some pointers, it is required to still remain the target
> of those pointers in the case where reallocation is not needed.
>
> If reallocation is needed, then "of course", any such pointers would get
> an undefined allocation status, just as they would for any other case of
> their target becoming deallocated (and subsequently allocated again, but
> that doesn't matter) other than via the pointer.

Thanks for the very helpful comments. I have delved too deeply into
all of the possible gotchas yet. The above comment concerning
reallocation would certainly have trip me up. I'll bookmark your
comments to keep them in mind as I plod along.

--
steve

Richard Maine

unread,
Jun 7, 2009, 5:26:47 PM6/7/09
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> As usual, it is too late, but I find reallocate on assignment without
> any hint that it is being done confusing and likely to cause problems.

That point was raised during the debate. I hesitate to say that there
was consensus, because I'm not sure it was unanimous. But at least a
majority felt otherwise.

I am of the opinion that it will remove more confusions than it causes.
The confusion about how Fortran strings work is a pretty big case in its
own.

> I might have suggested that variables have the REALLOCATABLE attribute
> such that they were available for allocate on assignment, otherwise they
> weren't. That adds only two letters, yet affirms that the programmer
> expects allocate on assignment.

I'd have voted against that one as I think it would add more confusion
and complication rather than help. I don't recall anyone suggesting
anything like that, but even off the top of my head, I can think of all
kinds of complications. So you would have both the allocatable and the
reallocatable attributes as separate properties? How do they interact?
Does reallocatable also imply allocatable? Can you pass a reallocatable
actual to an allocatable dummy? Vice versa? Etc. Sounds like a big
source of confusion to me.

And this all to achieve what? Let's see. There are 2 cases.

1. Most cases. By the current rules, most cases of assignment to
left-hand side with incompatible shape or type parameters are illegal
programs. The standard gives no guarantee of what happens to such
programs. So it seems that this proposed feature would carefully
distinguish between a form where the standard would specify the behavior
versus another form where the standard would say that "anything can
happen" (possibly including the same behavior) as for the other form. I
fail to see how this distinction would reduce confusion and problems.

Well, I suppose you could introduce mandatory run-time error detection
for that class of error; if so, that's a rather more fundamental change
than seems implied. If you want manatory run-time error detection, you'd
better argue that major issue on its own rather than as an incidental
side issue relating to allocatable.

2. String lengths as a special case. It is special because that is the
only case where asignment to a left-hand side with different properties
is currently anything other than an error. For this case ordinary
allocatable would continue to act in the way that already regularly
confuses people. You'd have to say reallocatable to get the "intuitive"
behavior? Nope. I don't buy that special case as an improvement in
clarity either. I suppose that perhaps you might disagree with my claim
that most people find it intuitive to have fmt='abc' result in fmt
having the value 'abc'. If so, then we are just going to disagree (and
I'd have to wonder whether we read the same newsgroup, where variants of
questions about that regularly arise).

I find myself quite confused as to exactly how this thing would fit
together, what things would be compatible with what other things,
whether string length would be special-cased or not (with extra fun for
the case of an array of strings, which might involve both the
string-length and the non-string-length cases), and other things.

I've written far too much on this really, as I suppose what I wrote
seems to ask for answers. Nah, I'm not really asking for such answers.
Even if you could come up with excellent answers to all the questions,
the fact that I had to ask means that, at least to me, such a facility
would not serve to make all this stuff intuitively obvious and
unconfusing. (Plus, even if you convinced me otherwise on that, then
we'd have the "too late" problem.)

While I can't definitively say what other people would have voted, I'd
lay pretty good odds that a proposal like that would not have passed and
thus that being "too late" is not the central problem.

Colin Watters

unread,
Jun 7, 2009, 5:41:46 PM6/7/09
to

"Richard Maine" <nos...@see.signature> wrote in message
news:1j0xv06.8rbfv46cs4kN%nos...@see.signature...

OK then, why is fmt not reallocated to length 6 on line 5?

--
Qolin

Email: my qname at domain dot com
Domain: qomputing

dpb

unread,
Jun 7, 2009, 5:59:45 PM6/7/09
to
Colin Watters wrote:
> "Richard Maine" <nos...@see.signature> wrote in message
> news:1j0xv06.8rbfv46cs4kN%nos...@see.signature...
>> <kar...@comcast.net> wrote:
>>
>>> I was wondering if the
>>> following code is valid Fortran 2003
>>>
>>> program test
>>> implicit none
>>> character(:), allocatable :: fmt, str
>>> allocate(character(3) :: fmt)
>>> fmt = 'abcdef'
>>> str = 'zyx'
...

>> Besides the feature of allowing allocation of character length at all,
>> the other "interesting" thing illustrated here is the f2003 feature of
>> allocation on assignment. The assignment statement will allocate or
>> reallocate an allocatable variable on the left-hand side to match the
>> expression.
>
> OK then, why is fmt not reallocated to length 6 on line 5?

It should/will be (I think Richard even specifically mentioned it in his
response...let's see--yes,

> Thus, when you assign 'abcdef' to fmt, fmt is reallocated to length 6.
> The fact that it was previously allocated to length 3 does not matter.

I didn't look carefully enough but it appears that Steve's comment on
what he apparently thinks the printed strings to be is wrong in that case.

The case that _isn't_ reallocated is the one wherein Richard provided
the fmt(:) substring assignment--substrings aren't allocatable, hence
they aren't reallocatable, either.

--


Richard Maine

unread,
Jun 7, 2009, 6:04:43 PM6/7/09
to
Colin Watters <qolin.see...@nowhere.co.uk> wrote:

> "Richard Maine" <nos...@see.signature> wrote in message
> news:1j0xv06.8rbfv46cs4kN%nos...@see.signature...
> > <kar...@comcast.net> wrote:

> >> character(:), allocatable :: fmt, str
> >> allocate(character(3) :: fmt)
> >> fmt = 'abcdef'
> >> str = 'zyx'
> >> print *, trim(fmt), trim (str) ! 'abczyx'

> > Besides the feature of allowing allocation of character length at all,


> > the other "interesting" thing illustrated here is the f2003 feature of
> > allocation on assignment. The assignment statement will allocate or
> > reallocate an allocatable variable on the left-hand side to match the
> > expression.
>
> OK then, why is fmt not reallocated to length 6 on line 5?

Oh. Sorry that I skimmed over the comments too quickly and missed that.
I probably read what I expected to see instead of what was actually
there. The code is "fine", but the comment on the print statement is
incorrect.

Fmt is reallocated to length 6, as I later said:

> Thus, when you assign 'abcdef' to fmt, fmt is reallocated to length 6.
> The fact that it was previously allocated to length 3 does not matter.

But I should have pointed out the erroneous comment in the print
statement. The actual output should ne abcdefzyx.

steve

unread,
Jul 1, 2009, 2:07:31 PM7/1/09
to
On Jun 7, 3:04 pm, nos...@see.signature (Richard Maine) wrote:

> Colin Watters <qolin.see_signat...@nowhere.co.uk> wrote:
> > "Richard Maine" <nos...@see.signature> wrote in message
> >news:1j0xv06.8rbfv46cs4kN%nos...@see.signature...
> > > <kar...@comcast.net> wrote:
> > >>    character(:), allocatable :: fmt, str
> > >>    allocate(character(3) :: fmt)
> > >>    fmt = 'abcdef'
> > >>    str = 'zyx'
> > >>    print *, trim(fmt), trim (str)    ! 'abczyx'
> > > Besides the feature of allowing allocation of character length at all,
> > > the other "interesting" thing illustrated here is the f2003 feature of
> > > allocation on assignment. The assignment statement will allocate or
> > > reallocate an allocatable variable on the left-hand side to match the
> > > expression.
>
> > OK then, why is fmt not reallocated to length 6 on line 5?
>
> Oh. Sorry that I skimmed over the comments too quickly and missed that.
> I probably read what I expected to see instead of what was actually
> there. The code is "fine", but the comment on the print statement is
> incorrect.
>
> Fmt is reallocated to length 6, as I later said:
>
> > Thus, when you assign 'abcdef' to fmt, fmt is reallocated to length 6.
> > The fact that it was previously allocated to length 3 does not matter.
>
> But I should have pointed out the erroneous comment in the print
> statement. The actual output should ne abcdefzyx.
>

Reviving an old thread.

First, thanks Richard and Colin for your comments. If I
understanding
correctly, the following is a conforming code.

program test
implicit none
character(:), allocatable :: fmt

!
! Allocate 3 storage units. Assign 'abc' into these units.
! Print contents of fmt, which is 'abc'.
!
allocate(character(3) :: fmt)
fmt = 'abc'
print *, fmt
!
! Assignment to fmt causes an implicit deallocation and allocation
! of 6 storage units. Print contents of fmt, which is 'abcdef'.
!
fmt = 'abcdef'
print *, fmt
end program test

I have two follow up questions. Are the following invalid programs
for the reasons given in the comments?

program test
implicit none
character(:), allocatable :: fmt

allocate(character(3) :: fmt)
fmt = 'abc'
print *, fmt

allocate(character(6) :: fmt) ! Invalid. Allocating an already
allocated entity.
fmt = 'abcdef'
print *, fmt
end program test

program test
implicit none
character(:), allocatable :: fmt

! Invalid. Not an ALLOCATE statement, intrinsic assignment,
! pointer association, nor argument association.
write(fmt, '(A)') 'abc'
print *, fmt
end program test

I'm trying to develop both valid and invalid programs for inclusion
into
the gfortran test suite. If anyone has exotic and not so exotic
examples,
I'd appreciate see the code.

--
steve

Richard Maine

unread,
Jul 1, 2009, 3:25:23 PM7/1/09
to
steve <kar...@comcast.net> wrote:

> I have two follow up questions. Are the following invalid programs
> for the reasons given in the comments?

Yes, I think you are correct in both cases.

> program test
> implicit none
> character(:), allocatable :: fmt
>
> allocate(character(3) :: fmt)
> fmt = 'abc'
> print *, fmt
>
> allocate(character(6) :: fmt) ! Invalid. Allocating an already
> allocated entity.

Correct. Perhaps slightly odd, as you can implicitly reallocate it, but
an explicit allocation also requires an explicit deallocation. I'm not
entirely sure how philosophically consistent this is, but you have it
correct, as far as I can tell.

> program test
> implicit none
> character(:), allocatable :: fmt
> ! Invalid. Not an ALLOCATE statement, intrinsic assignment,
> ! pointer association, nor argument association.
> write(fmt, '(A)') 'abc'

Also correct. One might plausibly imagine implicit allocation being
extended to cases like this, but it isn't so today to my knowledge.

0 new messages