Gabriel Kerneis wrote:
> Disclaimer: I am not an expert, did not write CIL (neither gcc ;-), so
> what follows is nothing more than my humble understanding of C99.

Hi Gabriel.

> On Fri, Aug 28, 2009 at 06:00:40PM +0200, Enea Zaffanella wrote:
>> I was considering the second example sent by Roberto.
>> Here we need to evaluate the following:
>>
>>    a = ((*p[0]->next) += 1);
>>
>> in a state where the subexpression
>>    *p[0]->next
>> evaluates to
>>    p[0].
>>
>> So the statement above modifies objects 'a' and 'p[0]',
>> which are distinct.
>> Moreover, the *old* value of object 'p[0]' is read (only once)
>> and it is only used to compute the *new* value that has to be stored 
>> into object 'p[0]'.
>>
>> So I cannot see the undefined behavior mentioned in C99 6.5-2:
>> =====
>> 2 Between the previous and next sequence point an object shall have its 
>> stored value modified at most once by the evaluation of an expression. 
>> Furthermore, the prior value shall be read only to determine the value 
>> to be stored.
>> =====
>>
>> To my eyes, this is exactly the same as
>>
>>    p[0] = p[0] + 1;
>>
>> Am I missing something?
> 
> I'm not an expert, but the spec says an object is a "region of data
> storage in the execution environment, the contents of which can
> represent values" (3.14), so basically this is a segment of memory (and
> has few to do with symbolic variables from the original program).
> 
> In this example, I think the object accessed via p[0] is NOT "read only
> to determine the value to be stored". It is also read to determine the
> value of *p[0]->next, to evaluate it to p[0], that is to determine where
> to store it. (This doesn't sound very convincing.)

Well, unfortunately, that piece of the standard is not crystal clear.
I am not saying that I have properly understood its real meaning, I am 
just willing to reason with you to try and capture its real meaning.

So your point is: if we are modifying an object, then its prior value 
should be used only to compute the new value of the same object; any 
other use of the prior value leads to undefined behavior.

Let us assume that your reading is what was really meant in the 
standard. My goal is to provide some evidence that you were actually 
right when saying "(This doesn't sound very convincing.)"

Consider the following example:

int a[2] = { 1, 2 };
int i = 1;
int j;
a[i++] = 3;  // Undefined behavior?

In the third line, we modify two objects:
  - the integer at address &i (let us call it OBJ_1), whose prior value 
is 1, is incremented;
  - the integer (array element) at address &a[1] (let us call it OBJ_2), 
whose prior value 2 is not read, is assigned new value 3.

The two objects OBJ_1 and OBJ_2 are distinct and do not overlap.

The prior value of OBJ_1 has two uses:
  1) compute the new value for OBJ_1;
  2) compute the address of OBJ_2.

Hence, by adopting your reading of the standard, the third line above 
should be flagged as undefined behavior.

Do you think this is indeed a case of undefined behavior?
If you think the answer is positive, then you can stop reading here.

In my humble opinion the one above is not undefined behavior ... hence 
there should be another reading for what is (badly!) said in the standard.

> The fact that ++x is syntactic sugar for x += 1, and that += does
> evaluate it's left operand only once (so, this is NOT equivalent to 
> x = x + 1) must also be important in that case (but I'm not sure what it
> means).

My idea is that we will obtain undefined behavior if we have an 
expression that:
  a) reads the prior value of the modified object; and
  b) it is not used to compute the new value of the object.

That is, there is no undefined behavior if *all* the expressions reading 
the prior value of the object are used to compute the new value of the 
object; but some of these can still be read for other uses.

According to this interpretation of the standard, examples of undefined 
behavior are the following:

a[i] = i = 0;
a[i] = i++;

Here, in both cases, the first occurrence of expression i tries to read 
the prior value of i, but it is not used to compute the new value of i.

The rationale underlying my reading is that if all the expressions 
reading the prior value of the object are used to compute the new value, 
then they will be evaluated *before* assigning the new value to the 
object, hence they will all get the correct prior value.
On the other hand, if there exists even a single expression reading the 
value of the object which is NOT used to compute its new value, then 
there will be no temporal dependency between the evaluation of this 
expression and the object update: the evaluation of the expression could 
take place before the side effect, after the side effect, or even during 
the execution of the side effect, leading to the undefined behavior.

Does this sound as a reasonable reading of the standard?

Going back to the original example:

    a = ((*p[0]->next) += 1);

Here _all_ the (sub-)expressions reading the prior value of the int* 
object found at address &p[0] are used (among other things) to compute 
the new value for the object. Hence, according to the interpretation 
above, there is no undefined behavior.

Cheers,
Enea.


> On the other hand, I'm not sure CIL respects the "optimization rules for
> factoring out assignments" stated in the Rationale (6.5.16).  I'm a bit
> lost here, to be perfectly honnest. And, further, the Rationale is not
> normative anyway...
> E.g., the above expression can be rewritten:
> a = ( t = (*p[0]->next), (*p[0]->next) =  (*p[0]->next) + 1, t + 1 );
> following the first rule, or
> a = ( t = (*p[0]->next) + 1, (*p[0]->next) =  (*p[0]->next) + 1, t );
> following the second rule (unless the "provided that neither i nor y
> have side effects themselves" provision is not met, but I don't see why
> they would have side effects). This is very deterministic, coherent with
> gcc, but not with CIL.
> 
> Anyone else?


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
CIL-users mailing list
CIL-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cil-users

Reply via email to