Volatile MEMs in statement expressions and functions inlined astrees

Paul Schlie schlie@mediaone.net
Mon Jan 7 13:08:00 GMT 2002


on 1/7/02 3:50 PM, Paul Schlie wrote:

As a minor correction, to what about volatile x; or *p;, it would seem to be
the case that if a volatile *p were to be evaluated in an <lvalue> context,
it should likely require a dereference access of *p, sorry for my likely too
quick earlier response.

(alternatively, if it is determined that a void-evaluation is only truly
required to evaluate assignment expressions, i.e. expressions which
explicitly modify state-values, that would seem reasonable to me as well.)

> (please see annotations below)
> 
> on 1/7/02 1:55 PM, Jason Merrill wrote:
>>>>>>> "Paul" == Paul Schlie <schlie@mediaone.net> writes:
>> 
>>> It seems to be agreed that the value of assignment expression as an:
>> 
>>> - lvalue, is equivalent to the lvalue of that assignment expression.
>>> - rvalue, is equivalent to the rvalue of that assignment expression.
>> 
>>> It further seems agreed that the terms "lvalue", and "rvalue" are semantic
>>> terms, where: (please excuse my terminology, but intent should be clear)
>> 
>>> - lvalue, refers to the "state-location" of a referenced "symbol" or
>>>   "expression-value" (only symbols and expressions explicitly yielding
>>>   reference-values are valid lvalues-expressions, no dereferencing of the
>>>   resulting lvalue is implied or required).
>> 
>> Yes.
>> 
>>> - rvalue, refers to the "state-value" of the referenced symbol or
>>>   "expression-value" (all valid expressions have valid state-values, and
>>>   do imply (and require if volatile) dereferencing
>> 
>> Yes.
>> 
>>> The controversy appears to be related to if and/or when it is necessary, or
>>> even appropriate to require the re-evaluation an assignment expression's
>>> lvalue to derive it's rvalue when required for subsequent evaluation,
>> 
>> Yes.
>> 
>>> and if the semantics of an statement evaluation (which semantically
>>> yields no value in C, unlike other languages such as scheme), implies the
>>> the semantics of an <lvalue> or <rvalue> be applied to the enclosed root
>>> expression.
>> 
>> Well, sort of.
>> 
>>> It is unreasonable to believe that the expression:
>> 
>>> X = Y; :: X = Y, X;
>> 
>>> Where if X were declared as volatile, would require X be sequentially
>>> write-accessed, and then read-accessed, which seems clearly wrong; as it
>>> would then be impossible to specify write-access to the exclusion of a
>>> subsequent read-access of a volatile variable.
>> 
>> Agreed.  There is no second read in this statement.
>> 
>>> Therefore one of the following must be true to for volatile X:
>> 
>>> X = Y; :: X = Y;
>> 
>>> - the root statement-expression is treated as an <lvalue> evaluation, which
>>>   does not imply or require the dereferencing of the resulting lvalue,
>>>   therefore no terminal dereference of X.
>> 
>> More or less.  More precisely, it's treated as a void evaluation, which
>> doesn't require anything.
>> 
>>> - the root statement-expression is treated as an <rvalue> evaluation, where
>>>   the resulting <rvalue> is thrown away, and assignment sub-expression's
>>>   return "the value written", in the form of a temporary (or optionally by
>>>   re-evaluating the lvalue target if non-volatile).
>> 
>> No.
>> 
>>> Therefore under no circumstances does:
>> 
>>> (X = Y) :: (X = Y, X)
>> 
>>> Except if X is non-volatile, and therefore can be re-de-referenced as an
>>> optimization to an otherwise required intermediate temporary, therefore not
>>> semantically equivalent.
>> 
>> No, that equivalence holds in all cases in C++.  But this only matters if
>> the resulting value is used in a further expression.
>> 
>>> In all circumstances:
>> 
>>> (X = Y) :: (temp = Y, X = temp)
>> 
>>> Regardless if X or Y are volatile, I have found no reference in the C
>>> standard to support alternative fully constant conclusions.
>> 
>> Yes, but this is vacuous.
>> It is further equivalent to (temp = Y, X = temp, X).
> 
> Agreed when evaluated in the context of an <lvalue>.
> 
> But not as an <rvalue>, as it would require X to be subsequently re-evaluated,
> which was agreed as being inappropriate; therefore more specifically, an
> assignment expression has different semantics depending on if it is evaluated
> as an lvalue, or rvalue (just as most expressions do).
> 
> <lvalue> (X = Y) :: (temp = Y, X = temp, X)
> <rvalue> (X = Y) :: (temp = Y, X = temp, temp)
> 
> Which should account for all concerns, and be fully consistent.
> 
>> I'm only talking about C++ here.  In C, the result of an assignment is an
>> rvalue, so
>> 
>> (X = Y) :: (temp = Y, X = temp, temp)
> 
> Agreed as above, when evaluated in the context of an <rvalue>.
> 
>> The only question as to whether or not evaluation of an lvalue as a
>> statement should cause a read from a volatile variable was in reference to
>> simple statements like
>> 
>>  x;  or
>>  *p;
> 
> Ultimately would suspect to be uniformly consistent it would need to be
> determined if an expression is evaluated as being in the context of an lvalue
> or rvalue; where:
> 
> <lvalue> implies no dereference of X, or *p, therefore no volatile access.
> <rvalue> implies a dereference of X, and *p, therefore a volatile access.
> 
> Personally I prefer <lvalue>, but also somewhat indifferent; assuming it
> is accepted that assignment statements have different lvalue and rvalue
> semantics, although <rvalue> semantics would largely preserve present volatile
> behavior.
> 
>> 
>> for which there is a GCC extension to perform the read even though it is
>> not required by the language.  There has been some discussion about whether
>> or not this is appropriate; I have no strong feeling on the subject.  I
>> would be happy to accept a patch to change this behaviour, so long as it
>> also adds a warning.
>> 
>> Jason



More information about the Gcc-patches mailing list