> Taken further, this exact method is what makes the restrict keyword usable in practice. One of the main problems of the restrict keyword is that you shouldn't be aliasing pointers. [..] one of the biggest problems of aliasing: passing in two null pointers
You shouldn't be dereferencing NULL pointers. Aliasing them is perfectly fine.
The non-aliasing requirements of restrict kick in only when you are actually accessing (and modifying!) the object referenced by an lvalue based on an expression of the restrict qualified pointer. So NULL pointers don't matter because first, they do not point to an object, and second, if you dereference them, you're already in UB land anyway. Correct code will not dereference NULL pointers, therefore the restrict qualification means absolutely nothing on code that opts to not try access anything through NULL pointers.
EDIT:
N1256 6.7.3.1p4 under Formal definition of restrict (emphasis mine):
> 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.
You shouldn't be dereferencing NULL pointers. Aliasing them is perfectly fine.
The non-aliasing requirements of restrict kick in only when you are actually accessing (and modifying!) the object referenced by an lvalue based on an expression of the restrict qualified pointer. So NULL pointers don't matter because first, they do not point to an object, and second, if you dereference them, you're already in UB land anyway. Correct code will not dereference NULL pointers, therefore the restrict qualification means absolutely nothing on code that opts to not try access anything through NULL pointers.
EDIT:
N1256 6.7.3.1p4 under Formal definition of restrict (emphasis mine):
> 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.