This is the mail archive of the
mailing list for the GCC project.
Re: Volatile MEMs in statement expressions and functions inlined astrees
- From: Linus Torvalds <torvalds at transmeta dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: Alexandre Oliva <aoliva at redhat dot com>, <gdr at codesourcery dot com>, <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 13 Dec 2001 12:25:45 -0800 (PST)
- Subject: Re: Volatile MEMs in statement expressions and functions inlined astrees
On Thu, 13 Dec 2001, Linus Torvalds wrote:
> I'm not ignoring Jasons arguments. I'm refuting them with logical means,
> and claiming that the arguments are _bogus_.
Let my try a different approach.
Instead of trying to argue _against_ Jason's arguments, let me try to
argue _for_ the end result that I obviously think is the only logically
tenable one, but using Jasons vocabulary for the C++ case, ok?
- "p = 0" is an expression, with a value.
Proof: C and C++ standards.
- "p = 0" is _also_ an lvalue in C++.
Proof: C++ standard. 'nuff said.
Existing gcc practice: "(p = 0) = 1" does in fact compile, and
gives the expected results.
- A lvalue as part of an expression (ie _not_ as the left side of an
argument) is always converted to a rvalue, whether that rvalue is
actually used or not.
Proof: Neither C nor C++ really even _have_ a notion of whether
a value is "used" or not. Expressions simply have values and
statements do not. End of story.
See also existing gcc practice, see the example of code generated
for just a plain "p" when "p" is volatile. This is not meant as a
"proof", but it _is_ clearly an indication that other parts of gcc
(and most programmers) certainly think that the lvalue->rvalue
conversion always happens, whether the rvalue is used or not.
- Nobody expects the statement "p = 0;" to _read_ from "p".
Proof: wild hand-waving, "ask anybody".
Existing gcc practice: most definitely.
Do we agree on these four points?
I will consider the four points above to be a-priori _facts_, so
disagreement on the points above would certainly be a crucial point of
contention. Please speak up.
But I also think that they are "clearly correct", and they are certainly
supported by existing gcc practice.
Now, let's look at what those two facts lead to, when combined.
- the statement "p = 0;" contains the _expression_ "p = 0", which is not
assigned to. Ergo, we have a lvalue expression that has a rvalue.
- lvalues are _always_ converted to rvalues:
Clearly, in the case of an assignment, that "conversion" cannot be a
simple dereference, since that would violate rule #4 above. But we're
in luck - the C++ standard actually tells us that the value of the
assignment expression (the "rvalue") is the value we assigned. So we
actually do _have_ a valid lvalue->rvalue conversion that is supported
by the standard, and has nothing to do with dereferencing the lvalue.
This is my argument. I will claim that it is (a) consistent with the C/C++
language standards and (b) internally consistent and logical, without
resorting to any ill-defined "only when used" rules..
Now, Jason's argument goes:
- Rule #3 does not exist, and we only do the lvalue->rvalue conversion
Existing gcc practice argues _against_ this interpretation of
Jason. See simple "p".
- lvalue -> rvalue conversion is always a dereference.
Proof: "a variable is a lvalue, and the rvalue of a variable is
the dereferencing of that variable. Thus the rvalue of a
assignment (which is also a lvalue) is gotten through
dereferencing the variable that is the assignment"
Counter-proof: "Linus is a human, and Linus has blue eyes. Thus
Jason (who is also human) also has blue eyes".
This is Jasons argument. With Jasons argument, a simple "p = 0" does _not_
dereference (because the rvalue is not used), but "q = p = 0" _does_
dereference "p" (because the value _is_ used, and a rvalue->lvalue
conversion is always a dereference).
According to Jason, "q = p = 0" becomes
p = 0;
q = p;
While _I_ think that "q = p = 0" becomes
p = 0;
q = (typeof p) 0;
(the "typeof" comes from the fact that the assigned value is converted to
the type of the assignee by the assignment as per normal C/C++ rules).