5

I've read a number of posts on the restrict keyword. But virtually every example I can find seem to refer to input parameters only to a function and, perhaps a single value. I need to clarify my understanding.

I've found a function that looks like it totally violates the rules of the keyword with both an input parameter and a local variable.

This function is called with a void* to a buffer and the pointer is declared as __restrict (this is Microsoft Visual C++). Yet later in the function, a local variable pointer of type UCHAR* is declared and made to point to that same restricted input parameter buffer.

Here is a seriously chopped down version of the function I'm talking about:

void Foo(int nVersion, int nX, int nY, int nWidth, void * __restrict pBuffer) const
{
    // ... blah blah blah
    UCHAR * __restrict pBufferPtr = ((UCHAR *) pBuffer) + 10;  // Isn't this aliasing?
    const void * __restrict pData =  (blah blah blah);     //... Get from some function call;
    memcpy(pBufferPtr, pData, nWidth);
}

Does the above example violate the rules of restrict?

CoffeeTableEspresso
  • 2,614
  • 1
  • 12
  • 30
user2057722
  • 51
  • 1
  • 3
  • Edited title and tags, since this is not applicable to C++ in general, just one vendor's extension. – aschepler Oct 15 '13 at 22:27
  • Why you tag this as MSVC? Microsoft states on MSDN from official side that they dont even support the restrict keyword (either in c nor c++) – dhein Oct 16 '13 at 17:38

2 Answers2

4

The restrict keyword only means that the pointers should point to unique portions of memory. In the above code, pBuffer points to something, let's call it A, pBufferPtr points to A+10, PData points to something completely different, B, so there's no violations.

AndyG
  • 39,700
  • 8
  • 109
  • 143
  • So the only thing that is guaranteed not to aliased is the actual pointer value itself and not the thing it points to? Suppose I initialized 'pBufferPtr' to 'pBuffer + nOffset' and 'nOffset' was zero. Suppose I then dereferenced both? That is *pBuffer = 100; UCHAR val = *pBufferPtr; Wouldn't this fail a load-hit store? – user2057722 Oct 15 '13 at 22:21
  • 1
    @user2057722 That would produce undefined behavior. Restrict is simply a hint to the compiler to allow it to perform some optimizations by assuming the pointers point to unique locations. It is up to the programmer to ensure that is indeed the case. – Dave Rager Oct 15 '13 at 22:25
  • So the function is (or at least could be) aliasing a pointer it declared as restrict, right? – user2057722 Oct 15 '13 at 22:26
  • @user2057722 Given that `pBuffer` is not used within this function other than to derive `pBufferPtr` from it and `pBufferPtr` is only around for the duration of this function, I would say it does not. If however this function also performed an operation on `pBuffer` that happened to extend beyond `pBuffer + 10` then I would say that it does and you run into undefined behavior. – Dave Rager Oct 15 '13 at 23:04
1

C++ has no such keyword as restrict. Moreover in your example there are two different words: __restrict and RESTRICT. I think that the first word is implementation defined and the second word denotes a macro. It is C that has the keyword restrict.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    OP specifically means Microsoft Visual-C++, which does reserve __restrict. I'm assuming that RESTRICT is defined as __restrict in my answer. – AndyG Oct 15 '13 at 22:20
  • Yes, that is correct. My apologies. In my editing to make the example simple, I meant to replace all instances of RESTRICT with __restrict as that's what RESTRICT evaluates to. I've corrected it now – user2057722 Oct 15 '13 at 22:29