This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug fortran/68993] MERGE does not evaluate its arguments
- From: "kargl at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sat, 19 Dec 2015 18:01:45 +0000
- Subject: [Bug fortran/68993] MERGE does not evaluate its arguments
- Auto-submitted: auto-generated
- References: <bug-68993-4 at http dot gcc dot gnu dot org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68993
kargl at gcc dot gnu.org changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |kargl at gcc dot gnu.org
--- Comment #1 from kargl at gcc dot gnu.org ---
(In reply to Joost VandeVondele from comment #0)
> I'm not 100% sure what the right answer is, i.e. if MERGE is defined by the
> standard to do something special with respect to evaluating its arguments.
> The origin is code like this:
>
> MERGE(C_NULL_PTR, C_LOC(pc), .NOT.PRESENT(pc)))
>
> is this standard conforming if pc is not present ? In that case MERGE is
> supposed to return C_NULL_PTR, but I see no reason why C_LOC(pc) would not
> be evaluated first.
The above is using C binding features. Your example below has
nothing to do with C binding. However, ...
>
> Gfortran and ifort behave differently in this respect.In the below code
> ifort calls foo 4x while gfortran calls it 2x.
both results are plausible as the code is invalid.
7.1.8.1 Evaluation of operands
It is not necessary for a processor to evaluate all of the operands
of an expression, or to evaluate entirely each operand, if the value
of the expression can be determined otherwise.
If a statement contains a function reference in a part of an expression
that need not be evaluated, all entities that would have become defined
in the execution of that reference become undefined at the completion
of evaluation of the expression containing the function reference.
C.4.2 Evaluation of function references
If more than one function reference appears in a statement,
they may be executed in any order (subject to a function result
being evaluated after the evaluation of its arguments) and their
values shall not depend on the order of execution. This lack of
dependence on order of evaluation permits parallel execution of
the function references (7.1.8.1).
C.9.5 Argument association and evaluation (12.4.1.2)
The provisions for expression evaluation give the processor
considerable flexibility for obtaining expression values in the
most efficient way possible. This includes not evaluating or only
partially evaluating an operand, for example, if the value of the
expression can be determined otherwise (7.1.8.1). This flexibility
applies to function argument evaluation, including the order of
argument evaluation, delaying argument evaluation, and omitting
argument evaluation. A processor may delay the evaluation of an
argument in a procedure reference until the execution of the procedure
refers to the value of that argument, provided delaying the evaluation
of the argument does not otherwise affect the results of the program.
The processor may, with similar restrictions, entirely omit the
evaluation of an argument not referenced in the execution of the
procedure. This gives processors latitude for optimization (for
example, for parallel processing).
> While gfortran's way of doing things seem natural, I suspect it is not
> standard conforming.
gfortran can do whatever it wants here as the code is invalid.
> > cat test.f90
> MODULE test
> INTEGER, SAVE :: i=0
> CONTAINS
> INTEGER FUNCTION foo()
> i=i+1
> foo=i
> END FUNCTION
> END MODULE test
>
> USE test
> WRITE(6,*) MERGE(foo(),foo(),.FALSE.)
Does the evaluation of foo() in the above give
merge(1, 2, .false.) or merge(2, 1,.false.)? Or,
given that the 3rd argument is .false., gfortran
replaced merge() with foo(). So, your code
transforms to
write(6,*) foo()
write(6,*) foo()
> WRITE(6,*) MERGE(foo(),foo(),.FALSE.)
> WRITE(6,*) i
> END
I believe that this PR should be closed with INVALID.