4

As far as I understand the formal definition of "restrict" in section 6.7.3.1 of the C standard, in the function below, pointer y is based on a restrict pointer x; hence, the compiler will assume that accesses *x and *y might alias:

void assign1(int *pA, long N) {
  int *restrict x = pA;
  { 
    int *y = x + N;
    *x = *y;
  }
}

However, what if y itself is declared restrict: can the compiler assume that *x and *y will never alias?

void assign2(int *pA, long N) {
  int *restrict x = pA;
  { 
    int *restrict y = x + N;
    *x = *y;
  }     
}
Alex Zhi
  • 183
  • 5
  • 2
    You might prefer the [HTML version of the C11 Standard](http://port70.net/~nsz/c/c11/n1570.html) or, specifically [C11p6.7.3.1](http://port70.net/~nsz/c/c11/n1570.html#6.7.3.1). – pmg Jan 13 '20 at 15:11
  • @pmg Thanks, I updated the question with the new link. – Alex Zhi Jan 13 '20 at 15:58

1 Answers1

1

Quoting Jeroen Dobbelaere, an LLVM developer working on a "restrict" implementation:

This is defined in 6.7.3.1 paragraph 4:

... Every other lvalue used to access the value of X shall also have its address based on P ...

For assign1:

  • x is a restrict pointer and is assumed to point to its own set of objects
  • y is a normal pointer, based on x
  • all access to the set of objects pointed by x are done through a pointer based on x

for assign2:

  • x is a restrict pointer and is assumed to point to its own set of objects
  • y is also a restrict pointer, based on x, but it is assumed to point to its own set of objects for the scope of y
  • because of that, *x and *y must never overlap, as all accesses to the objects of y must be done based on a pointer derived from y

As such, a N=0 will trigger undefined behavior in assign2

Doing the assignment to *x outside the inner block, makes the code valid again:

void assign3(int *pA, long N) {
  int *restrict x = pA;
  int tmp;
  {
    int *restrict y = x + N;
    tmp = *y;
  }
  *x = tmp; // may alias with *y
}
Alex Zhi
  • 183
  • 5