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

Aliasing, defined assignment and parenthesized expressions

139 views
Skip to first unread message

Marco

unread,
Sep 9, 2015, 8:49:28 AM9/9/15
to
Hi all,
in the attached code copy_t_a is called passing "more or less" the
same actual argument for both dummy arguments, which in principle
would violate the aliasing rules. However, my understanding is that
introducing parentheses should create a temporary, solving the
problem in cases B) and C). I am not sure about defined assignment,
case A).

The results that I see are the expected ones using nagfor, i.e. the
value of x does not change after assignment, while they are either
different or produce segmentation fault with gfortran and ifort.

My question is whether the code is correct or not.



module m
implicit none

type :: t_a
class(*), allocatable :: x
end type t_a

interface assignment(=)
module procedure copy_t_a
end interface

contains

subroutine copy_t_a(y,x)
type(t_a), intent(in) :: x
type(t_a), intent(out) :: y
allocate( y%x , source=x%x)
end subroutine copy_t_a

end module m


program p
use m
implicit none

type(t_a) :: v1

! Define v1
allocate( real :: v1%x )
select type( x => v1%x ); type is(real)
x = 1.5
end select


! nagfor: returns x=1.5 for A), B) and C)
! gfortran: segmentation fault for A) and B), x=0 for C)
! ifort: x=0 for A), B) and C)

v1 = v1 ! A)
!v1 = (v1) ! B)
!call copy_t_a( v1 , (v1) ) ! C)
select type( x => v1%x ); type is(real)
write(*,*) "v1%x = ",x
end select

end program p

FortranFan

unread,
Sep 9, 2015, 11:41:52 AM9/9/15
to
When it comes to features introduced in Fortran 2008 and 2003 standards, it would help if you state which versions of compilers you have tried in addition to their names, especially because the implementations are still progressing and bug fixes are being applied regularly for them. The 3rd compiler you state, for instance, returns 1.5 using their latest version for all 3 cases, but only in the Release build i.e., with optimization. With no optimization (as in a Debug build), it returns some undefined value.

Real experts can tackle your "correctness" question; my head hurts simply looking at the 3 cases and trying to contemplate navigating through the standards documentation on unlimited polymorphism and assignment to itself! If NagFor is a fully correct implementation of a sharp mind like Malcolm Cohen, perhaps it is the "gold" standard on this!

Marco

unread,
Sep 9, 2015, 12:40:19 PM9/9/15
to
Am Wed, 09 Sep 2015 08:41:49 -0700 schrieb FortranFan:

> On Wednesday, September 9, 2015 at 8:49:28 AM UTC-4, m wrote:
>
> When it comes to features introduced in Fortran 2008 and 2003 standards,
> it would help if you state which versions of compilers you have tried in
> addition to their names, especially because the implementations are
> still progressing and bug fixes are being applied regularly for them.
> The 3rd compiler you state, for instance, returns 1.5 using their latest
> version for all 3 cases, but only in the Release build i.e., with
> optimization. With no optimization (as in a Debug build), it returns
> some undefined value.

Yes, my point was mostly regarding the correctness of the code without
adding too many details which then would be important in reporting
possible problems. Anyway:

NAG Fortran Compiler Release 6.0

Intel(R) 64, Version 16.0.0.109 Build 20150815
Intel(R) 64, Version 15.0 Build 20150407

GNU Fortran (GCC) 6.0.0 20150907 (experimental)

Concerning optimization, I could imagine that at least for A) and B)
this would result in some drastic simplification which would eliminate
completely the problematic call...

> Real experts can tackle your "correctness" question; my head hurts
> simply looking at the 3 cases and trying to contemplate navigating
> through the standards documentation on unlimited polymorphism and
> assignment to itself! If NagFor is a fully correct implementation of a
> sharp mind like Malcolm Cohen, perhaps it is the "gold" standard on
> this!

That would make the user's life easier!

Marco

unread,
Sep 9, 2015, 1:01:33 PM9/9/15
to
I might add that unlimited polymorphism is possibly not the problem
here, since the results do not change using

real, allocatable :: x

instead of

class(*), allocatable :: x

Marco


steve kargl

unread,
Sep 9, 2015, 1:22:46 PM9/9/15
to
Marco wrote:

> I might add that unlimited polymorphism is possibly not the problem
> here, since the results do not change using
>
> real, allocatable :: x
>
> instead of
>
> class(*), allocatable :: x
>

It's a bug in gfortran. Please submit a bug report.

--
steve

Marco

unread,
Sep 9, 2015, 1:41:09 PM9/9/15
to
Done: it is Bug 67528

Thank you.

(I am going to report it also to Intel)

Ian Harvey

unread,
Sep 9, 2015, 4:29:33 PM9/9/15
to
On 2015-09-09 10:47 PM, Marco wrote:
> Hi all,
> in the attached code copy_t_a is called passing "more or less" the
> same actual argument for both dummy arguments, which in principle
> would violate the aliasing rules. However, my understanding is that
> introducing parentheses should create a temporary, solving the
> problem in cases B) and C). I am not sure about defined assignment,
> case A).
>
> The results that I see are the expected ones using nagfor, i.e. the
> value of x does not change after assignment, while they are either
> different or produce segmentation fault with gfortran and ifort.
>
> My question is whether the code is correct or not.


The code is ok. There is an outstanding bug against gfortran for
erroneous aliasing in defined assignment - see pr59202 - that is
plausibly relevant.

Note that with the current release of ifort I get the expected result of
v1%x = 1.5.

steve kargl

unread,
Sep 9, 2015, 5:43:36 PM9/9/15
to
Ian Harvey wrote:

> On 2015-09-09 10:47 PM, Marco wrote:
>> Hi all,
>> in the attached code copy_t_a is called passing "more or less" the
>> same actual argument for both dummy arguments, which in principle
>> would violate the aliasing rules. However, my understanding is that
>> introducing parentheses should create a temporary, solving the
>> problem in cases B) and C). I am not sure about defined assignment,
>> case A).
>>
>> The results that I see are the expected ones using nagfor, i.e. the
>> value of x does not change after assignment, while they are either
>> different or produce segmentation fault with gfortran and ifort.
>>
>> My question is whether the code is correct or not.
>
>
> The code is ok. There is an outstanding bug against gfortran for
> erroneous aliasing in defined assignment - see pr59202 - that is
> plausibly relevant.
>
> Note that with the current release of ifort I get the expected result of
> v1%x = 1.5.
>

I may have just fixed this. See fortran @ gcc mailing list. With my patch,
your code generates

F F
T F
F F
T F
F T
T T

--
steve

Ian Harvey

unread,
Sep 9, 2015, 7:34:25 PM9/9/15
to
On 2015-09-10 6:29 AM, Ian Harvey wrote:
> On 2015-09-09 10:47 PM, Marco wrote:
>> Hi all,
>> in the attached code copy_t_a is called passing "more or less" the
>> same actual argument for both dummy arguments, which in principle
>> would violate the aliasing rules. However, my understanding is that
>> introducing parentheses should create a temporary, solving the
>> problem in cases B) and C). I am not sure about defined assignment,
>> case A).
>>
>> The results that I see are the expected ones using nagfor, i.e. the
>> value of x does not change after assignment, while they are either
>> different or produce segmentation fault with gfortran and ifort.
>>
>> My question is whether the code is correct or not.
>
>
> The code is ok. There is an outstanding bug against gfortran for
> erroneous aliasing in defined assignment - see pr59202 - that is
> plausibly relevant.
>
> Note that with the current release of ifort I get the expected result of
> v1%x = 1.5.

As has been pointed out on the intel forum by FortranFan, you get the
expected result *unless* you have the debugging version of the C runtime
active. This implies that the generated code has a use-after-free
issue, which would be consistent with the possibility of aliasing not
being correctly accounted for by that compiler.

Marco

unread,
Sep 10, 2015, 3:22:22 AM9/10/15
to
Valgrind errors are also consistent with this: regardless of printing
the correct result it shows

==18293==
==18293== Invalid read of size 4
==18293== at 0x4022DE: copy_t_a (test.f90:17)
==18293== by 0x4022DE: MAIN__ (test.f90:35)
==18293== by 0x4021FD: main
==18293== Address 0x5afb0f0 is 0 bytes inside a block of size 4 free'd
==18293== at 0x4C2A1CC: free (vg_replace_malloc.c:473)
==18293== by 0x407A83: for_dealloc_allocatable
==18293== by 0x4022AD: copy_t_a (test.f90:14)
==18293== by 0x4022AD: MAIN__ (test.f90:35)
==18293== by 0x4021FD: main
==18293==

where the relevant lines are

copy_t_a (test.f90:17) -> allocate( y%x , source=x%x)
copy_t_a (test.f90:14) -> subroutine copy_t_a(y,x)

so x%x is freed on entry into copy_t_a and then referenced.




glen herrmannsfeldt

unread,
Sep 10, 2015, 2:47:59 PM9/10/15
to
Marco <mres...@gmail.com> wrote:

> in the attached code copy_t_a is called passing "more or less" the
> same actual argument for both dummy arguments, which in principle
> would violate the aliasing rules. However, my understanding is that
> introducing parentheses should create a temporary, solving the
> problem in cases B) and C). I am not sure about defined assignment,
> case A).

As I understand it, parenthesese don't automatically create a temporary.

In PL/I they create a modifiable temporary, which is sometimes
convenient. (PL/I also creates modifiable temporaries for constants,
while last I knew Fortran didn't do that.)

In Fortran, parentheses do come into the aliasing rules, but not
in such an easy to explain way.

-- glen


Richard Maine

unread,
Sep 10, 2015, 3:10:52 PM9/10/15
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> As I understand it, parenthesese don't automatically create a temporary.
..
> In Fortran, parentheses do come into the aliasing rules, but not
> in such an easy to explain way.

Seems straightforward enough to me. But then I'd also say that they
essentially create a temporary. Maybe if you don't see it that way,
that's why you find it hard to explain. :-)

The Fortran standard doesn't use the term "temporary" and that is
admitedly an implementation detail left to the compiler. But what the
standard does say is close enough to saying that a temporary is created
that I'd say you could consider it to say that, with the understanding
that the compiler is also allowed to optimize the temporary away if it
concludes it can safely do so.

The parens explicitly make the argument an expression (as they fit the
syntax of an expression, but not of anything else alowed as an actual
argument). Expressions are evaluated to produce a value. That value is
what then gets passed. It is just plain a value not associated (aka
aliased) to anything that might have been in the expression. You might
as well say it is a temporary because if it weren't a temporary it would
be associated with the variable inside the parens. Only of the compiler
concludes that the association wouldn't matter can it get by with
optimizing away the temp.

--
Richard Maine
email: last name at domain . net
dimnain: summer-triangle

glen herrmannsfeldt

unread,
Sep 11, 2015, 7:01:04 AM9/11/15
to
Richard Maine <nos...@see.signature> wrote:

(snip,I wrote)

>> As I understand it, parenthesese don't automatically create a temporary.

>> In Fortran, parentheses do come into the aliasing rules, but not
>> in such an easy to explain way.

> Seems straightforward enough to me. But then I'd also say that they
> essentially create a temporary. Maybe if you don't see it that way,
> that's why you find it hard to explain. :-)

OK, so can you:

CALL SUB((X))

and then:

SUBROUTINE SUB(Y)
PRINT *,Y
Y=3
END

> The Fortran standard doesn't use the term "temporary" and that is
> admitedly an implementation detail left to the compiler. But what the
> standard does say is close enough to saying that a temporary is created
> that I'd say you could consider it to say that, with the understanding
> that the compiler is also allowed to optimize the temporary away if it
> concludes it can safely do so.

> The parens explicitly make the argument an expression (as they fit the
> syntax of an expression, but not of anything else alowed as an actual
> argument). Expressions are evaluated to produce a value. That value is
> what then gets passed. It is just plain a value not associated (aka
> aliased) to anything that might have been in the expression. You might
> as well say it is a temporary because if it weren't a temporary it would
> be associated with the variable inside the parens. Only of the compiler
> concludes that the association wouldn't matter can it get by with
> optimizing away the temp.

-- glen

Wolfgang Kilian

unread,
Sep 11, 2015, 7:27:23 AM9/11/15
to
On 11.09.2015 13:00, glen herrmannsfeldt wrote:
> Richard Maine <nos...@see.signature> wrote:
>
> (snip,I wrote)
>
>>> As I understand it, parenthesese don't automatically create a temporary.
>
>>> In Fortran, parentheses do come into the aliasing rules, but not
>>> in such an easy to explain way.
>
>> Seems straightforward enough to me. But then I'd also say that they
>> essentially create a temporary. Maybe if you don't see it that way,
>> that's why you find it hard to explain. :-)
>
> OK, so can you:
>
> CALL SUB((X))
>
> and then:
>
> SUBROUTINE SUB(Y)
> PRINT *,Y
> Y=3
> END

Give Y the VALUE attribute, then, yes.

(X) as an actual argument behaves like a temporary but is not definable.
VALUE makes the dummy definable, regardless what the actual argument is.

>
>> The Fortran standard doesn't use the term "temporary" and that is
>> admitedly an implementation detail left to the compiler. But what the
>> standard does say is close enough to saying that a temporary is created
>> that I'd say you could consider it to say that, with the understanding
>> that the compiler is also allowed to optimize the temporary away if it
>> concludes it can safely do so.
>
>> The parens explicitly make the argument an expression (as they fit the
>> syntax of an expression, but not of anything else alowed as an actual
>> argument). Expressions are evaluated to produce a value. That value is
>> what then gets passed. It is just plain a value not associated (aka
>> aliased) to anything that might have been in the expression. You might
>> as well say it is a temporary because if it weren't a temporary it would
>> be associated with the variable inside the parens. Only of the compiler
>> concludes that the association wouldn't matter can it get by with
>> optimizing away the temp.
>
> -- glen
>

-- Wolfgang

--
E-mail: firstnameini...@domain.de
Domain: yahoo

glen herrmannsfeldt

unread,
Sep 11, 2015, 2:23:17 PM9/11/15
to
Wolfgang Kilian <kil...@invalid.com> wrote:
> On 11.09.2015 13:00, glen herrmannsfeldt wrote:
>> Richard Maine <nos...@see.signature> wrote:

(snip,I wrote, regarding parentheses and actual arguments)


>> OK, so can you:

>> CALL SUB((X))

>> and then:

>> SUBROUTINE SUB(Y)
>> PRINT *,Y
>> Y=3
>> END

> Give Y the VALUE attribute, then, yes.

> (X) as an actual argument behaves like a temporary but is not definable.
> VALUE makes the dummy definable, regardless what the actual argument is.

Yes.

PL/I, originating in the early 1960's at a time when a favorite
Fortran error was modifying a constant actual argument, supplies
modifiable temporaries for constants and parenthesized actual
arguments.

To me, that is a nice simple rule. You know what the compiler is
doing, why it is doing it, and what it allows you to do.

So, why does Fortran not use definable temporaries?

That is the not so easy to explain part that I mentioned previously.


-- glen

Richard Maine

unread,
Sep 11, 2015, 2:48:53 PM9/11/15
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> PL/I, originating in the early 1960's at a time when a favorite
> Fortran error was modifying a constant actual argument, supplies
> modifiable temporaries for constants and parenthesized actual
> arguments.
>
> To me, that is a nice simple rule. You know what the compiler is
> doing, why it is doing it, and what it allows you to do.
>
> So, why does Fortran not use definable temporaries?
>
> That is the not so easy to explain part that I mentioned previously.

You might have different preferences, but I don't see what is hard to
explain about it. Maybe you find it hard to explain *WHY* that is the
case, but I don't see it as hard at all to explain what the facts are.
Expressions are not definable. Ever.

If one tries to mention the VALUE attribute as an exception, I'll argue
that the VALUE attribute takes a value and makes a definable temporary
with it as the initial value. Yes, in some sense this means that one
could think of 2 temporaries when you pass something like (x) as an
actual argument for a VALUE dummy. The expression result is put in one
temporary and that is then copied to the other temporary created by the
VALUE attribute. An implementation might well optimize one of them away,
but that's pretty much the model. The temporary created by VALUE is
definable, but the one created by the parens is not.

For what its worth, and at the risk of inciting the wrath of our
favorite proponent of PL/I as the perfect solution to everything, I'll
note that the PL/I way regularly confused me and resulted in me writing
buggy code. I several times got caught by changing the value of a local
copy when I intended to change the value of the actual argument. Yes,
I'm sure someone will point out that this labels me as a slow learner. I
would say that the Fortran default makes sense to me if only because the
vast majority of the time that one changes the value of a dummy
argument, one intends for it to also change the actual. It certainly
does happen that one sometimes wants a modifyable copy that doesn't
propogate back to the actual, but I consider this the minority case.

I made that eror in my PL/I code a lot larger percentage of the time
than I made the converse error in my Fortran code.

(And no, I won't debate this with Robin. I won't actually debate it with
anyone actually. Just content to point out that I have a different
perspective on it. Some people can civilly accept that different
perspectives exist. Other people... have a harder time with that.)

FortranFan

unread,
Sep 11, 2015, 2:51:30 PM9/11/15
to
On Friday, September 11, 2015 at 2:23:17 PM UTC-4, glen herrmannsfeldt wrote:

> ..
>
> So, why does Fortran not use definable temporaries?
>
> ..


Isn't that is achieved using the VALUE attribute in the current Fortran standard, that the previous poster mentioned?


glen herrmannsfeldt

unread,
Sep 11, 2015, 4:28:09 PM9/11/15
to
Richard Maine <nos...@see.signature> wrote:

(snip, I wrote)

>> PL/I, originating in the early 1960's at a time when a favorite
>> Fortran error was modifying a constant actual argument, supplies
>> modifiable temporaries for constants and parenthesized actual
>> arguments.

>> To me, that is a nice simple rule. You know what the compiler is
>> doing, why it is doing it, and what it allows you to do.

>> So, why does Fortran not use definable temporaries?

(snip)

> You might have different preferences, but I don't see what is hard to
> explain about it. Maybe you find it hard to explain *WHY* that is the
> case, but I don't see it as hard at all to explain what the facts are.
> Expressions are not definable. Ever.

(snip on VALUE attribute)

> For what its worth, and at the risk of inciting the wrath of our
> favorite proponent of PL/I as the perfect solution to everything, I'll
> note that the PL/I way regularly confused me and resulted in me writing
> buggy code. I several times got caught by changing the value of a local
> copy when I intended to change the value of the actual argument. Yes,
> I'm sure someone will point out that this labels me as a slow learner. I
> would say that the Fortran default makes sense to me if only because the
> vast majority of the time that one changes the value of a dummy
> argument, one intends for it to also change the actual. It certainly
> does happen that one sometimes wants a modifyable copy that doesn't
> propogate back to the actual, but I consider this the minority case.

OK, one feature of PL/I is the ability to specify the many different
attributes of a variable, or write a constant with appropriate attributes.

This complicates the passing of arguments and conveniently, with
appropriate prototypes, PL/I will convert arguments for you.

Compilers I knew were good at giving warning messages in that case,
as the argument conversion is one way.

Personally, I found it better than what Fortran did, and I presume
still does, pass the bits of the wrong type of argument, but I can
see that it can cause problems.

Note, for example, that to PL/I FLOAT BINARY(50) and FLOAT BINARY(51)
are distinct data types, even though they both might have the same
machine representation. In contrast, Fortran

REAL(SELECTED_REAL_KIND(14))

and

REAL(SELECTED_REAL_KIND(15))

are likely the same data type, which you can test
by testing the values of SELECTED_REAL_KIND.

I am not sure by now in which cases the compiler will do a one-way
conversion.

It could be more obvious, such as passing a fixed point variable
to a floating point dummy.

> I made that eror in my PL/I code a lot larger percentage of the time
> than I made the converse error in my Fortran code.

If actual and dummy arguments agree in attributes, there should be
no conversion. But often enough, they don't.

For another interesting conversion case, is the case of ENTRY
statements, PL/I will oonvert the return value to one with
the appropriate attributes for the specific ENTRY point.
(It is probably better not to use ENTRY points with different
attributes, though.)

Fortran, as I understand it, EQUIVALENCEs the return values.

> (And no, I won't debate this with Robin. I won't actually debate it with
> anyone actually. Just content to point out that I have a different
> perspective on it. Some people can civilly accept that different
> perspectives exist. Other people... have a harder time with that.)

Yes, I won't debate with him, though I do have fun replying sometimes.

-- glen

glen herrmannsfeldt

unread,
Sep 11, 2015, 4:33:45 PM9/11/15
to
FortranFan <pare...@gmail.com> wrote:

(snip, I wrotei)
>> So, why does Fortran not use definable temporaries?


> Isn't that is achieved using the VALUE attribute in the current
> Fortran standard, that the previous poster mentioned?

Well, VALUE relates to the called routine, where the need for
temporaries it determined by the caller.

As noted, PL/I passes a definable temporary for expressions and
constants. The called routine doesn't have to know about it.

It might be that a common implementation of VALUE is a temporary
in the called routine.

(The usual C call convention pushes the values on the stack,
and progams can modify the stack version. That might not be
best on all machines. Fortran presumably agrees with C for
BIND(C) routines.)

-- glen

0 new messages