Ben Bacarisse <> writes:
> Tim Rentsch <> writes:
>
>> Ben Bacarisse <> writes:
>>
>>> Tim Rentsch <> writes:
>>>
>>>> Ben Bacarisse <> writes:
>>>>
>>>>> Tim Rentsch <> writes:
>>>>> <snip -- I hoe too dramatic a snip>
>>>>>>> Yes, the consequences of a volatile access are unconstrained, and
>>>>>>> the standard has no business restricting what an implementation
>>>>>>> may do in such circumstances, but the standard *does* have a
>>>>>>> legitimate role in determining that some programs are undefined as
>>>>>>> far it is concerned. One thing that makes the behaviour undefined
>>>>>>> is the situation described in 6.5 p2.
>>>>>>
>>>>>> (Since you have responded briefly I will also, on just one
>>>>>> point. We can get back to the others sometime later if
>>>>>> that's important.)
>>>>>>
>>>>>> Can you identify for me which scalar object is modified
>>>>>> twice as a result of executing 'int i = x + x;', with x
>>>>>> being declared volatile? Remember, a volatile-qualified
>>>>>> access is a side effect, but it is a non-specific one, not
>>>>>> one that modifies the object being accessed. There is no
>>>>>> guarantee that the side effect of accessing a particular
>>>>>> volatile object will modify any given scalar object, or even
>>>>>> any object at all.
>>>>>
>>>>> Agree, but I don't see why that is relevant. The wording has
>>>>> changed, I thought, so that side-effects of any type are the
>>>>> issue. So 6.5 p2 talks only about side-effects on scalar
>>>>> objects, and simply accessing a volatile object constitutes a
>>>>> side effect. What, if anything, changes it not obviously
>>>>> relevant.
>>>>
>>>> First let me be sure I understand you correctly. The wording
>>>> describing sequencing and access rules obviously has changed
>>>> between, well, let's be specific, N1256 and N1570. Do you
>>>> believe the intended meaning of these passages is significantly
>>>> different between these two versions of the Standard?
>>>
>>> I find it hard enough to follow what is written without trying to
>>> deduce what is intended. Others have said that no change in meaning
>>> is intended but who am I to say either way? My remarks were based
>>> solely on what is written in N1570.
>>
>> For giving answers in comp.lang.c, I often (or usually?) find
>> that looking for the intended meaning results in better answers,
>> ie, answers that are more consistent with statements made in
>> Defect Reports and the Rationale document, etc, than reading just
>> what's written in (one revision of) the Standard. It's different
>> in comp.std.c -- there the whole point is to talk about whether
>> or how well the Standard expresses, or could express, what is
>> intended (or sometimes should be intended).
>
> Just a note: I did start all this by saying: "I'm having trouble
> squaring this with the wording of 6.5 p2". In other words it was, from
> the start, a comp.std.c type reply. The problem was always about the
> words, not the intent.
>
>> Here though I asked
>> the question only to better understand your opinion or point of
>> view. Who are you to say? Just the foremost and most reliable
>> authority as to your own conscious thoughts, and without doubt
>> the person most qualified to answer the question I was asking.
>
> I am also the most reliable authority as to whether I believe you prefer
> cod to haddock when getting a fish supper, but I'd still reply "who am I
> to say" if asked which I believe you prefer!
>
> I'm not being evasive. I am pretty certain that the intent was not to
> change the meaning with respect to non-volatile objects, but there has
> been so much revision of the standard in the area of threads and side
> effect sequencing, with the goal of producing a memory model consistent
> with modern hardware, that I don't feel able to even hazard a wild
> guess. I have not read any of those parts, so I don't know if the
> change of wording was intended to produce different semantics in the
> case of volatile objects because, somehow, it now matters.
>
> <snip>
>>>> Maybe I see what you're getting at -- accessing a volatile object
>>>> is supposed to count as a side effect "on that scalar object". But
>>>> I don't see any text in the Standard that supports that conclusion.
>>>> Can you offer any? Or am I still misunderstanding you?
>>>
>>> No, that's exactly it. The new wording -- the switch from talking
>>> about modification to talking about side effects -- now includes
>>> accesses to volatile objects, at least in my naive reading of
>>> 5.1.2.3 p2:
>>>
>>> "Accessing a volatile object, modifying an object, modifying a
>>> file, or calling a function that does any of those operations are
>>> all side effects,12) which are changes in the state of the
>>> execution environment. Evaluation of an expression in general
>>> includes both value computations and initiation of side
>>> effects. Value computation for an lvalue expression includes
>>> determining the identity of the designated object."
>>>
>>> So "accessing a volatile object" and "modifying an object" are both
>>> side effects expressed in exactly the same terms. Neither is
>>> explicitly said to be "on the object" so I don't see how can you say
>>> that one is "on the object" but the other is not. I'd argue that if
>>> the intent is that modification of an object is a side effect on the
>>> object, but accessing a volatile object is not, then that distinction
>>> that needs to be made clear. The default understanding has to be
>>> that they are both side effect on an object.
>>
>> I'm not sure if I'm shocked by this last statement or merely very
>> surprised. On the one hand it is clear from other passages in
>> the Standard that there are some kinds of side effects that are
>> not "on a scalar object"; but, the default understanding has to
>> be, when the Standard does _not_ say, that a side effect must be
>> a side effect on a scalar object (and not just some scalar object
>> but the same one)? Normally I'd expect the default assumption to
>> be just the opposite - that a particular condition is met only
>> when the Standard includes some sort of explicit statement as
>> to the condition in question.
>
> Maybe "default understanding" is the wrong phrase. All I meant was that
> the ordinary meaning of the words makes both of these side effects "on
> an object".
>
>> Beyond that general reaction,
>> however, let's look into some specifics.
>>
>> The operators that directly change scalar objects are postfix ++
>> and --, prefix ++ and --, and assignment.
>>
>> The semantics of postfix ++ (and --) are given in section 6.5.2.4,
>> which says in part:
>>
>> As a side effect, the value of the operand object is
>> incremented (that is, the value 1 of the appropriate
>> type is added to it). [...] The value computation of
>> the result is sequenced before the side effect of
>> updating the stored value of the operand.
>>
>> The semantics of prefix ++ (and --) are given in section 6.5.3.1,
>> which says in part:
>>
>> The expression ++E is equivalent to (E+=1). See the
>> discussions of additive operators and compound assignment
>> for information on constraints, types, side effects, [and
>> some other things].
>>
>> The semantics of assignment are given in section 6.5.16, which
>> says in part:
>>
>> The side effect of updating the stored value of the left
>> operand is sequenced after the value computations of the
>> left and right operands.
>>
>> To me all of these explicitly reference a particular object that
>> the side effect will modify.
>
> Yes, and there's no argument at all about these cases. But 5.1.2.3 p3
> says that accessing a volatile object is a side effect. There's a
> particular object being referenced there as well -- the one being
> accessed.
>
> Clearly the plain English preposition "on" can be used for a
> modification: it's a side effect on an object; but since, in the case of
> a volatile object, the access itself is a side effect, I don't see why
> that is not equally plainly a side effect "on" the object.
>
>> Compare the passages above to the
>> semantics of volatile access, given in 6.7.3 p7, which says in
>> part:
>>
>> An object that has volatile-qualified type may be modified
>> in ways unknown to the implementation or have other unknown
>> side effects. Therefore any expression referring to such an
>> object shall be evaluated strictly according to the rules of
>> the abstract machine, as described in 5.1.2.3.
>>
>> Here there is no statement about what the side effects of reading
>> a volatile object might be.
>
> I don't think it matters. The access alone is a side effect. Yes,
> there may be others unknown, but however little the standard says about
> modifications and other side effects, access to object alone is one
> certain side effect.
>
>> They might modify the object being
>> read, or they might not; they might modify some other scalar
>> object, or they might not;
>
> [Aside: could it? Only if it, too, is volatile I'd have thought.]
>
>> they change some other physically
>> detectable state of the machine running the program, or they might
>> not. (The modifications mentioned in the first sentence may occur
>> at any time, indepedent of any access in program expressions.)
>> Certainly there is no explicit statement that reading a volatile
>> object modifies (or updates, or has a side effect on) an object.
>> That is a clear distinction with every other operation that might
>> be affected by 6.5 p2.
>
> You are talking about modification but 6.5 p2 does not. All that
> matters is whether the side effect of accessing a volatile scalar object
> falls into the description of "a side effect on a scalar object". Even
> if nothing is modified, the access alone is a side effect and I contend
> that the normal English meaning of "on an object" applies here: it's a
> side effect and there is a specific object associated with the side
> effect (the object being accessed) so it is a "side effect on an
> object". (Forgive me for sometimes including and sometimes dropping the
> qualification "scalar".)
>
>> Finally, there is 5.1.2.3 p9:
>>
>> EXAMPLE 1 An implementation might define a one-to-one
>> correspondence between abstract and actual semantics: at
>> every sequence point, the values of the actual objects would
>> agree with those specified by the abstract semantics. The
>> keyword volatile would then be redundant.
>>
>> Under your theory, volatile would not be redundant in such cases,
>> because adding volatile would change the semantics of programs
>> like the sample code that started the discussion, and so the
>> above EXAMPLE would be contradicted.
>
> This is a good argument for the intent (unless, of course, it was simply
> overlooked) but my argument has always been about the words. I
> previously expressed no opinion about the intent of the committee, but
> this is evidence of intent, so I do now have an opinion (a weak one, but
> an opinion none the less) on this question!
>
>> Admittedly, this paragraph
>> is informative rather than normative. But, considered along with
>> the other cited passages, the evidence favors the position that
>> reading a volatile-qualified object, even though it is a side
>> effect, is not in and of itself "a side effect on a scalar object"
>> as the phrase is used in 6.5 p2.
>>
>> Does this convince you? If it doesn't, do you have any other
>> evidence to offer that reading a volatile object constitutes, for
>> the purpose of 6.5 p2, "a side effect on a scalar object"?
>
> We may soon just have to agree to differ because I don't see anything
> you've presented as being evidence against my contention. Yes, I accept
> that there is evidence that my reading is not what was intended, but my
> point has always been about the words. If reading a scalar is a side
> effect, clearly associated with a unique object, then it's a side effect
> on that object.
>
> Let me try another tack. Imagine C! -- a language like C but in which
> access to a volatile object is not special. C! compilers can remove,
> re-order, and duplicate such accesses just as they can any other. In
> order to get some use back from a volatile object, C! has a new unary
> prefix operator, !!x, which reads x. The C! standard says:
>
> "The operand of !! must denote a volatile-qualified object. An
> expression of the form !!x has the type and value of x, but the
> evaluation is also an 'entaglement'."
>
> It also says that there are other types of entanglement: modifying an
> object is an entanglement, doing IO is another.
>
> Given that we don't know the intent of the C! standards committee, would
> you interpret:
>
> "If an entanglement on a scalar object is unsequenced relative to
> either a different entanglement on the same scalar object or a value
> computation using the value of the same scalar object, the behavior is
> undefined."
>
> as applying to
>
> volatile int x;
> int y = !!x + !!x;
>
> or not? Is the string association of "side effect on" with
> "modification of" at the heart of your argument?
Well, this has been kind of a comedy of errors, each of us not
understanding where the other person was coming from.
My worldview of what is being described is simple and easy to
explain. Probably I should have just done this at the beginning,
but 20-20 hindsight and all that.
Some operations have (or cause, or produce) side effects. Example:
an assignment operation has a side effect of modifying its
left-hand-side operand.
(Note: technically I should have said evaluating an operation is
what causes a side effect. As long as the distinction is understood
it isn't important to emphasize it.)
A side effect is what the Standard says it is: a change in the
state of the execution environment.
Considering all changes in the state of an execution environment,
some are changes to the state of an object. A side effect on an
object is a side-effecting operation that has an effect on that
object, ie, the state of the object is what's being changed (perhaps
among other, unrelated, changes).
(Note: I'm leaving out the 'scalar' part of 'scalar object' because
I think we agree that it doesn't change the discussion in any
important way.)
There also can be changes to the state of an execution environment
arising from "outside forces", eg, RAM being hit by a cosmic ray,
or less exotically a buffer being filled in by doing a particular
system call (ie, a system-specific system call not part of any
standard library function or regular C operation). Such changes
are also side effects, but they are (by definition) outside of
what the Standard defines.
To me the above description seems like the most natural reading of
the text of the Standard, and quite consistent with the ordinary
meaning of the words. For example, considering an environment of
city streets and traffic, we could by analogy call a traffic
accident a "side effect" of city traffic, but when a car hits a
pedestrian the most significant consequence will likely be the
effect on the pedestrian rather than the effect (if any) on the car.
Based on the above, those operations that modify an object count as
side effects on that object, but reading a volatile object does not.
(The Standard sometimes uses the word update basically as a synonym
for modify.) This is so because a write access necessarily involves
a modification -- ie, a change -- to the object in question, but a
read access of a volatile object does not (necessarily) change the
object in question. (The volatile object being read may change as
a result of the unknown side effects mentioned in 6.7.3 p7, but that
is outside the discussion of whether reading a volatile object must
be a side effect on that object.) Reading a volatile object is a
change to the state of the execution environment, but not a change
to the state of the volatile object itself; there is some effect
_on the system as a whole_, but no effect _on the particular object_.
An argument might be given that an object might "change" even if its
state remains the same, so reading a volatile object might have an
effect on the object, ie, the effect of leaving it alone. However,
such an argument is undercut by text in section 3.1, defining the
different types of access. Surely if it is important to note that a
object is modified when even the value being stored is the same as
its previous value (as is done in 3.1 p3), then it would also be
important to have a similar note saying an access of a volatile
object counts as a change to the object (or an effect on the object)
even when the access is a read rather than a write. But there is
no such note. Again, reading a volatile object has an effect on
the execution environment, but there is nothing to indicate it
has an effect on the object itself.
So there in a nutshell is both my view of what the words mean and an
argument based on that reading that supports my conclusions (eg, my
earlier statement about the non-undefinedness of 'x + x').
Having said all this I invite your response in whatever way you
think best. Originally I had started by responding to individual
paragraphs, but at some point I decided it would be more helpful to
take this approach instead. There may still be some loose ends but
hopefully the discussion has been moved farther along than it was up
to now. (And I hope you have gotten answers to your questions even
though I didn't specifically address them.)