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

Q: Aliasing and the standard

60 views
Skip to first unread message

Jos Bergervoet

unread,
Jan 23, 1999, 3:00:00 AM1/23/99
to

Although aliasing has often been discussed here, I'm still puzzled
about the exact implications for the following example:

call triple(x, x) ! will x be tripled ???

subroutine triple (a, b)
real, intent(in) :: a
real, intent(out) :: b
b = 3*a
end

Suppose the compiler uses copy in/out for both a and b (ignoring the
intent specifiers). Suppose the copy-out of a is done last, like:
copy in a
copy in b ! superfluous, but allowed by the standard?
do the work (local b = 3*a)
copy out b
copy out a ! Superfluous for intent(in), but standard allows it?

Then x will not be tripled at all after the call in the main program.
It has back its original value. Can this occur? Or does the standard
require that intent(in) items are NOT copied out?

And if the latter applies, is the above one of the few LEGAL uses of
aliasing? Or does the standard reject this in any case?

Thanks in advance,
Jos

Richard Weaver

unread,
Jan 23, 1999, 3:00:00 AM1/23/99
to
Rejected. Briefly, if something is defined through a dummy argument
then it may be referenced only through that dummy argument. In the
standard see "Restrictions on entities associated with dummy
arguments".

Dick W


In <bergervo....@iaehv.IAEhv.nl> berg...@iaehv.IAEhv.nl (Jos

Richard Maine

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to
berg...@iaehv.IAEhv.nl (Jos Bergervoet) writes:

>
> Although aliasing has often been discussed here, I'm still puzzled
> about the exact implications for the following example:

[elided]

> Suppose the compiler uses copy in/out for both a and b...

One can suppose many things, but they need not be true. The normative
text (that's standard-speak for the "official" part) of the standard
says nothing at all about copy-in/copy-out. There may be some mention
of it in the notes.

As Dick Weaver mentioned, the elided code is illegal. The section of
the standard that forbids this does not even mention the words INTENT
or copy-in/copy-out.

Yes, parts of the standard are written in ways specifically intended
to allow copy-in/copy-out or not, at the compiler's option. So one
can make guesses about what the standard might allow by thinking about
things that would work in both cases. But they would be only guesses.

Yes, I would hope that a compiler that did copy-in/copy-out would be
smart enough to avoid the copy-out for INTENT(IN) arguments, but the
standard doesn't require this.

Consider here the case where the compiler does *NOT* do
copy-in/copy-out (as indeed many compilers do not). Then changes in
the INTENT(OUT) argument could affect values subsequently used for the
INTENT(IN) argument. True, your particular sample doesn't
subsequently use the INTENT(IN) argument, but that's getting far too
complicated a condition to reasonably put in the standard. The rules
here are already quite complicated enough. Anyway, this is just
an attempt at rationalization/explanation. Whether one agrees that
its a good explanation or not, it remains that the standard forbids
the sample shown.

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Ron Shepard

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to
In article <bergervo....@iaehv.IAEhv.nl>, berg...@iaehv.IAEhv.nl
(Jos Bergervoet) wrote:

>[...] Or does the standard reject this in any case?

I think so.

On the other hand, the calling sequence

call triple( (x), x )

bypasses the aliases problems (in practice by creating a temporary) and
gives the desired result.

$.02 -Ron Shepard

Tony T. Warnock

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to

Ron Shepard wrote:

I wouldn't rely on it. The extraneous parentheses may be eliminated by a
clever compiler.

Tony


Richard Maine

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to
"Tony T. Warnock" <u09...@cic-mail.lanl.gov> writes:

> Ron Shepard wrote:
> > call triple( (x), x )
> > bypasses the aliases problems (in practice by creating a temporary) and
> > gives the desired result.
>

> I wouldn't rely on it. The extraneous parentheses may be eliminated by a
> clever compiler.

Such "cleverness" would be a violation of the standard. But Tony's
statement is still true - that one perhaps shouldn't rely on it.
You'd have a valid complaint against the compiler vendor for a
violation of the standard, but that doesn't mean you won't find
compilers with the problem.

I think I recall someone running a bunch of tests of this on
various compilers, but the details escape me.

So if one wanted to stand on abstract "correctness", the extra parens
should make it work. If one cared more about writing code that worked
on a maximum of platforms with a minimum of fuss, I'd not count on it.
I'm usually more interested in having my stuff work than in being able
to blame someone else for it not working. (A philosophy that clearly
makes me ineligible for a management position, but I'll avoid saying
anything more along that line lest I get in trouble again for making
"unnecessarily derogatory" remarks about management - and besides it
would be off-topic).

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Steve Lionel

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Richard Maine <ma...@altair.dfrc.nasa.gov> wrote in message
news:ue3e4yo...@altair.dfrc.nasa.gov...

>"Tony T. Warnock" <u09...@cic-mail.lanl.gov> writes:
>
>> Ron Shepard wrote:
>> > call triple( (x), x )
>> > bypasses the aliases problems (in practice by creating a temporary) and
>> > gives the desired result.
>>
>> I wouldn't rely on it. The extraneous parentheses may be eliminated by a
>> clever compiler.
>
>Such "cleverness" would be a violation of the standard. But Tony's
>statement is still true - that one perhaps shouldn't rely on it.
>You'd have a valid complaint against the compiler vendor for a
>violation of the standard, but that doesn't mean you won't find
>compilers with the problem.

I disagree. There is no requirement that a compiler create a temporary for
(x) - that's just an expression and the program is still required to follow
the standard's rules for aliasing which prevents routine triple from
changing the value of x (since it would change the value of the expression -
12.4.1.6(1))

While it's true that many compilers DO make a temporary copy for (x), that's
simply a nice feature and NOT required by the standard.

Please send Visual Fortran support questions to dvf-s...@digital.com

Steve Lionel mailto:Steve....@digital.com
DIGITAL Fortran Development http://www.digital.com/info/slionel.html
Compaq Computer Corporation
110 Spit Brook Road, ZKO2-3/N30
Nashua, NH 03062-2698 "Free advice is worth every cent"

DIGITAL Fortran web site: http://www.digital.com/fortran

William Clodius

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Steve Lionel wrote:
> <snip>

> I disagree. There is no requirement that a compiler create a temporary for
> (x) - that's just an expression and the program is still required to follow
> the standard's rules for aliasing which prevents routine triple from
> changing the value of x (since it would change the value of the expression -
> 12.4.1.6(1))
> <snip>

The question is: What is the meaning of an expression, even such a
simple one as (x)? Is it:

1. A separate entity that can be replaced with another entity with the
same values, the other entity in this case being x, only if the compiler
can show there are no side effects in the statement modifying the two
entities? This interpretation would forbid aliasing x and (x) in this
case.

2. Is there a distinction between defining an entity using an expression
and an assignment? What is the meaning of y in

y = x
call triple( y, x)

and how does it differ from the meaning of (x)?

3. Is (x) a special meaningless case of an expression?

For what its worth my interpretation has always been 1.

--

William B. Clodius Phone: (505)-665-9370
Los Alamos Nat. Lab., NIS-2 FAX: (505)-667-3815
PO Box 1663, MS-C323 Group office: (505)-667-5776
Los Alamos, NM 87545 Email: wclo...@lanl.gov

Dick Hendrickson

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Steve Lionel wrote:
>
> Richard Maine <ma...@altair.dfrc.nasa.gov> wrote in message
> news:ue3e4yo...@altair.dfrc.nasa.gov...
> >"Tony T. Warnock" <u09...@cic-mail.lanl.gov> writes:
> >
> >> Ron Shepard wrote:
> >> > call triple( (x), x )
> >> > bypasses the aliases problems (in practice by creating a temporary) and
> >> > gives the desired result.
> >>
> >> I wouldn't rely on it. The extraneous parentheses may be eliminated by a
> >> clever compiler.
> >
> >Such "cleverness" would be a violation of the standard. But Tony's
> >statement is still true - that one perhaps shouldn't rely on it.
> >You'd have a valid complaint against the compiler vendor for a
> >violation of the standard, but that doesn't mean you won't find
> >compilers with the problem.
>
> I disagree. There is no requirement that a compiler create a temporary for
> (x) - that's just an expression and the program is still required to follow
> the standard's rules for aliasing which prevents routine triple from
> changing the value of x (since it would change the value of the expression -
> 12.4.1.6(1))
>
> While it's true that many compilers DO make a temporary copy for (x), that's
> simply a nice feature and NOT required by the standard.
>
Mostly I sort of disagree with Steve. True, there is no requirement
that a compiler create a temporary, there is no "requirement" that
a compiler ever generate any particular type of code. But, "(x)"
is very different from "x" and a compiler must know what the
differences are and do something about it. In something like:
subroutine xxx(a,b)
b = a
b = b + a
end

Given a perfectly legal sequence like
x = 1.0
call xxx((x),x)
print *, x

the program must print 2.0.
A call like call xxx(x,x) is flat out illegal because if there is any
aliasing between actual arguments then neither of them may be defined
in xxx.

However, the actual argument "(x)" must be evaluated (somehow)
before the call and this value becomes associated with the dummy
argument a, while "x" becomes associated with "b". "Intent" within
the subroutine has no effect on this.

Dick Hendrickson

Richard Maine

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
"Steve Lionel" <Steve....@digital.com> writes:

> Richard Maine <ma...@altair.dfrc.nasa.gov> wrote in message

> >> > call triple( (x), x )

> >> I wouldn't rely on it. The extraneous parentheses may be eliminated by a
> >> clever compiler.
> >

> >Such "cleverness" [eliminating the apparently extraneous parend]
> >would be a violation of the standard....

> I disagree. There is no requirement that a compiler create a temporary for
> (x) - that's just an expression and the program is still required to follow
> the standard's rules for aliasing which prevents routine triple from
> changing the value of x (since it would change the value of the expression -
> 12.4.1.6(1))
>
> While it's true that many compilers DO make a temporary copy for (x), that's
> simply a nice feature and NOT required by the standard.

Agree that the standard doesn't use the words "temporary" or "copy".
If a compiler can make it all work some other way, that's fine. But
I disagree about what cases it is that a compiler has to make work.
In particular, I claim that it is allowed for the code to change
the value of x through the second argument here.

Hmm... Interesting point though. I still disagree with what I think
you are arguing, but I'll admit there is some subtlety to the
question. I interpret 12.4.1.6(1) as applying to the case "call
triple(x, x)". In that case, the entity associated with the first
dummy argument is x, and 12.4.1.6(1) pretty clearly applies and says
that the value of x can't be changed through the second argument (or
through the first either).

However, in the case "call triple((x), x)", the entity associated with
the first dummy argument is the result of evaluation of the expression
"(x)". I don't think that changing the value of x during execution of
the procedure affects the value of the expression (x) evaluated at the
procedure invocation. It affects the value of the variable x; variables
by definition have values that can change during execution of a program.
But an expression is not a variable. Having been evaluated, the value
of an expression can no longer change. (You might loop back and execute
the same code again later, but that will be a different instance of the
expression evaluation, not a changed value for the original expression).
Just as in the straight-line code

x = 3.
write (*,*) x+1.
x = 7.

I would not say that the "x=7." affects the value of the x+1. expression
in the write.

The compiler can certainly evaluate the actual arguments in any order
(or in parallel). So the evaluation of one actual argument can't
affect variables used in expressions in any others (restrictions on
function side effects). And a compiler could avoid evaluating an
actual argument altogether in some cases, or could delay evaluation
until needed if its smart enough. But if it delays evaluation until
needed, I think it had better handle cases where variables used in the
expression might have changed values.

For example, I would be most upset (and I feel justifiably so), if the
compiler decided that, since it is buffering output, the x+1. in the
write statement above could be evaluated later...using the then-current
value of 7. for x.

In the "call triple((x), x)", if the compiler can see that the procedure
does not reference its first dummy argument after changing the second,
it could get by without a copy. Or there are probably other valid
implementation schemes also. But I'd claim that the code

x = 7.
call triple( (x), x)
..
subroutine triple(a, b)
b = 100.
b = 3.*a
end

is legal (if a bit stupid) and had better end up with a value of 21. instead
of 300. for x. (Ok, being floats, perhaps 300. is a (poor) approximation
of 21. So change the example to integer to be pedantic). If the compiler
makes this work ok, then the standard isn't pickly about details like
whether this involved a temporary copy. Of course, a compiler is likely
to make this case work by optimizing away the b=100., but the same
principles apply to more complicated cases that don't so obviously
optimize away.

Anyway, my basic argument here is that the value of the expression
(x) is not affected by *SUBSEQUENT* changes in the value of x. I
distinguish this from the case where the actual argument is a variable;
the value of a variable is affected by subsequent changes in the
value of the variable. (Yes, I know that last part is a tautology,
but I wanted to use parallel wording to illustrate the difference).

I'll admit the distinction here is subtle. Perhaps I could even be
wrong. This is the interpretation I'd always assumed, but it might
take some digging around to see whether there is text in the
standard to actually support it as definitive. Seems like
something about expression evaluation in general ought to be
applicable. Something has to establish that expressions are
evaluated with the "current" values of the variables and that you can't
just evaluate expressions at any random time when the variable values
are different. And something ought to establish that the values of
expressions in actual arguments are defined by the values at the
time of the call (modulo the separate issue of side effects of
functions involved in the actual argument expressions).

I don't have time to track this all down in that much detail right
now.

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Jos Bergervoet

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Dick Hendrickson <dick.hen...@att.net> writes:

>A call like call xxx(x,x) is flat out illegal because if there is any
>aliasing between actual arguments then neither of them may be defined
>in xxx.

Thanks for the explanations from all respondents.

These illegal calls, however, do occur in some programs. Most compilers do
not complain oabout it. I am wondering what can go wrong if you do this and
if you're careful not to rely on the original value of x after you may have
changed it through aliasing?

It seems to me that, although against the standard, it can not go wrong
unless I assume a copy-in .AND. a superfluous copy-out, as I did in my
original posting.

So if it is wrong why don't compilers reject it? (even some strict subset
compilers!)

And if it is (apparently) so difficult to flag, why is the standard against
it? Couldn't it just say that it's the programmers own responsibility: they
could write their routines in an "aliasing safe" way if they want, just
like they can be written thread safe or not?


-- Jos


Dick Hendrickson

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Jos Bergervoet wrote:
>
> Dick Hendrickson <dick.hen...@att.net> writes:
>
> >A call like call xxx(x,x) is flat out illegal because if there is any
> >aliasing between actual arguments then neither of them may be defined
> >in xxx.
>
> Thanks for the explanations from all respondents.
>
> These illegal calls, however, do occur in some programs. Most compilers do
> not complain oabout it. I am wondering what can go wrong if you do this and
> if you're careful not to rely on the original value of x after you may have
> changed it through aliasing?

What can go wrong is that the compiler might do something you didn't
count
on. If you really and truly think of the two aliased dummy arguments as
one thing, why not write the subroutine with only one argument? That
would
solve the problem. But, that's not a sulution, because, as you know,
subroutines
are written by different people and used differently by different
people.
Where things can go wrong is in optimizations. Compilers are getting
better
and better at keeping things in registers; not just variables, but
expression
values. If we didn't have the no-alias rule a compiler would be forced
to
do reloads of all dummy arguments after any argument definitions. Given
that
optimizers ofter reorder code you can't be sure that you're careful not
to
rely on the original value. Something like:
subroutine xxx(A,B)
A = 1
B = 1/B
end
Since divide is often a slow operation (this is my Cray background
<grin>)) many
optimizers will load B and start the divide before they store the 1 into
A. This
is OK if A and B are different things. Similarly, compilers extract
loop invarient
code. Something like
subroutine yyy(C,D)
real D(10)
do I = 1,10
D(I) = D(I)/C
enddo
end
without the no-alias rule the compiler would be forced to cover the case
where
C is aliased to an element in D and not compute something like register
= 1/C
in the loop preamble.


>
> It seems to me that, although against the standard, it can not go wrong
> unless I assume a copy-in .AND. a superfluous copy-out, as I did in my
> original posting.

No, as above, multiple uses of a variable in an optimized subroutine can
also
go wrong.

>
> So if it is wrong why don't compilers reject it? (even some strict subset
> compilers!)

Because it's hard to detect in general. Separate compilation is one
example.
Passed in routine names are another. Something like:
subroutine zzz(ext,a)
call ext(a,a)
end
might or might not be OK. Conditional execution is also undetectable.
Somethin like:
subroutine xyz(e,f)
if (e = 23) f = 17
end
I'm not sure if call xyz(29,29) is legal or not.


>
> And if it is (apparently) so difficult to flag, why is the standard against
> it? Couldn't it just say that it's the programmers own responsibility: they
> could write their routines in an "aliasing safe" way if they want, just
> like they can be written thread safe or not?

Maybe, but as I tried to show above, it's hard to write that way and be
sure
that you've got it right for all possible compilers and hardwares.

Dick Hendrickson
>
> -- Jos

Dan Nagle

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Hello,

Richard Maine wrote:
>
<snip ongoing discussion>


>
> However, in the case "call triple((x), x)", the entity associated with
> the first dummy argument is the result of evaluation of the expression
> "(x)". I don't think that changing the value of x during execution of
> the procedure affects the value of the expression (x) evaluated at the
> procedure invocation. It affects the value of the variable x; variables
> by definition have values that can change during execution of a program.
> But an expression is not a variable. Having been evaluated, the value
> of an expression can no longer change. (You might loop back and execute
> the same code again later, but that will be a different instance of the
> expression evaluation, not a changed value for the original expression).
> Just as in the straight-line code
>
> x = 3.
> write (*,*) x+1.
> x = 7.
>
> I would not say that the "x=7." affects the value of the x+1. expression
> in the write.

I think, in the case of write()'s, that the situation may be
worse than stated. Suppose, on different runs of the same program,
the OS decided to allocate different amounts of buffer space to
the program. Then on one run, the write may use the x = 3., and
on another run the write may use the x = 7.

I would certainly object to an interpretation which allowed
a program to execute to completion and give different answers
on different runs based upon the OS allocating differently
sized buffers! (Except, of course, execution time :-)

>
<snip further discussion>
>
> --
> Richard Maine
> ma...@altair.dfrc.nasa.gov

--

Cheers!
Dan Nagle dna...@erols.com

Richard Maine

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
berg...@iaehv.IAEhv.nl (Jos Bergervoet) writes:
> Dick Hendrickson <dick.hen...@att.net> writes:
>
> >A call like call xxx(x,x) is flat out illegal because if there is any
> >aliasing between actual arguments then neither of them may be defined
> >in xxx.

> It seems to me that, although against the standard, it can not go wrong


> unless I assume a copy-in .AND. a superfluous copy-out, as I did in my
> original posting.

Many things can and do go wrong. If you ignore this, it is completely
at your own peril. I gave one example of a different scenario in a
previous post.

> So if it is wrong why don't compilers reject it? (even some strict subset
> compilers!)

Starvation is wrong. Why does it happen. :-)

Its hard to test in all cases, particularly with subroutines that have
implicit interfaces and are in separate files. Presumably vendors have
finite resources and must tradeoff cost versus benefit, just like pretty
in much every other activity. I've never yet seen a compiler that
catches absolutely every error....and I never expect to see one. Once
you realize that, it becomes much more of a judgement call about what
errors are worth diagnosing. Just saying "this is an error, so the
compiler should catch it" isn't going to be a very convincing argument
for a complete redesign of the compilation system...and for taking
resources that might otherwise have been spent on diagnosing other
errors.

> And if it is (apparently) so difficult to flag, why is the standard against
> it? Couldn't it just say that it's the programmers own responsibility: they
> could write their routines in an "aliasing safe" way if they want, just
> like they can be written thread safe or not?

Well, in a way that's what the standard does say. It says that code
like this is non-standard. This is pretty much the same as saying
that its the programmer's responsibility. The standard says nothing
at all about what happens. If you know how your compiler works and
know that it will do what you want, then the standards committee won't
send around an agent in the middle of the night to put a stop to it.
On the other hand, don't expect much sympathy when the code doesn't
work on the next machine you try to port it to, on the next release
of the same compiler, when used in a different context with the same
compiler, etc..

And don't expect much help in figuring out how to write your code
"aliasing safe". My only advice on how to do so is to stick to the
standard. Otherwise, I "wash my hands" of the results. I think its a
bad idea to even try to figure out what non-standard things you can
"get by with" in this regard. Looks to me like you've missed even
some trivial ways that such code could have problems (see earlier
post). I don't even know all of the complicated ones - haven't tried
to think out all the obscure possibilities - don't intend to bother.

So, yes, its "the programmer's responsibility." I think thats just
a bigger burden than you realize.

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Richard Weaver

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
In <uer9six...@altair.dfrc.nasa.gov> Richard Maine <ma...@altair.dfrc.nasa.gov>
writes:
>
>"Steve Lionel" <Steve....@digital.com> writes:
>
>> Richard Maine <ma...@altair.dfrc.nasa.gov> wrote in message
>> >> > call triple( (x), x )
>
>...[snip]

>However, in the case "call triple((x), x)", the entity associated with
>the first dummy argument is the result of evaluation of the expression
>"(x)". I don't think that changing the value of x during execution of
>the procedure affects the value of the expression (x) evaluated at the
>procedure invocation. It affects the value of the variable x; variables
>by definition have values that can change during execution of a program.
>But an expression is not a variable.
>... [snip]

My comments apply to several recent posts in this thread; Richard's is simply the
latest I've seen.

A variable is allowed as an expression; see ch 7. Everything past
primary is optional. For example, there is the assignment statement,
variable = expr, where variables are clearly allowed on the right.
Thus an expression can be a variable in exactly the same sense as "an
expression can be real". "Any expression" is not a variable; neither is
"Any expression" "real".

So, "X" is just as much an expression as "(X)" or "X+X".

When, for example, the syntax for actual-arg says "is expr or variable
or ..." it would seem that "or variable" can be deleted as redundant.
Distinctions of the form "when the expression is a variable ..." would
need to be in the constraints or text.

I couldn't find any (in Fortran 90, my last free standard) text that
was dependent on an actual argument being a variable. Its
"Restrictions on entities ...".

So it gets interesting. X + X would not be definable, but for a clever
compiler X + X - X would be a definable actual argument (ignoring
exceptions).

Gee, I'd forgotten how much fun this stuff can be.

Dick W

Richard Weaver

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
In <bergervo....@iaehv.IAEhv.nl> berg...@iaehv.IAEhv.nl (Jos Bergervoet)

writes:
>
>Dick Hendrickson <dick.hen...@att.net> writes:
>
>>A call like call xxx(x,x) is flat out illegal because if there is any
>>aliasing between actual arguments then neither of them may be defined
>>in xxx.
>
>Thanks for the explanations from all respondents.
>
>These illegal calls, however, do occur in some programs. Most compilers do
>not complain oabout it. I am wondering what can go wrong if you do this and
>if you're careful not to rely on the original value of x after you may have
>changed it through aliasing?
>
>It seems to me that, although against the standard, it can not go
wrong
>unless I assume a copy-in .AND. a superfluous copy-out, as I did in my
>original posting.

As I recall, your example was something like b = 3a. A valid
evaluation is

b = a
b = b + a
b = b + a

So call by reference can also fail.

Dick W

James Giles

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
In general, the Fortran standard does not prohibit things. I describes
the interpretation of standard conforming programs. If the program
does not conform to the standard, the compiler is free to do as it
likes (something that I've argued against in the past). In this case,
the call to triple((x),x) has a standard conforming interpretation if
the procedure does not redefine the first argument, even if it does
define or redefine the second argument.

The standard document associates semantic properties of the language
with syntactic categories (the non-terminal names in the published grammar).
The first argument to the procedure, '(x)', is in the syntactic category of
_primary_ (using '_' to indicate italics). The production rule is R701 (F90).
The second argument has the more specific syntactic category _variable_.
There is no way to parse the first argument (according to the standard
grammar) which yields the syntactic category of _variable_ for the
first argument. Therefore, the first argument has the semantic interpretation
within the standard of a primary expression. The second has the additional
properties (and liberties) of a variable (I say "additional" because it can
also be reduced through R701 to a _primary_).

None of this would be the least controversial if the first argument had been
'(x+5)'. No one would have even suggested there was a possible problem
here. The confusion arises when the expression consists only of parens
around a variable. But the requirements of the standard are the same for
both expressions. (I wonder what the debate would have been with
triple((x+0),x)? Would people have assumed that this was ambiguous?)

Now, this is all aside from the comment Dr. Warnock made: it is probably
unsafe to assume that a given compiler will treat the call correctly. Even if
you have tested the compiler in a test instance to make sure it does the right
thing, it may not do so consistently. Vendors are under considerable pressure
to produce fast code. Not all the transformations they attempt in this regard
are always correct. Perhaps the best thing to do is make your temporary explicit:

y=x
call triple(y,x)

--
J. Giles


William Clodius

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Jos Bergervoet wrote:
> <snip>

> So if it is wrong why don't compilers reject it? (even some strict subset
> compilers!)
> <snip>

The general case cannot be solved as it is equivalent to the halting
problem. In the following how is the compiler to verify that x(i) is a
not the same memory location as x(j)? Of course with user error and no
checking they might have the same memory location.

write(*,*) 'Input two different integers between 1 and 10'
read(*,*) i, j
call triple( x(i), x(j))

Richard Maine

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
rwe...@ix.netcom.com(Richard Weaver) writes:

> When, for example, the syntax for actual-arg says "is expr or variable
> or ..." it would seem that "or variable" can be deleted as redundant.
> Distinctions of the form "when the expression is a variable ..." would
> need to be in the constraints or text.

Yes, there are several such cases of wording like that. I agree they
are poor wording. (They predate my stint as editor and that hasn't
been something I've taken the time to go back and fix up). Without
trying to hash out the precise words on comp.lang.fortran, the
intent in all such cases that I know of is roughly as you describe - that
the case where the argument (or whatever) is a variable is treated
differently from that of more general expressions.

I would argue (fairly strongly) that x+x-x is not definable. The *ONLY*
way you get in the special case is when the expression consists of
a single primary that is a variable (or some such wording - I might
have missed something doing it on the fly like this).

--
Richard Maine
ma...@altair.dfrc.nasa.gov

William Clodius

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
From my point of view, the question is: Does Fortran's argument passing
mechanism have strict semantics for expressions used as arguments to
procedures, i.e., is the x in the expression (x), defined to have the
value it has before the procedure is invoked? I expect (x) to have a
well defined value if (x+5) has a well defined value.

Steve Lionel

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Wow - I never thought I'd get tangled up in a discussion of the standard
with folks such as have responded here - Richard Maine in particular!

I've done some more reading, and discussed this with my colleagues
(including our standards rep, Stan Whitlock), and want to make some
observations...

First, my initial contention was that a compiler that replaced:

CALL TRIPLE ((X),X)

with

CALL TRIPLE (X,X)

would still be a conforming implementation.

The section of the standard I referenced, 12.4.1.6(1), says (in part)
"Action that affects the value of the entity or any part of the entity or
any part of it shall be taken through the dummy argument ..."

However.. there is NOTE 12.23 which says "Since a dummy argument declared
with an intent of IN shall not be used to change the associated actual
argument, the associated actual argument remains constant throughout the
procedure." Now I understand that NOTEs are not a formal part of the
standard, but this certainly implies that if we had:

SUBROUTINE TRIPLE (X,Y)
REAL, INTENT(IN) :: X
REAL, INTENT(OUT) :: Y
Y = X * 3
WRITE (*,*) X
END

That the value displayed in the WRITE statement would be the same value X
had at entry to the routine. A compiler could implement this by making a
copy on entry to the routine.

But.. what if in this case X did not have INTENT(IN)? The standard permits
this, since X is not redefined within TRIPLE, but then what about the text I
cited from 12.4.1.6? There's no text I can see which requires that the
value if expression arguments be completely evaluated at the time of the
procedure reference. Does redefining the actual argument X "affect the
value" of the expression (X)?

There's another part of the standard, where the wording is clearer, that I
think is relevant here, and that is section 7.1.7, Evaluation of operations.
In part, it says: "The evaluation of a function reference shall neither
affect nor be affected by the evaluation of any other entity within the
statement. If a function reference causes definition of or undefinition of
an actual argument of the function, that argument or any associated entities
shall not appear elsewhere in the same statement."

I agree that the standard is somewhat ambiguous regarding the initial point.
And I hasten to add that our compilers DO pass a copy for (X). It's just
that I can't find clear justification in the standard for saying that a
"processor" (compiler) that transforms CALL SUB((X),X) into CALL SUB(X,X) is
non-conforming. Therefore, I would certainly agree that, no matter what,
usage of this nature is a "bad thing" and should be avoided.

Richard Weaver

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
In <ueg18xy...@altair.dfrc.nasa.gov> Richard Maine <ma...@altair.dfrc.nasa.gov>
writes:
>...[snip]

>I would argue (fairly strongly) that x+x-x is not definable. The
*ONLY*
>way you get in the special case is when the expression consists of
>a single primary that is a variable (or some such wording - I might
>have missed something doing it on the fly like this).

Ahhh, but x+x-x is not definable only if the standard says that the
result of an expression evaluation cannot be one of the expression
primaries -- and it can't say that because the expression "X" in "call
s (X)" MUST evaluate to X!

And looking through the chapter on procedures, I didn't see (may have
missed, of course) any related text about variables, only about
entities.

What we are looking at is not the intended goodness, but just which
perverse interpretations might be allowed.

Dick W

Richard Maine

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
"Steve Lionel" <Steve....@digital.com> writes:

> Wow - I never thought I'd get tangled up in a discussion of the standard
> with folks such as have responded here - Richard Maine in particular!

Dunno why not. You've always seemed knowledgable enough about some
pretty fine points of the standard to me. Not that I've always agreed
with every argument you've made....but I'd hate to "keep score" on how
many of those times that I later concluded you were right. :-)

> I've done some more reading, and discussed this with my colleagues
> (including our standards rep, Stan Whitlock),

Hi, Stan.

> But.. what if in this case X did not have INTENT(IN)?

I don't think INTENT(IN) is really relevant here. As far as I'm
aware, the compiler doesn't have to do anything different at run-time
because of the presense or absense of INTENT(IN) (though it is allowed
to). INTENT(IN) just adds a bunch of restrictions on things the user
code is allowed to do. The compiler may give diagnostics for violating
these (and it might be required to do so in some contexts - too much
a side question to be worth tracking down right now). And the
compiler is *ALLOWED* to do things differently with INTENT(IN) (doing
a call-by-value or a copy-in are two obvious possibilities), but I
don't know of anything that actually requires anything about INTENT(IN)
to be different at runtime.

> There's no text I can see which requires that the
> value if expression arguments be completely evaluated at the time of the

> procedure reference. Does redefining the actual argument X "affect the
> value" of the expression (X)?

Indeed, this appears to me to be the basic question. I believe the
intended interpretation to be that expressions in the arguments need
to be evaluated with the values defined at the time of the procedure
reference (though the actual evaluation can be deferred as long as the
right values get used). And thus redefining X does not affect the
value of the expression (x). But I don't have handy text to support
it at the moment. Don't think I'm gonna be able to give you a
definitive answer (assuming there is one) in the course of this
thread. Might be a good interp question if this really isn't covered
somewhere.

> There's another part of the standard, where the wording is clearer, that I
> think is relevant here, and that is section 7.1.7, Evaluation of operations.
> In part, it says: "The evaluation of a function reference shall neither
> affect nor be affected by the evaluation of any other entity within the
> statement. If a function reference causes definition of or undefinition of
> an actual argument of the function, that argument or any associated entities
> shall not appear elsewhere in the same statement."

Function invocations have extra restrictions because there can be
multiple of them, along with other stuff, in a single statement. A
subroutine call (including evaluation of its arguments) is always the
only thing in a statement......well...gotta be careful about saying
"always". I guess there are defined assignments, which translate
into subroutine calls, but that's a pretty restricted case.

This is probably all I have to say in this thread for now, as I
see I'me getting repetitive. I know I haven't given adequate
evidence to definitively establish the answer, but I don't think
I've got time to do so right now...would require a bit of careful
reading and searching, not just a snap reply.

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Dick Hendrickson

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to

We may have lost something in the translation from F77 to F90. Section
15.9.2 in F77 gives a bunch of restrictions on actual arguments,
including "Actual arguments may be constants,...expressions INVOLVING
OPERATORS, and expressions ENCLOSED IN PARENTHESIS if and only if
the associated dummy ...is not defined during execution of the
referenced external procedure." I couldn't find the matching words
in either F90 or F95. But I found enough to convince me that they are
there, at least in spirit <grin>.

F77 says for a CALL that the sequence is (15.6.2.2)
(1) evaluation of actual arguments that are expressions
(2) association of actual arguments with the corresponding dummy
(3) the actions specified by the procedure

In F90 Rule 1213 says an actual argument is either an expr or a
variable or... So it seems we intended to distinguish between
"(x)" and "x". The text for a CALL (12.4.4) says "When a [CALL
executes] all actual argument expressions are evaluated, then the
arguments are associated , and then the subroutione is executed."
Which is parallel to the F77 description.

Section 12.5.2.1, the last couple of lines says
"A dummy data object whose intent is not specified is subject to
the limitations of the data entity that is the associated actual
argument. That is, a reference to the dummy data object may occur
if the actual argument is defined and the dummy data object may be
defined if the actual argument is definable."

I think there is wording somewhere that defines what "definable"
means, but I can't find it right now.

But, to me it's as clear as anything else in the standard. In an
argument list the standard attempts to distinguish between an
expression and a variable. It says that the expression is evaluated
before the call, and that things that aren't "definable" (like
expressions) can't be defined in the subroutine.

Dick Hendrickson

Richard Maine

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Dick Hendrickson <dick.hen...@att.net> writes:

> The text for a CALL (12.4.4) says "When a [CALL
> executes] all actual argument expressions are evaluated, then the
> arguments are associated , and then the subroutione is executed."
> Which is parallel to the F77 description.

Thanks, Dick. I think those are the words I was looking for. Didn't
think to look there (dunno why not - just blindness). There are
simillar words in the adjacent section on function invocation. And I
checked that you quoted correctly - indeed the word "then" is used,
establishing a time relationship.

(Stuff elsewhere can be used to waffle that the processor doesn't
really have to do things at the time the standard describes it
as long as it ends up getting the same result. So this "then"
doesn't mean that the processor can't delay evaluation, but it does
mean that the answer better be the same as if it hadn't done so).

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Walt Brainerd

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
rwe...@ix.netcom.com(Richard Weaver) wrote:

> So it gets interesting. X + X would not be definable, but for a clever
> compiler X + X - X would be a definable actual argument (ignoring
> exceptions).

When all else fails, check the standard 8^):

12.5.2.1 Effects of INTENT attribute on subprograms

The INTENT attribute of dummy data objects limits the way
in which they may be used in a subprogram. A dummy data object
having INTENT (IN) must not be defined or redefined by the
subprogram. A dummy data object having INTENT (OUT) is initially
undefined in the subprogram. A dummy data object with INTENT (INOUT)
may be referenced or be defined. A dummy data object whose intent is not
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


specified is subject to the limitations of the data entity that is the

^^^^^^^^


associated actual argument. That is, a reference to the dummy data
object may occur if the actual argument is defined and the dummy data

^^^^^^^^^^^^^^


object may be defined if the actual argument is definable.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

=========================================================================

A thing is definable if it can appear on the left of an assignment.

"X" is definable
"X + X - X" is not
"(x)" is not

This is a syntactic thing and has nothing to do with the fact that
these three are "mathematically equivalent" as expressions.

Incidentally, I tried to get rid of every occurrence of "variable or
expression" in the F90 standard, so there should have been none when
you got ahold of it Richard (M)! (A grep on my copy doesn't turn up
any--unless it is broken across a line.)

--
Walt Brainerd wa...@fortran.com
Unicomp, Inc. +1-520-298-7212 298-7074 (fax)
7660 E. Broadway, Suite 203 +1-500-Fortran (367-8726)
Tucson, AZ 85710 USA http://www.fortran.com/fortran

Richard Weaver

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
In <78lmc7$7...@boofura.swcp.com> wa...@swcp.com (Walt Brainerd) writes:
>
>> ... [snip]

>12.5.2.1 Effects of INTENT attribute on subprograms
>
>The INTENT attribute of dummy data objects limits the way
>in which they may be used in a subprogram. A dummy data object
>having INTENT (IN) must not be defined or redefined by the
>subprogram. A dummy data object having INTENT (OUT) is initially
>undefined in the subprogram. A dummy data object with INTENT (INOUT)
>may be referenced or be defined. A dummy data object whose intent is
not
>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>specified is subject to the limitations of the data entity that is the
>^^^^^^^^
>associated actual argument. That is, a reference to the dummy data
>object may occur if the actual argument is defined and the dummy data
> ^^^^^^^^^^^^^^
>object may be defined if the actual argument is definable.
>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
>======================================================================
==
>
>A thing is definable if it can appear on the left of an assignment.
>
> "X" is definable
> "X + X - X" is not
> "(x)" is not
>
>This is a syntactic thing and has nothing to do with the fact that
>these three are "mathematically equivalent" as expressions.


Start with

CALL S ( X, (X), X+X-X )

and f90 (corrected per prior notes, eliminating redundant "variable")

actual-arg is expr or procedure-name or alt-return-spec

For "CAll S ... there are three expressions; all three evaluate to the
same thing (ignoring exceptions). There is nothing in Section 7
"Expressions and Assignment" that says the expression X is in anyway
different from (X) or X+X-X. You might think they are different, you
might want them to be different. But nowhere does Section 7 specify a
difference. And note that for the expression "X", the result of
evaluation of that expression MUST BE definable. Thus there is no
reason that clever compilers cannot produce a definable result for (X)
or X+X-X; the same definable result produced for the expression "X".

Your assertion that a thing is definable if it "can appear on the left
of an assignment" is a partial truth. There is an association,
"Argument association", between the expressions in a procedure
invocation and the dummy data objects of that invocation. Thus if the
dummy data object is defined, the associated argument expression is
also defined.

Hey, its no big deal, just one more interpretation that is needed.

Dick W

Dick Hendrickson

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to

But, the crux is that it is wrong to delete the "variable" here. The
wording is poor and the formal grammar isn't quite right. But if
you look at
actual-arg is expr or VARIABLE or procedure-name or alt-return-spec

it seems clear ( :-) ) that the standard is trying (imperfectly) to
distinguish between "real expressions" (the things F77 refered to
as having operators or parenthesis) and degenerate expressions like X.

When chapter seven talks about assignment it uses
R735 variable = expr
as the form and constrains "variable" to not be a constant (via
R601). Thus, x = x and x= (x) are both OK (assuming x has been
previously defined somehow), but (x) = x is bad.

It probably wouldn't hurt to add some clarifying words during the edit
phase, but I don't think anything is so unclear that half a dozen
people can't figure it out in less than a week or so :-) . I'd say
formal interps should be resolved for "real" problems; J3 has enough
to do as it is.

Dick Hendrickson

Ron Shepard

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
In article <78kl1l$p...@usenet.pa.dec.com>, "Steve Lionel"
<Steve....@digital.com> wrote:

> Richard Maine <ma...@altair.dfrc.nasa.gov> wrote in message

> news:ue3e4yo...@altair.dfrc.nasa.gov...
> >"Tony T. Warnock" <u09...@cic-mail.lanl.gov> writes:
> >
> >> Ron Shepard wrote:

> >> > call triple( (x), x )

> >> > bypasses the aliases problems (in practice by creating a temporary) and
> >> > gives the desired result.
> >>

> >> I wouldn't rely on it. The extraneous parentheses may be eliminated by a
> >> clever compiler.
> >

> >Such "cleverness" would be a violation of the standard. But Tony's
> >statement is still true - that one perhaps shouldn't rely on it.
> >You'd have a valid complaint against the compiler vendor for a
> >violation of the standard, but that doesn't mean you won't find
> >compilers with the problem.
>

> I disagree. There is no requirement that a compiler create a temporary for
> (x) - that's just an expression and the program is still required to follow
> the standard's rules for aliasing which prevents routine triple from
> changing the value of x (since it would change the value of the expression -
> 12.4.1.6(1))

No, it is the *second* argument that is changed/assigned within "triple",
not the *first* argument, which is the expression.

> While it's true that many compilers DO make a temporary copy for (x), that's
> simply a nice feature and NOT required by the standard.

It seems odd that the compiler would be able to substitute some variable
for the value of an expression in a subroutine call just because that
variable happens to have the same value. Would you say that a compiler
should be able to make the same substitution for

call triple( (x+0.0), x)

or

call triple( (x*1.0), x)

or any of many other equivalent expressions? I don't have the standard in
front of me, but it seems very odd that such substitutions would be
allowed. I would think that (x) is just as much of an expression as
(x*1.0).

$.02 -Ron Shepard

Richard Weaver

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
In <36AF2E...@att.net> Dick Hendrickson <dick.hen...@att.net> writes:
>
>Richard Weaver wrote:
>>
>>...[snip]

>> and f90 (corrected per prior notes, eliminating redundant "variable")
>>
>> actual-arg is expr or procedure-name or alt-return-spec


>
>But, the crux is that it is wrong to delete the "variable" here. The
>wording is poor and the formal grammar isn't quite right. But if
>you look at
>actual-arg is expr or VARIABLE or procedure-name or alt-return-spec
>
>it seems clear ( :-) ) that the standard is trying (imperfectly) to
>distinguish between "real expressions" (the things F77 refered to
>as having operators or parenthesis) and degenerate expressions like X.


The crux is that the concept of "variable" is nowhere used in the
following text; the deletion of the redundant syntax is not so much to
clean up the syntax as it is to make that point.

And the deletion is moot; I'm looking at f90 and Walt has already said
he deleted, or intended to delete, all such in the files passed to
Richard Maine.

I will also admit to having trouble extending a single occurence of
"variable" to "the standard is trying to distinguish between" -- even
imprefectly. But again, I'm looking at f90 and f95 might well have
better text.

Thanks for your patience
Dick W

Steve Lionel

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
Ron Shepard <she...@tcg.anl.gov> wrote in message
news:shepard-2701...@anchah.chm.anl.gov...

>It seems odd that the compiler would be able to substitute some variable
>for the value of an expression in a subroutine call just because that
>variable happens to have the same value. Would you say that a compiler
>should be able to make the same substitution for
>
> call triple( (x+0.0), x)
>
>or
>
> call triple( (x*1.0), x)
>
>or any of many other equivalent expressions? I don't have the standard in
>front of me, but it seems very odd that such substitutions would be
>allowed. I would think that (x) is just as much of an expression as
>(x*1.0).

Well, *IF* one interprets the standard as saying that changing x changes the
value of the expression, and therefore such changing of x is disallowed,
then yes, such a substitution would be valid. Some folks here, including
myself, think the standard is ambiguous on this point. But I think everyone
agrees that it would be inappropriate for a compiler (in the real world) to
actually make such a translation.

"Language lawyering" is a tricky business, and sometimes the standard says
things that seem to defy "common sense". In areas such as this one, you
have to be very careful in determining when and in what order certain events
occur. And I *DO* have the standard in front of me!

At this point, I'm satisfied that the INTENT (!) of the standard is to say
that the value of an expression argument is fixed at the time of argument
association and therefore nothing that happens during procedure invocation
will change it.

Ron Shepard

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
In article <78nn7t$k...@usenet.pa.dec.com>, "Steve Lionel"
<Steve....@digital.com> wrote:

>Well, *IF* one interprets the standard as saying that changing x changes the
>value of the expression, and therefore such changing of x is disallowed,
>then yes, such a substitution would be valid.

Ok, now I think I see your argument. You are saying that whether the
argument is "x" or "(x*1.0)", a compiler could interpret BOTH forms as
expressions. The idea of passing a VARIABLE as an actual argument would
have no meaning to this compiler, since it would interpret everything as
an EXPRESSION. For this compiler, it would be illegal to change the value
of ANY dummy argument, because the actual arguments would all be
expressions. You are saying that such a compiler would be, technically
speaking, standard conforming, because the semantic distinction between a
variable and an expression, in the actual argument list of a subprogram,
is sufficiently ambiguious in the standard to allow such an
interpretation.

[...]


>"Language lawyering" is a tricky business, and sometimes the standard says

>things that seem to defy "common sense". ^^^^

Agreed. In this case, if your argument is valid about this ambiguity,
instead of "says", I would say "allows".

$.02 -Ron Shepard

Jos Bergervoet

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
Richard Maine writes:

> And don't expect much help in figuring out how to write your code
> "aliasing safe". My only advice on how to do so is to stick to the
> standard. Otherwise, I "wash my hands" of the results. I think its a
> bad idea to even try to figure out what non-standard things you can
> "get by with" in this regard. Looks to me like you've missed even
> some trivial ways that such code could have problems (see earlier
> post). I don't even know all of the complicated ones - haven't tried

1) Writing "aliasing safe" may be hard, but possibly not as hard
as _detecting_ aliasing, which is equivalent to the halting problem.
So wouldn't the first option still be useful then?

2) As for sticking to the standard: then it's every caller's
responsibility not to call triple(x,x). The programmer who originally
writes it may be unhappy with the possibility of things going wrong...

3) I may have missed trivial ways my example code can go wrong, but
previous posts did not provide any! The only way (until now) was the
mechanism I gave in my original posting, where a compiler would bluntly
ignore the intent(in) specifier. This should simply be prohibited by
the standard. I am still interested to find out in what trivial ways
triple(x,x) could go wrong!

> So, yes, its "the programmer's responsibility." I think thats just
> a bigger burden than you realize.

I already concluded it was big enough to share it with c.l.f :-)

-- Jos

William Clodius

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
Modifiable aliasing is a potential problem in any language. Many
languages define in detail the behavior of the language's constructs in
the presence of modifiable aliasing. Fortran simply terms all
non-obvious (e.g., I consider local equivalence and pointers to be
obvious forms of aliasing) forms of modifiable aliasing illegal. As a
result there are forms of modifiable aliasing that can be anticipated in
writing procedure bodies in the other languages that cannot be handled
in Fortran. However, in practice, there are relatively few contexts
where there is an obviously desirable result of modifiable aliasing,
having to deal with those cases results in convoluted code, and having
the language require a given behavior in the presence of aliasing has a
performance impact (at least in the case of "safe" optimization
switches) in the majority of cases where such aliasing does not occur.

INTENT(IN) describes how the body of the procedure must treat the
argument in the absence of aliasing at the call site. It assumes that
the argument is not aliased, and, in many circumstances, can allow the
compiler to verify that the argument has not been "directly" modified by
the code. This protection is not perfect, too much code exists whith
arguments whose INTENT is either not specified or has INTENT(INOUT).

In particular note for triple, you can get problems even withougt a
superfluous copy out. You could have a compiler avoid a subsequent copy
in. For example

call triple(x,x)
y = x*x

the compiler could generate code to copy x into two registers, call
triple telling it to use the values in the registers, and then calculate
y arbitrarily choosing one of those registers. This posibility become
even more obvious with

Subroutine example(x,y)
...
call triple(x,y)
z = x*x
...
end
...
call example(x,x) ! this call, but not example itself, is illegal

what value should z have? How should the programmer of example reason
about aliasing he did not explicitly invoke? How should the user (the
compiler) reason about this?


An F90/95 programmer, in invoking a procedure, should be aware that
aliasing with an argument with intent OUT is illegal, aliasing involving
arguments all of intent IN is safe, aliasing with arguments with intent
unspecified requires consultation with the documention to verify that
the arguments are effectively intent in, and aliasing with arguments
with intent INOUT is (almost?) always as bad as aliasing with arguments
of intent OUT. The programmer should also be aware of common block and
module variables, modifiable aliasing of them is also undefined.

Writing aliasing safe code invocation is sometimes tedious, but
relatively straightforward. It requires always creating temporaries, for
the entity that would otherwise be aliased. In the case of triple any of

call triple((x), x)
or
y=x
call triple(y,x)
or
y=x
call triple(x,y)

are standard conforming ways of invoking triple without aliasing. There
are some tricks to this. I have not checked on F90 but in F77

call triple(x, (x))

wher the second argument effectively has intent out, is illegal. An
intent OUT (and intent inout?) dummy argument would have to have a named
argument at the call site.

Walt Brainerd

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
rwe...@ix.netcom.com(Richard Weaver) writes:

> Your assertion that a thing is definable if it "can appear on the left
> of an assignment" is a partial truth.

Here is the definition of "definable" in the standard (Glossary, Appendix A):

===
definable (2.5.4) : A variable is definable if its value may be changed
by the appearance of its name or designator on the left of an assignment
statement.
===

If you are not willing to accept the definitions in the standard, then we
are with "Alice in Wonderland" where words can mean anything you want them
to mean and we can't have a meaningful discussion.

> Hey, its no big deal, just one more interpretation that is needed.

Absolutely not. The standard is as clear about this as it is about anything.

The section I quoted previously says that you can't change the value of a
dummy unless it is associated with an actual argument that is definable.
Definable is defined above and (x) and X+X-X are not definable.

Richard Weaver

unread,
Jan 28, 1999, 3:00:00 AM1/28/99
to
In <shepard-2701...@anchah.chm.anl.gov> she...@tcg.anl.gov
(Ron Shepard) writes:
>...[snip]

>It seems odd that the compiler would be able to substitute some
variable
>for the value of an expression in a subroutine call just because that
>variable happens to have the same value. Would you say that a
compiler
>should be able to make the same substitution for
> ... [deliberate snip in the middle of sentence]

The overall model is that the standard:

-- requires programs to use "only those forms and relationships
described [in the standard]".

-- requires processors [compilers, libraries, machine, ...] to execute
standard-conforming programs "in a manner that fulfills the
interpretations [of the standard]"

Thus while programs are constrained to conform to the standard,
processors can do whatever they want PROVIDED that the result of the
program is that specified by the standard. Compilers can discard dead
code, combine common expressions, move constant code out of loops,
anything!, -- so long as the result of program execution is still as
defined by the standard.

Dick W

There are some other requirements on processors, but the above should
be adequate until you want to read the standard.

Jos R Bergervoet

unread,
Jan 28, 1999, 3:00:00 AM1/28/99
to
Jos Bergervoet wrote:
>
> [...] I am still interested to find out in what trivial ways
> triple(x,x) could go wrong!
>

I think I found a simple and reasonable example:

subroutine triple(a,b)
integer, intent(in) :: a
integer, intent(out) :: b
b = 3*a
end subroutine triple

could be replaced by the compiler with:

subroutine triple(a,b)
integer, intent(in) :: a
integer, intent(out) :: b
b = 2*a ! 2*a by shift-left operation (faster?)
b = b+a ! one extra addition needed
end subroutine triple

The aliased case "call triple(x,x)", leads to x becoming 4*x now.
Although the above "optimization" might not actually be faster, this
possibility should convince everyone of the wisdom of the standard.

-- Jos

Jozef R. Bergervoet Electromagnetism and EMC
Philips Research Laboratories, Eindhoven, The Netherlands
E-mail: berg...@natlab.research.philips.com Phone: +31-40-2742403

Steve Lionel

unread,
Jan 28, 1999, 3:00:00 AM1/28/99
to
Ron Shepard <she...@tcg.anl.gov> wrote in message
news:shepard-2701...@sabb.tcg.anl.gov...

>In article <78nn7t$k...@usenet.pa.dec.com>, "Steve Lionel"
><Steve....@digital.com> wrote:
>
>>Well, *IF* one interprets the standard as saying that changing x changes
the
>>value of the expression, and therefore such changing of x is disallowed,
>>then yes, such a substitution would be valid.
>
>Ok, now I think I see your argument. You are saying that whether the
>argument is "x" or "(x*1.0)", a compiler could interpret BOTH forms as
>expressions.

No, I didn't mean this at all and I CERTAINLY don't believe it.

I really don't want to drag this out, but here's sort of what my point was.

Consider the following program:

X = 3.0
READ (*,*) X
WRITE (*,*) X*1.0
END

What value gets displayed by the WRITE statement? You don't know, do you?
That's because the value of the expression X*1.0 is dependent on the current
value of X when the expression gets evaluated. Therefore, changing the
value of X changes the value of (X*1.0) - with me so far? And would you
also agree that a compiler could change X*1.0 to just X in this program and
get the same result?

In the original case, involving a routine call, the question boils down to
just when it is an expression argument is evaluated. If it is evaluated at
the time of initial argument association, then there is no problem.
However, if a compiler is allowed to defer evaluation until the argument is
actually used, then there could be a problem. I couldn't find wording in
the standard that said one way or another, and I suggested an interpretation
where the value of the expression (X*1.0) does change if you change the
value X, through argument association, which the standard would then
prohibit. I now believe that the standard intends to say that expression
arguments are completely evaluated at the time of argument association,
therefore nothing in the routine can change the value, and therefore I
withdraw my contention that a compiler can legally replace (X) with X in an
argument list.

Jeff Drummond

unread,
Jan 28, 1999, 3:00:00 AM1/28/99
to

In article <36AE05EF...@erols.com>, Dan Nagle <dna...@erols.com> writes:
|> Richard Maine wrote:

[ snip ]

|> > x = 3.
|> > write (*,*) x+1.
|> > x = 7.
|> >
|> > I would not say that the "x=7." affects the value of the x+1. expression
|> > in the write.
|>
|> I think, in the case of write()'s, that the situation may be
|> worse than stated. Suppose, on different runs of the same program,
|> the OS decided to allocate different amounts of buffer space to
|> the program. Then on one run, the write may use the x = 3., and
|> on another run the write may use the x = 7.

I think in this case one would have to view the buffer space as equivalent
(at least in function) to a compiler temporary, even if (to follow the
original point, if I understand it correctly) the compiler never otherwise
created temporaries.

-Jeff j...@sgi.com
--
"PHENOMENAL COSMIC POWER; itty-bitty living space." --Robin Williams in
_Aladdin_, on the pros and cons of being a Genie.

Ron Shepard

unread,
Jan 31, 1999, 3:00:00 AM1/31/99
to
In article <78pt99$n...@usenet.pa.dec.com>, "Steve Lionel"
<Steve....@digital.com> wrote:

[...]


> In the original case, involving a routine call, the question boils down to
> just when it is an expression argument is evaluated. If it is evaluated at
> the time of initial argument association, then there is no problem.

I don't think this could be the case for fortran. However, I remember
through the fog a language once where expressions used as arguments were
really function definitions. They were sort of like statement functions,
where the local variables used in the expressions kept their values within
the lower-level subroutine. Maybe it was pl/1? Anyone know for sure
which language this was?

> However, if a compiler is allowed to defer evaluation until the argument is
> actually used, then there could be a problem.

Yes, I agree. This is why I don't think this kind of defered evaluation
would be allowed in fortran. Surely (I know, "Don't call me Shirly" ;-),
someone in the last 50 years would have recognized such an ambiguity and
"fixed" it in one of the language standard revisions.

>[...] and therefore I


> withdraw my contention that a compiler can legally replace (X) with X in an

> argument list. [...]

Is there still a question about whether a compiler could call "X" an
expression? Certainly this would not result in a "practical" language,
but I'm curious if such a compiler would be standard conforming to a
language lawyer. That is, would it be simply a poor "quality of
implementation" situation, or is there unambiguous wording that prevents
"X" from being interpreted as an expression rather than a variable? Is
this different in F95/F90 than it was in F77?

$.02 -Ron Shepard

James Giles

unread,
Jan 31, 1999, 3:00:00 AM1/31/99
to

Ron Shepard wrote in message ...
...

>I don't think this could be the case for fortran. However, I remember
>through the fog a language once where expressions used as arguments were
>really function definitions. They were sort of like statement functions,
>where the local variables used in the expressions kept their values within
>the lower-level subroutine. Maybe it was pl/1? Anyone know for sure
>which language this was?

It was "call by name" association. The language was one of the ALGOLs
(ALGOL 60 according to one book I have). The basic problem with it is still
with us when C programmers define important functions as macros instead. If
the definition of SQUARE(x) is ((x)*(x)), then the reference SQUARE(*a++)
becomes ((*a++)*(*a++)), which is probably not what the programmer intended.
Macros are often said to behave as if they were procedures with "call by name"
argument association.

As for Fortran, I believe that Walt Brainerd has already posted the relevant
portions of the standard to settle the issue: Fortran evaluates non-definable
arguments (expressions) before argument association and associates the
resulting value.

--
J. Giles

Walt Brainerd

unread,
Jan 31, 1999, 3:00:00 AM1/31/99
to
"James Giles" <james...@worldnet.att.net> wrote:

> As for Fortran, I believe that Walt Brainerd has already posted the relevant
> portions of the standard to settle the issue: Fortran evaluates non-definable
> arguments (expressions) before argument association and associates the
> resulting value.

And remember one thing that Dick Weaver got right on: the compiler may generate
any code that creates the same effect as the above. If it can figure out that
an expression does not need to be evaluated, it doesn't have to generate code
to evaluate it.

James Giles

unread,
Jan 31, 1999, 3:00:00 AM1/31/99
to

Walt Brainerd wrote in message <79298k$9...@llama.swcp.com>...

>"James Giles" <james...@worldnet.att.net> wrote:
>
>> As for Fortran, I believe that Walt Brainerd has already posted the relevant
>> portions of the standard to settle the issue: Fortran evaluates non-definable
>> arguments (expressions) before argument association and associates the
>> resulting value.
>
>And remember one thing that Dick Weaver got right on: the compiler may generate
>any code that creates the same effect as the above. If it can figure out that
>an expression does not need to be evaluated, it doesn't have to generate code
>to evaluate it.

Yes, but the point is that the standard does not allow any form of late
evaluation which might be based on changes that could have been made
to components of the expression. If you do evaluate a non-definable argument
later than the actual call, it must really be "as-if" it had been evaluated before
argument association.

--
J. Giles

Wclodius

unread,
Feb 1, 1999, 3:00:00 AM2/1/99
to
The term macro is most often used for call by textual substitution. Call by
name places some additional semantic constraints on the substitution that makes
it easier to reason about. For example the macro SQUARE(x) if defined as (x*x)
when applied to SQUARE(y+z) yields y+z*y+z which is interpreted as y+(z*y)+z
while a call by name SQUARE(x) procedure defined as (x*x) when applied to
SQUARE(y+z) yields the equivalent of (y+z)*(y+z). I.e. call by name reduces the
amount of parenthesization you need to get what you usually want.

There is however a dialect of Scheme, that defines its macros in terms of call
by name.

Note some functional languages define argument passing mecvhanism in terms of
lazy evaluation, which is closely related to call by name, although those
languages typically avoid or minimize side effects that complicate the
understanding of call by name in imperative languages.

William B. Clodius

James Giles

unread,
Feb 1, 1999, 3:00:00 AM2/1/99
to

Wclodius wrote in message <19990131205112...@ng111.aol.com>...
...

>Note some functional languages define argument passing mecvhanism in terms of
>lazy evaluation, which is closely related to call by name, although those
>languages typically avoid or minimize side effects that complicate the
>understanding of call by name in imperative languages.

Actually, in a truly functional language (like Haskell), there is no difference
between call by name, call by value, or call by reference (for symbols).
In a language with no side effects at all, the distinction no longer matters
(or no longer exists, pragmatically).

--
J. Giles

0 new messages