Order of argument evaluation in C++, etc.

hbaker@netcom.com (Henry G. Baker)
Sat, 8 Jul 1995 17:20:43 GMT

          From comp.compilers

Related articles
Order of argument evaluation in C++, etc. hbaker@netcom.com (1995-07-08)
Re: Order of argument evaluation in C++, etc. wclodius@lanl.gov (WIlliam B. Clodius) (1995-07-10)
Re: Order of argument evaluation in C++, etc. chase@centerline.com (1995-07-12)
Re: Order of argument evaluation in C++, etc. hbaker@netcom.com (1995-07-18)
Re: Order of argument evaluation in C++, etc. stefan.monnier@epfl.ch (Stefan Monnier) (1995-07-20)
Re: Order of argument evaluation in C++, etc. dmk@dmk.com (1995-07-21)
Re: Order of argument evaluation in C++, etc. jhallen@world.std.com (1995-07-21)
[50 later articles]
| List of all articles for this month |

Newsgroups: comp.compilers
From: hbaker@netcom.com (Henry G. Baker)
Followup-To: poster
Keywords: question, C++
Organization: nil
Date: Sat, 8 Jul 1995 17:20:43 GMT

The following question is posed in C++, but is essentially independent
of the language and is therefore a generic compiler question rather than
a C++-specific question.

Consider the following expression in C++: plus(sqr(f(a)),sqr(g(b))).

The names 'plus' and 'sqr' could conceivably mean addition and
squaring, depending upon the datatypes of the functions and variables.

C++ requires that the arguments to a function be completely evaluated
(and all side-effects posted) prior to entering the function, but the
implementation is free to evaluate the arguments in any order, and
presumably side-effects can be used to determine this ordering for
a particular implementation.

Question: although it may not be required by the language standard,
can one _practically_ depend upon a compiler finishing one argument
completely before starting to evaluate another? For example, if the
compiler evaluates f(a), can one be relatively certain that sqr(f(a))
will then be evaluated before g(b) commences? In other words, would
there ever be a reason for evaluating this expression in anything
other than in some depth-first ordering?

The question is actually a whole range of questions, depending upon
the datatypes involved.

1. The datatypes are all floating point 'double'. If f(a) and g(b)
are inline and simple, I could conceive of reordering the expression
in a more-or-less breadth-first ordering in order to optimize some
parallel or pipelined FPU.

2. The datatypes are all user-defined and very expensive (think of
100x100 matrices of doubles). Unless we are running on a machine with
multiple processors, and the compiler is smart enough to figure out
that sqr(), f(), and g() are all independent, I would be amazed if a
compiler did anything other than depth-first order for this

3. An additional wrinkle: the result type of sqr() is different from
the argument types of plus(), so the compiler must insert a conversion.

3a. Think of sqr: int -> int, and plus: double x double -> double.
In this case, a compiler might conceivably hold off on the conversion
from int to double from the first argument until the second argument
produces its (int) result. Then it might convert both ints to doubles
and finish the plus function.

3b. Same question, but f(), g(), and sqr() operate on 100x100
matrices of ints, and plus() operates on 100x100 matrices of doubles.
The conversion is now a user-defined conversion. Would the compiler
ever _not_ completely finish the evaluation of either conv(sqr(f(a)))
or conv(sqr(g(b))) before even starting to embark on evaluating the
other? If not, why not?

I'm not looking for a 'language lawyer' answer to this question, but
only for thoughts from compiler people on what rational reasons a
compiler could have for doing other than some depth-first evaluation
of an expression involving user-defined datatypes and user-defined

The reason for the question has to do with (among other things) the
ordering of allocation/deallocation of the generated temporaries in
the user-defined datatype situation. Would this ordering ever be
other than LIFO? If not, why not, and under what conditions?

[I'm already aware of the fact that non-GNU C++ compilers may generate
an additional non-LIFO temporary to hold the result of a function
before it is finished, and must then do an additional constructor copy
to the 'real' temporary. My question is not about this particular C++
botch, but about the 'real' temporaries that are generated by the
caller of the complete expression.]

Thanks in advance for any help.


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.