On 2/16/20 3:49 PM, Bruno Haible wrote:
I'm after warnings that point to undefined behaviour, and since passing a
'char *' in place of an 'unsigned char *', 'FILE *', or similar already
generates a compiler warning, using 'restrict' here does not offer an
advantage.
It can still offer an advantage, since GCC doesn't necessarily generate a
compiler warning without the 'restrict'. For example, in the following code GCC
complains about the call to f but not the call to g:
void f (char *restrict, int *restrict);
void g (char *, int *);
int
main (void)
{
int a[] = {0, 0, 0};
void *p = a;
f (p, p);
g (p, p);
}
More generally, the role of 'restrict' for optimizations can't be easily
separated from its role for warnings. Using 'restrict' to save machine
instructions also means that it's better for GCC to generate warnings when the
behavior would otherwise be undefined; conversely, typically when GCC generates
warnings it's free to optimize more. Because of this close connection, when in
doubt it's better to use 'restrict' in a way that benefits optimization as well
as warning.
int snprintf (char *str, size_t size, const char *format, ...);
... since 'restrict' on the first parameter is going to signal a warning
for overlaps with the 3rd, 4th, 5th, ... parameter, we don't need 'restrict'
on the 3rd parameter.
If we omit 'restrict' from the 3rd parameter, GCC won't warn when the 3rd
parameter overlaps with the 4th. That's a minus.
I mean any possible implementation, compiled from the code we have in gnulib.
'restrict' is part of the contract between the caller of the function and the
implementation of the function. When the compiler optimizes the implementation,
it has to stick to the contract.
This sounds backwards. Ordinarily (without restrict) there is a contract that
prevents the compiler from optimizing the implementation in certain ways. With
restrict, that part of the contract goes away. From the programmer's point of
view, 'restrict' places additional restrictions on the caller, not on the
callee. And appropriate use of 'restrict' signals to programmers what the callee
can do. This signal to humans is useful regardless of whether tools like GCC use
the signal to generate warnings or optimizations.
The "same array" rule comes from what I understood from various explanations
of 'restrict' on the web [1], and from what I see in the glibc headers for
functions that have multiple output parameters of the same type:
- splice in <bits/fcntl-linux.h>,
- printf_arginfo_size_function in <printf.h>,
- openpty in <pty.h>,
- re_set_registers in <regex.h>,
- copy_file_range in <unistd.h>.
That stackoverflow explanation is full of confusing answers and none of them are
particularly good. And the glibc headers evidently were not written by people
who cared about proper use of 'restrict' (possibly because they wrote the
headers before 'restrict' existed or was widely supported).
But ecvt, fcvt in <stdlib.h> have 'restrict'. You may want to register a glibc
bug if you think these five functions should have 'restrict' :)
It's not a bug. It's required by POSIX (which uses 'restrict' more carefully) in
its older editions. See:
https://pubs.opengroup.org/onlinepubs/009695399/functions/ecvt.html
The functions in questions have been withdrawn from POSIX; if they had not been,
the 'restrict's would still be there.