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

"Implicit" use of assignment(=)

171 views
Skip to first unread message

Paweł Biernat

unread,
Sep 15, 2012, 10:49:23 AM9/15/12
to
Recently I noticed that overloaded assignment operator has no effect when it is called "implicitly", in cases demonstrated by the following program:

module a_mod

type :: a
contains
procedure :: a_ass
generic :: assignment(=) => a_ass
end type a

type :: b
type(a) :: ta
end type b

contains

subroutine a_ass(out, in)
class(a), intent(out) :: out
type(a), intent(in) :: in
print *, "Overloaded"
end subroutine a_ass

end module a_mod

program assign
use a_mod

type(a) :: ta1, ta2
type(a) :: tt(1)
type(b) :: tb1, tb2

! works when called "explicitly"
print *, "Explicit calls:"
ta1 = ta2
tb1%ta = tb2%ta
tt(1) = ta1

! "implicit" calls don't work:
print *, "Implicit calls:"
tt = [ta1]
tb1 = tb2

end program assign

Is there any reason for not calling the overloaded assignment in the last two ("implicit") cases?

Are there any other cases, not mentioned in the above program, where such distinction is made?

Is there a way to force the use of the overloaded assignment, but without changing the "b" type (i.e. without overloading b's assignment)?

Best regards,
Paweł Biernat

PS Many thanks to you guys for all the insightful answers I already received on my previous questions, I really appreciate your help.

Tobias Burnus

unread,
Sep 15, 2012, 12:28:09 PM9/15/12
to
Paweł Biernat wrote:
> Recently I noticed that overloaded assignment operator has no effect when it is called "implicitly", in cases demonstrated by the following program:


It seems to be a rather common bug in many compilers that they do not
invoke the defined assignment for the components during for intrinsic
assignment. However, some (few) compilers correctly do so. I heard that
the IBM xlf does so and presumably also the latest NAG compiler, maybe
also others.

For gfortran exists a patch* which implements this; it should get
reviewed and committed soon. Thus, one of the next nightly/weekly builds
of gfortran 4.8 should have it.** (Or you build it yourself.**)

Tobias

* http://gcc.gnu.org/ml/fortran/2012-09/msg00034.html
** http://gcc.gnu.org/wiki/GFortranBinaries

Richard Maine

unread,
Sep 15, 2012, 12:35:33 PM9/15/12
to
Pawe? Biernat <pawel....@uj.edu.pl> wrote:

> Recently I noticed that overloaded assignment operator has no effect when
> it is called "implicitly", in cases demonstrated by the following
> program:

[code elided]

Thanks for providing the code. I'd never have figured out what you meant
by an "implicit" call without it. (My first guess was that you meant a
CALL statement to be an explicit call, and an appropriate assignment
statement to be an implicit one; the code makes it clear that's not what
you meant, though). Hmm. I also find it hard to describe just in words
without making the words pretty lengthy.

In the problematic case, you are doing an intrinsic assignment on an
object of derived type B. That derived type has a component of type A.
The assignment of the type(a) component is at issue. Type A has a
type-bound assignment. When you directly do an assignment of the
component, the type-bound assignment works, but when you do an intrinsic
assignment on the whole structure of type B, you are seeing an intrinsic
assignment for the component of type A. (For those who might find that
unclear, try reading it while looking at the OP's posted code).

Looks to me like a compiler bug. Of course, since this is an f2003
feature and there are almost no full f2003 compilers, but only compilers
that have implemented isolated features of f2003 (my usual knee-jerk
comment), "bug" is hard to claim. Perhaps it just counts as one of the
"features" of f2003 that wasn't implemented instead. I know of no
definitive way to itemize the "features". I've see lists, but they are
not definitive and don't precisely define exactly what behavior counts
as part of what feature. It is really hard to do features in isolation
and make sure you have studied the whole standard for anything that
might even subtly relate.

From f2003 7.4.1.3 "Interpretation of intrinsic assignments".

"A derived-type intrinsic assignment is performed as if each component
of <variable> were asigned from the corresponding component of
<expr> using...defined assignment for each nonpointer nonallocatable
component of a type that has a type-bound defined assignment
consistent with the component..."

Your "implicit" example fits that description in the standard. I
conclude that the defined assignment should be used for the component.

Now if your defined assignment were not type-bound, things would be
different. That's much of why type-bound assignment was introduced. With
defined assignments that are not type bound, it is far too easy to
accidentally get an intrinsic assignment. But if you have a type-bound
defined assignment, it should pretty much always be used, as though the
intrinsic version didn't even exist. I add the "pretty much" only to
cover myself, as I can't off-hand think of any exceptions. (Things like
initializers aren't actually assignments, even though they look
simillar).

--
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,
Sep 15, 2012, 12:47:23 PM9/15/12
to
Tobias Burnus <bur...@net-b.de> wrote:

> Pawe? Biernat wrote:
> > Recently I noticed that overloaded assignment operator has no effect
> > when it is called "implicitly", in cases demonstrated by the following
> > program:
>
> It seems to be a rather common bug in many compilers that they do not
> invoke the defined assignment for the components during for intrinsic
> assignment. However, some (few) compilers correctly do so. I heard that
> the IBM xlf does so and presumably also the latest NAG compiler, maybe
> also others.
>
> For gfortran exists a patch* which implements this; it should get
> reviewed and committed soon. Thus, one of the next nightly/weekly builds
> of gfortran 4.8 should have it.** (Or you build it yourself.**)

Make sure it happend only for type-bound defined assignments. Otherwise
you will break valid f90/f95 code. See my other reply.

James Van Buskirk

unread,
Sep 15, 2012, 1:35:40 PM9/15/12
to
"Pawel Biernat" <pawel....@uj.edu.pl> wrote in message
news:27bfbe9d-f2a2-4273...@googlegroups.com...
The last case was covered by Richard and Tobias, but tt = [ta1]
or even tt = ta1 didn't work because defined assignment has to
follow the TKR matching rules for generic names. To get tt = [ta1]
to work you could separately define an assignment between arrays of
type(a) and to get tt = ta1 to work, an assignment from a scalar of
type(a) to an array of type(a) or you could get them both to work
simply by declaring subroutine a_ass to be IMPURE ELEMENTAL.

I tried to demonstrate this with gfortran but ran into another
problem:

C:\gfortran\clf\impure>type impure.f90
module a_mod

type :: a
contains
procedure, NOPASS :: a_ass, a_ass_vv, a_ass_sv
generic :: assignment(=) => a_ass
generic :: assignment(=) => a_ass_vv
generic :: assignment(=) => a_ass_sv
end type a

type :: b
type(a) :: ta
end type b

contains

impure elemental subroutine a_ass(out, in)
! subroutine a_ass(out, in)
class(a), intent(out) :: out
type(a), intent(in) :: in
print *, "Overloaded"
end subroutine a_ass

subroutine a_ass_vv(out, in)
class(a), intent(out) :: out(:)
type(a), intent(in) :: in(:)
print *, "Overloaded array->array"
end subroutine a_ass_vv

subroutine a_ass_sv(out, in)
class(a), intent(out) :: out(:)
type(a), intent(in) :: in
print *, "Overloaded scalar->array"
end subroutine a_ass_sv

end module a_mod

program assign
use a_mod

type(a) :: ta1, ta2
type(a) :: tt(1)
type(b) :: tb1, tb2

! works when called "explicitly"
print *, "Explicit calls:"
ta1 = ta2
tb1%ta = tb2%ta
tt(1) = ta1

! "implicit" calls don't work:
print *, "Implicit calls:"
tt = [ta1]
tt = ta1
tb1 = tb2

end program assign

C:\gfortran\clf\impure>gfortran impure.f90 -oimpure
impure.f90:6.32:

generic :: assignment(=) => a_ass
1
Error: 'a_ass' and 'a_ass_sv' for GENERIC '=' at (1) are ambiguous
impure.f90:39.6:

use a_mod
1
Fatal Error: Can't open module file 'a_mod.mod' for reading at (1): No such
file
or directory

I don't see why these two are ambiguous: I thought array argument
procedures were supposed to override elemental procedures.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Paweł Biernat

unread,
Sep 15, 2012, 2:36:22 PM9/15/12
to
Thanks for the patch, although I will wait for the 4.8 nightly binaries.

I assumed that this behavior is compliant to the f2003 standard as I tried two, fairly new, different compilers: ifort 13.0.0 20120731 and gfortran 4.7.1 20120721 and both gave the same (wrong) result without any complains.

Also I have seen someone on this group mentioning, about a month ago, the upcoming support for unlimited polymorphic types in gfortran. Are there any news on it yet?

Best regards,
Paweł Biernat.

Richard Maine

unread,
Sep 15, 2012, 2:43:52 PM9/15/12
to
James Van Buskirk <not_...@comcast.net> wrote:
...
...
> generic :: assignment(=) => a_ass
> 1
> Error: 'a_ass' and 'a_ass_sv' for GENERIC '=' at (1) are ambiguous
...
> I don't see why these two are ambiguous: I thought array argument
> procedures were supposed to override elemental procedures.

I believe you are correct, although one does have to be careful about
oversimplifying the rules involved. I have never been able to come up
with a simple version of the full procedure resolution rules; I just
have to go through the ones in the standard line by line. Fortunately
for most users, most cases of procedure resolution are trivial (there is
only one procedure that fits and it's the one that gets used) so they
don't have to delve into the full rules.

I'd say your description seems to confuse two separate (but related)
parts of the standard. You talk about how some procedures "override"
others. That's part of the messy rules in 12.4.4 of f2003 about how
references are resolved (and its a slight simplification, but that
simplification doesn't matter here).

But the rules about avoiding ambiguity in generics are separate. They
are even on a whole separate clause (standard-speak for "chapter") of
the standard in 16.2.3. Those sections are related in that 16.2.3 is
supposed to make sure that the rules of 12.4.4 will never be ambiguous
(12.4.4 explicitly says as much). But you can't go backwards and deduce
16.2.3 from the rules in 12.4.4. There are cases that would be
unambiguous if you actually ran through 12.4.4, but are disallowed by
16.2.3 anyway.

All that is a bit of a side journey because I do agree with your
conclusion that the code shown should work. But I just don't agree with
the reasoning that it is because "array argument procedures were
supposed to override elemental procedures." I agree because I see no
prohibition against the code in 16.2.3. I don't even need to look at the
question of what overrides what else - just at what combinations of
specific are allowed to exist together.

It actually briefly threw me that the word "elemental" doesn't even
appear in 16.2.3. Surely it wasn't forgotten about there? But after
review, I decided it was intentional (I probably once knew that). For
teh purpses of 16.2.3, you just look at an elemental procedure like any
other. The result is that you can't have both an elemental and a scalar
nonelemental specific that conflict, but you can have both an elemental
and an array version because they have different TKR (namely the R
part). The rules of 12.4.4 then lead you through which one you get
(which will usually be the array one, though that's a slight
simplification in the case of nested scopes that might have different
specifics in the generic at different nesting levels - yukk).

Richard Maine

unread,
Sep 15, 2012, 2:49:48 PM9/15/12
to
Pawe? Biernat <pawel....@uj.edu.pl> wrote:

> I assumed that this behavior is compliant to the f2003 standard as I tried
> two, fairly new, different compilers: ifort 13.0.0 20120731 and gfortran
> 4.7.1 20120721 and both gave the same (wrong) result without any
> complains.

Well, no. The behavior you observed is not compliant with the f2003
standard. The behavior you apparently expect is that specified by f2003.
The behavior that you observed is not.

Note that, as I alluded to previously, neither of the compilers you
mention (or any other that you are likely to be able to use) claims to
be an f2003 compiler. So no, even ignoring matters of possible compiler
bugs, it is not valid to deduce the specifications of f2003 based on
compilers that don't claim to conform to it.

Paweł Biernat

unread,
Sep 15, 2012, 2:53:56 PM9/15/12
to
W dniu sobota, 15 września 2012 18:35:35 UTC+2 użytkownik Richard Maine napisał:
Thanks for the reference to the standard.

Referring to your comment on unimplemented features of f2003, this might be a delicate question, but what is the reason of such state? Is it due to the complexity of the standard (almost 600 pp for f2003) or are there other priorities like improving performance of existing features? I am a complete ignorant in the matter of feature implementation and I don't intend to judge compiler programmers but asking out of pure curiosity.

Best regards,
Paweł Biernat.

Thomas Koenig

unread,
Sep 15, 2012, 3:43:15 PM9/15/12
to
On 2012-09-15, Paweł Biernat <pawel....@uj.edu.pl> wrote:

> Referring to your comment on unimplemented features of f2003,
> this might be a delicate question, but what is the reason of
> such state? Is it due to the complexity of the standard (almost
> 600 pp for f2003) or are there other priorities like improving
> performance of existing features?

I can only speak for gfortran, for which there is progress in
implementing parts of the standard, but progress is limited
by available resources (i.e. volunteers).

Of course, volunteers are always very welcome *hint*.

paul.rich...@gmail.com

unread,
Sep 16, 2012, 3:38:41 AM9/16/12
to
Dear Paweł,

>
> Also I have seen someone on this group mentioning, about a month ago, the upcoming support for unlimited polymorphic types in gfortran. Are there any news on it yet?

I circulated a preliminary patch for unlimited polymorphic just last week. It triggered discussion of an issue with the gfortran abi for polymorphic objects and this is connected with an error in the assignment or pointer assignment of characters to unlimited objects. There is also a lot to be done to develop the testcases before the patch can be submitted formally.

That said, it is substantially there :-)

Regards

Paul

Tobias Burnus

unread,
Sep 16, 2012, 5:15:22 AM9/16/12
to
Richard Maine wrote:
> Make sure it happend only for type-bound defined assignments. Otherwise
> you will break valid f90/f95 code. See my other reply.

I think the patch handles this correctly, but I will re-check.


Richard Maine wrote:
>> generic :: assignment(=) => a_ass
>> > 1
>> >Error: 'a_ass' and 'a_ass_sv' for GENERIC '=' at (1) are ambiguous
> ...
>> >I don't see why these two are ambiguous: I thought array argument
>> >procedures were supposed to override elemental procedures.
> I believe you are correct,

So do I - and looking at the patch its a bug related to the CLASS
implementation and not to array vs. scalar checking. The issue has been
filled as problem report, which already has a patch. Cf.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54594


Richard Maine wrote:
> Note that, as I alluded to previously, neither of the compilers you
> mention (or any other that you are likely to be able to use) claims to
> be an f2003 compiler. So no, even ignoring matters of possible compiler
> bugs, it is not valid to deduce the specifications of f2003 based on
> compilers that don't claim to conform to it.

Well, but that also doesn't work with those compiles which claim full
Fortran 2003 conformance; vendors might miss smaller features. For
instance, I had a code which contained as only Fortran 2003 feature:
REAL, PARAMETER :: maxexp = LOG(2.0)*MAXEXPONENT(2.0)
The code was compiling with 5 of my compilers - but not with the only
one which claimed full Fortran 2003 conformance.

Thus, I think using newer compilers gives a hint whether something is
standard conforming or not, but only the standard provides a definite
answer. (On the other hand, it also doesn't help if something is
standard conforming but not supported by the compilers one uses.)


Paweł Biernat wrote:
> Referring to your comment on unimplemented features of f2003, this
> might be a delicate question, but what is the reason of such state? Is
> it due to the complexity of the standard (almost 600 pp for f2003) or
> are there other priorities like improving performance of existing
> features? I am a complete ignorant in the matter of feature
> implementation and I don't intend to judge compiler programmers but
> asking out of pure curiosity.

Fortran 2003 added quite a lot of new features thus it simply takes time
to implement it. And especially smaller features might be missed, e.g.
supporting arrays of nonconstant size in namelists. Additionally, other
things like performance, diagnostic support, fixing bugs also take time
to develop. As do other features like OpenMP, highly-demanded Fortran
2008 features, etc.

My impression was also that the pressure on vendors to implement Fortran
2003 features was relatively low until the later mid-2000s. However, I
think currently there is quite some pressure on vendors to implement at
least the more common Fortran 2003 features.


In case of gfortran: g95/gfortran were create relatively recently. And
in the first version of gfortran (GCC 4.0/4.1, ~2005) the focus was on
fully supporting Fortran 95 and fixing the bugs. Only when the Fortran
95 was stable, the implementation of newer features could start.
Especially as gfortran is nearly entirely developed as voluntary,
spare-time project, the development is not as linear as with commercial
compilers.

However, the Fortran 2003 supports gets more and more complete and solid
in all major compilers, including gfortran. I also think that it will
taker shorter until Fortran 2008 is supported, not only because the
additions were smaller but also because of the current momentum.


For GCC 4.8 you can expect support for CLASS(*) and FINAL subroutines
[both features are nearly ready] - and many smaller improvements which
aren't visible in the release notes; e.g. a fix for the bug which
started this thread. Besides minor issues, the only other missing big
Fortran 2003 features are parameterized-derived types, user-defined I/O
and the (optional!) IEEE support.


On the other hand, some features of newer standards will also be
implemented earlier; for instance, in GCC 4.8 there is support for
assumed-type TYPE(*) and (incomplete support for) assumed-rank
DIMENSION(..) of Technical Specification (TS) 29113:2012. One could
argue that Fortran 2003 should have been first completed. However,
TYPE(*),DIMENSION(..) is required by an important library: The Message
Passing Interface (MPI) 3.0 will use it.* Additionally, the FINAL
subroutine support uses assumed-rank internally.

(The trigger for the TYPE(*) and then DIMENSION(..) support was that
gfortran seems to be the only compiler which doesn't seem to have a
vendor-specific directive to ignore the TKI check for an argument, which
is what MPI vendors like to use for their buffer argument. The hope was
that TYPE(*) is sufficient, but passing a scalar to TYPE(*),DIMENSION(*)
is not allowed; thus, dimension(..) is needed. Assumed-rank arrays also
allow the MPI library to handle arrays with strides internally, which is
another bonus.)

Tobias

* See http://meetings.mpi-forum.org/MPI_3.0_main_page.php; there is also
some preliminary support for F2008+TS in Open MPI.

Paweł Biernat

unread,
Sep 16, 2012, 7:37:19 AM9/16/12
to
As suggested by James Van Buskirk, the "impure elemental" directive solves the problem for scalar->vector and vector->vector assignments. I checked it with gfortran and it works as expected, but ifort produces a load of errors and seems not to allow the two directives at a time before the function name.

However, "impure" is not required if "print" is removed and instead one can use a component of "type(a)" to detect the call to "a_ass" (e.g. add "integer :: i = 1" inside "type(a)" and then use "out%i = 2" in the "a_ass"). This makes the scalar/vector to vector assignments call "a_ass" in both, ifort and gfortran.


Another case that came to my mind is:

type(a), allocatable :: ta3
allocate(ta3, source = a())

should it result in a call to "a_ass"?


Regards,
Paweł Biernat.

James Van Buskirk

unread,
Sep 17, 2012, 8:47:03 AM9/17/12
to
"Tobias Burnus" <bur...@net-b.de> wrote in message
news:505598AA...@net-b.de...

> Richard Maine wrote:

>> Make sure it happend only for type-bound defined assignments. Otherwise
>> you will break valid f90/f95 code. See my other reply.

> I think the patch handles this correctly, but I will re-check.

> Richard Maine wrote:
>>> generic :: assignment(=) => a_ass

>>> >Error: 'a_ass' and 'a_ass_sv' for GENERIC '=' at (1) are ambiguous
>> ...
>>> >I don't see why these two are ambiguous: I thought array argument
>>> >procedures were supposed to override elemental procedures.
>> I believe you are correct,

> So do I - and looking at the patch its a bug related to the CLASS
> implementation and not to array vs. scalar checking. The issue has been
> filled as problem report, which already has a patch. Cf.
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54594

In my testing, I also found that the IMPURE EMEMENTAL attribute
of subroutine a_ass was not required to trigger this issue, but
it looks like your patch is going to fix it even if the test
case were changed to remove this attribute, although I didn't
see any tests like that in PR54594.

BTW, I posted a pair of f95 issues last week but I think they
got lost because they were embedded in a rather long post. I
could repost a cut-down version if you like.

Janus Weil

unread,
Sep 17, 2012, 9:18:12 AM9/17/12
to

> > So do I - and looking at the patch its a bug related to the CLASS
> > implementation and not to array vs. scalar checking. The issue has been
> > filled as problem report, which already has a patch. Cf.
> > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54594
>
> In my testing, I also found that the IMPURE EMEMENTAL attribute
> of subroutine a_ass was not required to trigger this issue, but
> it looks like your patch is going to fix it even if the test
> case were changed to remove this attribute, although I didn't
> see any tests like that in PR54594.

The fix for this PR has already been committed to gcc trunk. And yes, it also works if IMPURE ELEMENTAL is removed.

Btw, gfortan now rejects your original code with:

generic :: assignment(=) => a_ass
1
Error: Type-bound operator at (1) can't be NOPASS
.


> BTW, I posted a pair of f95 issues last week but I think they
> got lost because they were embedded in a rather long post. I
> could repost a cut-down version if you like.

Instead of reposting it here, it would be much more helpful if you would directly open a bug report on http://gcc.gnu.org/bugzilla/ (which really is not much more more effort than a c.l.f. post).

Thanks,
Janus

James Van Buskirk

unread,
Sep 17, 2012, 10:25:31 AM9/17/12
to
"Janus Weil" <ja...@gcc.gnu.org> wrote in message
news:f2097add-67c1-4afb...@googlegroups.com...

>> In my testing, I also found that the IMPURE EMEMENTAL attribute
>> of subroutine a_ass was not required to trigger this issue, but
>> it looks like your patch is going to fix it even if the test
>> case were changed to remove this attribute, although I didn't
>> see any tests like that in PR54594.

> The fix for this PR has already been committed to gcc trunk. And yes,
> it also works if IMPURE ELEMENTAL is removed.

> Btw, gfortan now rejects your original code with:

> generic :: assignment(=) => a_ass

> Error: Type-bound operator at (1) can't be NOPASS

I saw that, but the discussion in the PR indicates that this
is not true for generic names. The reason for the NOPASS
attribute was that I wanted to define assignment to arrays and
it seems the passed argument has to be scalar.

>> BTW, I posted a pair of f95 issues last week but I think they
>> got lost because they were embedded in a rather long post. I
>> could repost a cut-down version if you like.

> Instead of reposting it here, it would be much more helpful if you
> would directly open a bug report on http://gcc.gnu.org/bugzilla/
> (which really is not much more more effort than a c.l.f. post).

I was going to do this at one point but there was something blocking
me; I forget what now. Here is the reduced test case:

C:\gfortran\clf\logtest>type scan.f90
module m1
implicit none
contains
subroutine s1(A)
logical A
integer iscan, iverify
character(7), parameter :: tf(2) = ['.FALSE.','.TRUE. ']

iscan = scan('AA','A',back=A)
iverify = verify('xx','A',back=A)
write(*,'(a)') 'SCAN test: A = '//trim(tf(iscan))
write(*,'(a)') 'VERIFY test: A = '//trim(tf(iverify))
end subroutine s1
end module m1

program p1
use m1
implicit none
logical B

B = .TRUE.
call s1(B)
end program p1

C:\gfortran\clf\logtest>gfortran scan.f90 -oscan

C:\gfortran\clf\logtest>scan
SCAN test: A = .FALSE.
VERIFY test: A = .FALSE.

C:\gfortran\clf\logtest>ifort scan.f90
Intel(R) Fortran Compiler for 32-bit applications, Version 9.1 Build
20061103
Z Package ID: W_FC_C_9.1.033
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.50727.363
Copyright (C) Microsoft Corporation. All rights reserved.

-out:scan.exe
-subsystem:console
scan.obj

C:\gfortran\clf\logtest>scan
SCAN test: A = .TRUE.
VERIFY test: A = .TRUE.

gfortran's implementation of the INDEX intrinsic paradoxically
seems to pass this test, however.

Janus Weil

unread,
Sep 17, 2012, 2:19:42 PM9/17/12
to

> >> BTW, I posted a pair of f95 issues last week but I think they
> >> got lost because they were embedded in a rather long post. I
> >> could repost a cut-down version if you like.
>
> > Instead of reposting it here, it would be much more helpful if you
> > would directly open a bug report on http://gcc.gnu.org/bugzilla/
> > (which really is not much more more effort than a c.l.f. post).
>
> I was going to do this at one point but there was something blocking
> me; I forget what now.

Well, you do need to create an account on bugzilla first. The rest is rather straightforward: For gfortran bugs, just choose product "gcc" and component "fortran", insert a test case and a short description of the problem and off you go ...

More information can still be added later (either by yourself of one of the gfortran developers).


> Here is the reduced test case:
>
> C:\gfortran\clf\logtest>type scan.f90

Apparently it has already been filed (and fixed!) by Tobias:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54608

Cheers,
Janus

James Van Buskirk

unread,
Sep 17, 2012, 5:46:48 PM9/17/12
to
"Janus Weil" <ja...@gcc.gnu.org> wrote in message
news:4ac4f307-90e1-4cd8...@googlegroups.com...

>> I was going to do this at one point but there was something blocking
>> me; I forget what now.

> Well, you do need to create an account on bugzilla first. The rest
> is rather straightforward: For gfortran bugs, just choose product
> "gcc" and component "fortran", insert a test case and a short
> description of the problem and off you go ...

It seemed that there were some terms you had to agree to and there
were some that I couldn't agree to.

>> Here is the reduced test case:

>> C:\gfortran\clf\logtest>type scan.f90

> Apparently it has already been filed (and fixed!) by Tobias:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54608

Yes, three cheers for Tobias! You know, the program that this PR
came from also turned up another, more complicated, situation.

C:\gfortran\clf\logtest>type minval3.f90
program minval3
implicit none
integer, parameter :: m = minval([1])
real(m*kind(1.0)) x
x = 17
write(*,*) x, kind(x)
end program minval3

C:\gfortran\clf\logtest>gfortran minval3.f90 -ominval3

C:\gfortran\clf\logtest>minval3
17.0000000 4

So gfortran can use MINVAL in constant expressions! A further
test:

C:\gfortran\clf\logtest>type minval4.f90
module m4procs
implicit none
contains
recursive function fun(depth) result(r)
integer r
integer depth
integer x(minval([1]))
integer y
save

x = 0
if(depth > 0) y = fun(depth-1)
x = x+1
r = x(1)
end function fun
end module m4procs

program minval4
use m4procs
implicit none

write(*,*) fun(1)
end program minval4

C:\gfortran\clf\logtest>gfortran minval4.f90 -ominval4

C:\gfortran\clf\logtest>minval4
2

This also shows that MINVAL is accepted in a constant expression
because if it weren't then array x in function fun would be an
automatic data object and so wouldn't have the SAVE attribute.
Without the SAVE attribute, the program prints out 1 instead of 2.

But now consider what happens when we add the MASK= optional
argument:

C:\gfortran\clf\logtest>type minval1.f90
program minval1
implicit none
integer, parameter :: m = minval([1],mask=[.TRUE.])
real(m*kind(1.0)) x
x = 17
write(*,*) x, kind(x)
end program minval1

C:\gfortran\clf\logtest>gfortran minval1.f90 -ominval1
minval1.f90:3.28:

integer, parameter :: m = minval([1],mask=[.TRUE.])
1
Error: transformational intrinsic 'minval' at (1) is not permitted in an
initial
ization expression
minval1.f90:4.9:

real(m*kind(1.0)) x
1
Error: Symbol 'm' at (1) has no IMPLICIT type
minval1.f90:5.4:

x = 17
1
Error: Symbol 'x' at (1) has no IMPLICIT type

So the first error message above is inaccurate in that MINVAL is
permitted, just the optional MASK= argument form has not yet been
implemented for constant expressions.

Now we try the automatic data object test again:

C:\gfortran\clf\logtest>type minval2.f90
module m2procs
implicit none
contains
recursive function fun(depth) result(r)
integer r
integer depth
integer x(minval([1],mask=[.TRUE.]))
integer y
save

x = 0
if(depth > 0) y = fun(depth-1)
x = x+1
r = x(1)
end function fun
end module m2procs

program minval2
use m2procs
implicit none

write(*,*) fun(1)
end program minval2

C:\gfortran\clf\logtest>gfortran minval2.f90 -ominval2
minval2.f90: In function 'fun':
minval2.f90:7:0: internal compiler error: in
gfc_trans_auto_array_allocation, at
fortran/trans-array.c:5573
integer x(minval([1],mask=[.TRUE.]))
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

So that's a bit of a problem. On to MINLOC:

C:\gfortran\clf\logtest>type minloc1.f90
program minloc1
implicit none
integer, parameter :: m(1) = minloc([1])
real(m(1)*kind(1.0)) x
x = 17
write(*,*) x, kind(x)
end program minloc1

C:\gfortran\clf\logtest>gfortran minloc1.f90 -ominloc1
minloc1.f90:3.31:

integer, parameter :: m(1) = minloc([1])
1
Error: transformational intrinsic 'minloc' at (1) is not permitted in an
initial
ization expression
minloc1.f90:4.9:

real(m(1)*kind(1.0)) x
1
Error: Function 'm' at (1) has no IMPLICIT type
minloc1.f90:5.4:

x = 17
1
Error: Symbol 'x' at (1) has no IMPLICIT type

C:\gfortran\clf\logtest>type minloc2.f90
module m2procs
implicit none
contains
recursive function fun(depth) result(r)
integer r
integer depth
integer x(sum(minloc([1])))
integer y
save

x = 0
if(depth > 0) y = fun(depth-1)
x = x+1
r = x(1)
end function fun
end module m2procs

program minloc2
use m2procs
implicit none

write(*,*) fun(1)
end program minloc2

C:\gfortran\clf\logtest>gfortran minloc2.f90 -ominloc2
minloc2.f90: In function 'fun':
minloc2.f90:7:0: internal compiler error: in
gfc_trans_auto_array_allocation, at
fortran/trans-array.c:5573
integer x(sum(minloc([1])))
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

So the most basic form of MINLOC runs into the same issues as
MINVAL with the MASK= optional argument.

James Van Buskirk

unread,
Sep 17, 2012, 7:45:21 PM9/17/12
to
"James Van Buskirk" <not_...@comcast.net> wrote in message
news:k385o5$6kc$1...@dont-email.me...

BTW, I tried minval1.f90, minval2.f90, minval3.f90, minval4.f90,
minloc1.f90, and minloc2.f90 on ifort 9.1, and it rejected
minval1.f90, minval3.f90, and minloc1.f90, as may be expected for
an f95 compiler. Also it printed out 1 for minloc2.f90, which is
the f95 result. However, the code it generated for minval2.f90
and minval4.f90 crashed with an access violation at run time.

I think that minval2.f90, minval4.f90, and minloc2.f90 are all
f95 standard-conforming, even though they should output different
results according to the f95 and f2003 standards, so the failures
on gfortran and ifort should be noted.

James Van Buskirk

unread,
Sep 18, 2012, 11:11:16 PM9/18/12
to
"James Van Buskirk" <not_...@comcast.net> wrote in message
news:k37bsn$neh$1...@dont-email.me...

> "Janus Weil" <ja...@gcc.gnu.org> wrote in message
> news:f2097add-67c1-4afb...@googlegroups.com...

>> Btw, gfortan now rejects your original code with:

>> generic :: assignment(=) => a_ass

>> Error: Type-bound operator at (1) can't be NOPASS

> I saw that, but the discussion in the PR indicates that this
> is not true for generic names. The reason for the NOPASS
> attribute was that I wanted to define assignment to arrays and
> it seems the passed argument has to be scalar.

Further reading of the standard leads me to conclude that I was
unnecessarily dismissive of the above error. In fact ASSIGNMENT(=)
doesn't count as generic-name (R1207 of N1830.pdf) and so its
specific bindings all have to have a passed-object dummy argument
(C469). The consequence of this seems to be that you can't have
type-bound defined assignment between arrays because the passed-
object dummy argument can't be an array (C456). So if you want
type-bound defined assignment between arrays, only an ELEMENTAL
subroutine will work. Assigning a scalar expr to an array variable
of the same type is possible, though. In this case we could have
declared

procedure, PASS=in :: a_ass_sv

but there is no way to declare a specific binding for a_ass_vv.

James Van Buskirk

unread,
Sep 19, 2012, 4:07:18 PM9/19/12
to
"James Van Buskirk" <not_...@comcast.net> wrote in message
news:k38cmd$fad$1...@dont-email.me...

> I think that minval2.f90, minval4.f90, and minloc2.f90 are all
> f95 standard-conforming, even though they should output different
> results according to the f95 and f2003 standards, so the failures
> on gfortran and ifort should be noted.

I changed the [] array constructors to (//) and tested on some f95
compilers:

C:\gfortran\clf\logtest\f95>type *.f90

minloc1.f90


program minloc1
implicit none
integer, parameter :: m(1) = minloc((/1/))
real(m(1)*kind(1.0)) x
x = 17
write(*,*) x, kind(x)
end program minloc1

minloc2.f90


module m2procs
implicit none
contains
recursive function fun(depth) result(r)
integer r
integer depth
integer x(sum(minloc((/1/))))
integer y
save

x = 0
if(depth > 0) y = fun(depth-1)
x = x+1
r = x(1)
end function fun
end module m2procs

program minloc2
use m2procs
implicit none

write(*,*) fun(1)
end program minloc2

minval1.f90


program minval1
implicit none
integer, parameter :: m = minval((/1/),mask=(/.TRUE./))
real(m*kind(1.0)) x
x = 17
write(*,*) x, kind(x)
end program minval1

minval2.f90


module m2procs
implicit none
contains
recursive function fun(depth) result(r)
integer r
integer depth
integer x(minval((/1/),mask=(/.TRUE./)))
integer y
save

x = 0
if(depth > 0) y = fun(depth-1)
x = x+1
r = x(1)
end function fun
end module m2procs

program minval2
use m2procs
implicit none

write(*,*) fun(1)
end program minval2

minval3.f90


program minval3
implicit none
integer, parameter :: m = minval((/1/))
real(m*kind(1.0)) x
x = 17
write(*,*) x, kind(x)
end program minval3

minval4.f90


module m4procs
implicit none
contains
recursive function fun(depth) result(r)
integer r
integer depth
integer x(minval((/1/)))
integer y
save

x = 0
if(depth > 0) y = fun(depth-1)
x = x+1
r = x(1)
end function fun
end module m4procs

program minval4
use m4procs
implicit none

write(*,*) fun(1)
end program minval4

C:\gfortran\clf\logtest\f95>type test.txt
Program gfortran ifort g95 ftn95 lf95
minloc1.f90 REJECTED REJECTED REJECTED REJECTED REJECTED
minloc2.f90 ICE 1 ICE 538976289 1
minval1.f90 REJECTED REJECTED REJECTED REJECTED REJECTED
minval2.f90 ICE ACCVIO ICE 1 1
minval3.f90 17.0, 4 REJECTED REJECTED REJECTED REJECTED
minval4.f90 2 ACCVIO ICE 1 1

gfortan -std=f95 xxx.f90 -oxxx (7/29/12)
ifort /stand:f95 xxx.f90 (11/03/06)
g95 -std=f95 xxx.f90 -oxxx (11/15/06)
ftn95 /ISO xxx.f90 /LINK (5/21/12)
lf95 /f95 xxx.f90 (2004)

So only lf95 got the consistent f95 results. It's a shame they
didn't choose to go on to f2003. They had a very steady compiler
that I didn't destroy as frequently as most others.

Tobias Burnus

unread,
Sep 20, 2012, 5:12:02 AM9/20/12
to
On 09/19/2012 10:07 PM, James Van Buskirk wrote:
> Program gfortran ifort g95 ftn95 lf95
> minloc1.f90 REJECTED REJECTED REJECTED REJECTED REJECTED
> minloc2.f90 ICE 1 ICE 538976289 1
> minval1.f90 REJECTED REJECTED REJECTED REJECTED REJECTED
> minval2.f90 ICE ACCVIO ICE 1 1
> minval3.f90 17.0, 4 REJECTED REJECTED REJECTED REJECTED
> minval4.f90 2 ACCVIO ICE 1 1
>

> So only lf95 got the consistent f95 results. It's a shame they
> didn't choose to go on to f2003. They had a very steady compiler
> that I didn't destroy as frequently as most others.

But you know that it is much easier to give consistent Fortran 95
results if the compiler is a Fortran 95-only compiler.

For instance the "2" instead of the "1" in the last line is because
gfortran compile-time simplifies the minval expression. Thus, "2" is the
correct Fortran 2003/2008, while "1" is the correct Fortran 95 result.
(The reason is that SAVE doesn't apply to automatic variables but if
minval becomes an initialization expression ...)

Adding the proper warnings/errors for such kind of changes is rather
involved. Thus, the question is whether -std=f95 can ever emulate a true
Fortran 95 compiler. I think to a certain extent, one has to live with
the issues mentioned in "1.6 Compatibility" - even if the compiler can
help a bit.

(Still, gfortran shouldn't ICE for minloc2/minval2 and it probably
should have rejected minval3 with -std=f95.)

Tobias

PS: I believe that James knew about the 2 vs. 1 issue, but for the
benefit for other readers ...

James Van Buskirk

unread,
Sep 20, 2012, 11:14:24 AM9/20/12
to
"Tobias Burnus" <bur...@net-b.de> wrote in message
news:505ADDE...@net-b.de...

> But you know that it is much easier to give consistent Fortran 95 results
> if the compiler is a Fortran 95-only compiler.

> For instance the "2" instead of the "1" in the last line is because
> gfortran compile-time simplifies the minval expression. Thus, "2" is the
> correct Fortran 2003/2008, while "1" is the correct Fortran 95 result.
> (The reason is that SAVE doesn't apply to automatic variables but if
> minval becomes an initialization expression ...)

> Adding the proper warnings/errors for such kind of changes is rather
> involved. Thus, the question is whether -std=f95 can ever emulate a true
> Fortran 95 compiler. I think to a certain extent, one has to live with the
> issues mentioned in "1.6 Compatibility" - even if the compiler can help a
> bit.

> (Still, gfortran shouldn't ICE for minloc2/minval2 and it probably should
> have rejected minval3 with -std=f95.)

The issue with minval4.f90 was one that I think the committee had
overlooked when f2003 was introduced. It seems reasonable to have
an extension where a given expression is allowed as an initialization
expression when not technically permitted by the standard, because
if the extension is actually used in a program, the program will be
nonconforming so the compiler is free to do what it wants with it.
The trouble is that there are a few forms of nondestructive testing
as in minval4.f90 and friends where the program is conforming
whether the expression is an initialization expression or not, but
the program result is different. Another way to test is with

character(minval((/1/))), allocatable :: x
save

where x should be deallocated in f95 but not in f2003. Another
example is the Digital extension of operator(.XOR.). You can
test for compilers of dvf/cfv/ifort lineage by defining
operator(.XOR.) and testing its precedence. Unfortunately, ifort
probably defeats this test with its -standard-semantics switch,
although I haven't tested. F2008 provides the COMPILER_VERSION()
intrinsic, so it isn't needed if this is available, kind of like
the way you identified early x86 processors by measuring the
length of the prefetch buffer but since the Pentium Classic there
has been the CPUID instruction for this purpose.

gfortran isn't alone in its behavior regarding minval4.f90. If
we use an expression which compilers more commonly extend to
initialization expressions:

C:\gfortran\clf\logtest\f95>type int1.f90
program int1
implicit none
integer, parameter :: rk = 1.5
integer, parameter :: m = int(rk)
real(m*kind(1.0)) x
x = 17
write(*,*) x, kind(x)
end program int1

C:\gfortran\clf\logtest\f95>type int2.f90
module i2procs
implicit none
contains
recursive function fun(depth) result(r)
integer r
integer depth
real, parameter :: rk = 1.5
integer x(int(rk))
integer y
save

x = 0
if(depth > 0) y = fun(depth-1)
x = x+1
r = x(1)
end function fun
end module i2procs

program minval4
use i2procs
implicit none

write(*,*) fun(1)
end program minval4

All 5 compilers tested accept int1.f90, and for int2.f90,
all but lf95 print out the f2003 value of 2; lf95 still
prints 1.

glen herrmannsfeldt

unread,
Sep 20, 2012, 1:16:15 PM9/20/12
to
James Van Buskirk <not_...@comcast.net> wrote:

(snip)
> character(minval((/1/))), allocatable :: x
> save

> where x should be deallocated in f95 but not in f2003.

(snip)
> C:\gfortran\clf\logtest\f95>type int2.f90
> module i2procs
> implicit none
> contains
> recursive function fun(depth) result(r)
> integer r
> integer depth
> real, parameter :: rk = 1.5
> integer x(int(rk))
> integer y
> save

> x = 0
> if(depth > 0) y = fun(depth-1)
> x = x+1
> r = x(1)
> end function fun
> end module i2procs

Is this in the list of incompatible changes between Fortran 95
and Fortran 2003?

(snip)

> All 5 compilers tested accept int1.f90, and for int2.f90,
> all but lf95 print out the f2003 value of 2; lf95 still
> prints 1.

-- glen

Steve Lionel

unread,
Sep 20, 2012, 1:38:04 PM9/20/12
to
On 9/19/2012 4:07 PM, James Van Buskirk wrote:
> C:\gfortran\clf\logtest\f95>type test.txt
> Program gfortran ifort g95 ftn95 lf95
> minloc1.f90 REJECTED REJECTED REJECTED REJECTED REJECTED
> minloc2.f90 ICE 1 ICE 538976289 1
> minval1.f90 REJECTED REJECTED REJECTED REJECTED REJECTED
> minval2.f90 ICE ACCVIO ICE 1 1
> minval3.f90 17.0, 4 REJECTED REJECTED REJECTED REJECTED
> minval4.f90 2 ACCVIO ICE 1 1
>
> gfortan -std=f95 xxx.f90 -oxxx (7/29/12)
> ifort /stand:f95 xxx.f90 (11/03/06)
> g95 -std=f95 xxx.f90 -oxxx (11/15/06)
> ftn95 /ISO xxx.f90 /LINK (5/21/12)
> lf95 /f95 xxx.f90 (2004)

I have created a problem report for ifort for minval2 and minval4 where
I get an ICE (you're using an older compiler.)

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran

Refer to http://software.intel.com/en-us/articles/optimization-notice
for more information regarding performance and optimization choices in
Intel software products.
0 new messages