The formal definition of the meaning of restrict
is given in section 6.7.3.1 of C2011. Note in particular that elements of the parameter list of a function prototype that is not part of a function definition do not meet the conditions set forth in paragraph 1 of that section:
Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T.
The parameter list of such a prototype does not provide any means to make such a designation. Therefore, nothing in the section gives any direct effect to a restrict
qualifier in that context.
The best interpretation is probably as a notice to users of the function that the parameters are declared with the restrict
qualifier in the function definition, where that qualifier does have effect.
Note also, however, that restrict
is not a blanket promise of absence of aliasing. Instead it is a qualified promise that if the target of the restrict
-qualified pointer is modified in any way then it will be accessed only via that pointer, within the scope of the pointer.
Coming back around to fopen()
, then, the restrict
qualifiers in the function prototype have nothing to say about the definedness of the behavior of any call of the function. That is, this is not inherently undefined:
char s[] = "r";
FILE *f = fopen(s, s);
The execution of the function is another story -- or it would be if the pointer targets were not also const
-qualified. Supposing that the prototype expresses the effective qualifiers for the function's definition, if the two arguments alias each other and if their target were modified by the function, then the function would invoke undefined behavior if it accessed the target via the other pointer. Inasmuch as the const
qualification of the pointer targets means that the function would invoke UB by modifying the target in the first place, the restrict
qualification is moot.
The execution of the function is another story. Although the const
qualification of the parameter targets means that we should assume that fopen()
will not attempt to modify them via those pointers, the targets themselves are not necessarily const
. They could conceivably be modified outside fopen()
, via a non-const
lvalue, and that would still be relevant to restrict
qualification. Suppose that the prototype expresses the effective qualifiers for the function's definition. If the two arguments alias each other, and if their shared target is modified anywhere in the program, then fopen()
would invoke UB when it accessed the target via both pointers.