Is the C restrict qualifier transitive through pointers?
Asked Answered
G

1

6

Is the C restrict keyword/qualifier transitive through multiple levels of pointer indirection?

For instance, given the following snippet:

struct Bar {
    int b;
};

struct Foo
{
    struct Bar* bar;
};

int examineFoos(struct Foo* restrict foo1, struct Foo* restrict foo2)
{
    foo1->bar->b = 1;
    return foo2->bar->b;
}

int main(void)
{
    struct Bar bar = { 0 };
    struct Foo foo1 = { .bar = &bar };
    struct Foo foo2 = { .bar = &bar };
    int val = examineFoos(&foo1, &foo2);
    return val;
}

Does this invoke undefined behaviour and can val == 0 because it violates the restrict when accessing bar, or is it valid code and we always get val == 1 because the restrict is not applied transitively through the bar pointer?

Grubby answered 22/4 at 19:39 Comment(1)
I doubt it would make sense from the usability perspective if it were "transitive" as you suggest.Hollenbeck
G
6

The restrict qualifications of foo1 and foo2 do not impose any limitations on use of the structures that foo1->bar and foo2->bar point to, as demonstrated below.

The requirements imposed upon a program by restrict are specified in C 2018 6.7.3.1 4. These requirements apply only “If L is used to access the value of the object X that it designates, and X is also modified (by any means),” where L is an lvalue for which &L is based upon a P that has been designated as a restrict-qualified pointer to type T, during execution of an associated block B. Based is specified in 6.7.3.1 3:

In what follows, a pointer expression E is said to be based on object P if (at some sequence point in the execution of B prior to the evaluation of E) modifying P to point to a copy of the array object into which it formerly pointed would change the value of E.

The restrict-qualified pointers are foo1 and foo2. Consider whether either foo1->bar or foo2->bar can be based upon either foo1 or foo2. In other words, if E is foo1->bar or foo2->bar, will its value change if the modification described above is made?

Suppose at various points in the body of examineFoos (the block B), we make a copy of the structures that foo1 and foo2 point to and then change foo1 and foo2 to point to the respective copies. Will the value of foo1->bar be the same after this intervention as it is before? Yes, because the value of foo1->bar is determined by the bytes that represent it, and those bytes have been copied. Similarly, foo2->bar will have the same value.

Therefore, foo1->bar and foo2->bar are not based upon foo1 or foo2, so the specification of restrict does not impose any requirements in regard to using them to access the objects they point to.

Glacier answered 22/4 at 20:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.