Michael Matz <[EMAIL PROTECTED]> writes:

>> This program appears to me to be invalid according to C99 6.7.3.1,
>> which is the only definition of restrict that we have.
>> 
>>     If P is assigned the value of a pointer expression E that is based
>>     on another restricted pointer object P2, associated with block B2,
>>     then either the execution of B2 shall begin before the execution
>>     of B, or the execution of B2 shall end prior to the assignment.
>>     If these requirements are not met, then the behavior is undefined.
>> 
>> In your program, P is q and P2 is p.  Block B and B2 are the same
>> block: the only block in foo.  It is obviously not the case that the
>> block executes before itself.  So I believe the assignment "q = p + 1"
>> is undefined behaviour.
>
> But the testcases in the PR can easily be transformed to fulfill this 
> requirement.  E.g.:
>
> int __attribute__((noinline))
> foo (int *__restrict p, int i)
> {
>   if (1)
>     {
>       int *__restrict q = p + 1;
>       if (1)
>         {
>           int *__restrict r = q - i;
>           int v, w;
>           v = *r;
>           *p = 1;
>           w = *r;
>           return v + w;
>         }
>     }
> }
> extern void abort (void);
> int main()
> {
>   int i = 0;
>   if (foo (&i, 1) != 1)
>     abort ();
>   return 0;
> }
>
> This (and the other testcases similarly changed) still break.

OK, let me quote the whole paragraph:

    During each execution of B, let L be any lvalue that has &L based
    on P.  If L is used to access the value of the object X that it
    designates, and X is also modified (by any means), then the
    following requirements apply: T shall not be const-qualified.
    Every other lvalue used to access the value of X shall also have
    its address based on P.  Every access that modifies X shall be
    considered also to modify P, for the purposes of this subclause.
    If P is assigned the value of a pointer expression E that is based
    on another restricted pointer object P2, associated with block B2,
    then either the execution of B2 shall begin before the execution
    of B, or the execution of B2 shall end prior to the assignment.
    If these requirements are not met, then the behavior is undefined.

The object X is *r.  You are accessing the object as *r, so in this
paragraph P is r.  The paragraph says that every lvalue used to access
the object must be based on P, which is r.  Your program violates
that, because you are accessing it via p, which is not based on r.

Your argument is presumably that the value of r is based on p, which
it is.  But I don't see how that helps.  Can you walk through that
paragraph in terms of your program and show how it meets the
requirements of that paragraph?


>> More generally, as I understand the restrict qualifier, it means that
>> if two pointers both have the restrict qualifier, and you use one of
>> the pointers to modify an object, you may not use the other pointer to
>> access that object.
>
> Can you deduce this from the standard?

The standard is very obscure, but the rationale, while not normative,
is at least more clear:

    A translator can assume that a restrict-qualified pointer declared
    with block scope is, during each execution of the block, the sole
    initial means of access to an object.

So I guess the question is whether the rationale is incorrect in its
paraphrasing of the standard.

Ian

Reply via email to