Volatile MEMs in statement expressions and functions inlined as trees

Linus Torvalds torvalds@transmeta.com
Fri Dec 14 15:28:00 GMT 2001


On 14 Dec 2001, Alexandre Oliva wrote:
>
> I agree this model would be nice, but I begin to find problems with
> it, at least in C++.  It would require lvalues to carry optional
> associated rvalues, such that, whenever you needed the rvalue of that
> lvalue, you would use the associated value if there was one, and load
> it from the lvalue otherwise, and such that sequence points invalidate
> such rvalues, should they be modified by means of other (or even the
> same) lvalue.

No, not really.

The thing is, you can determine which one to use at _parse_ time, because
they rvalue vs lvalue thing is a very static issue. You don't have to
carry any of the information around at any time.

So for example, in

	(p = q) = r;

everybody agrees (although for different reasons) that we'll use the
lvalue of "p = q". There is no "carry around" phase.

And in

	p = (q = r);

we use the rvalue of "q = r".

But, you don't actually have to even think of it this way. The above is
just my mental picture - nothing more. From an implementation standpoint,
it is easier to not see it as "two different values", but see it as simply
an "lvalue->rvalue conversion" issue.

If the conversion isn't needed, then the point is moot. We're using the
lvalue. No ifs, buts or maybes. And if the conversion is needed, then I
claim that my mental model simply translates to a conversion process that
is:

 - is lvalue an object? rvalue = dereference it.
 - is lvalue an assignment expression? rvalue = right side of assignment

Note how the standard doesn't actually say _how_ the "lvalue->rvalue"
conversion is done. There is no "pointer dereference" mentioned anywhere.

The standard only says that all non-function, non-array types can be
converted to rvalues, and that the type has to be complete and initialized
etc. It then says "The value contained in the object indicated by the
lvalue is the rvalue result".

But the "lvalue" in this case is an _assignment_. So the "value containted
in the object" is really a question of "the value contained in the
assignment".

And, the way I read the "the result of the assignment is the value
stored", THAT is the "value contained in the assignment".

See? This is why I wanted to separate out the notions of "type", "value"
and "lvalueness". They are separate issues, and the standard says separate
things about assignments for all three issues.

When the standard says that the result of an assignment expression is an
lvalue, that does NOT say what the "value contained" in the assignment is.

And when the standard says that the result is the type of the left
operand, that's another completely orthogonal issue.

And when the standard says that the result is the "value stored", then
that says to me that the "value contained within the assignment" is the
"value stored".

So let me recap: don't think of the "separate lvalue and rvalue" as an
_implementation_ model - it isn't. It's just a mental model to help
explain the _conceptual_ separation of lvalue and rvalue. I would not
suggest actually implementing the logic that way - I think you can
implement the logic much more easily by just selecting the right _part_ of
the assignment when you do the lvalue->rvalue conversion on the assignment
expression.

The two are logically the same thing, just different ways of looking at
the issue.

				Linus



More information about the Gcc-patches mailing list