[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: restrict
From: |
Bruno Haible |
Subject: |
Re: restrict |
Date: |
Mon, 17 Feb 2020 21:55:53 +0100 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-171-generic; KDE/5.18.0; x86_64; ; ) |
Hi Paul,
> > 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);
> }
True. But it's pretty rare that people use 'void *' pointers and cast them
to pointers of different types.
Also, even a small variation of this code does not produce a warning any more:
void f (char *restrict, int *restrict);
void g (char *, int *);
int
main (void)
{
int a[] = {0, 0, 0};
void *p = a;
f (p, a); // no warning!
g (p, a);
}
> 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.
It needs to be weighed against the desire not to produce warnings for valid
uses. For example here:
> > 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.
Actually, GCC doesn't warn here, even with 'restrict', because the 3rd argument
is a const-pointer and the 4th argument, being variadic, is treated like a
const-pointer as well. Test case (enable one of the declarations):
#include <stddef.h>
//extern int smprintf (char *restrict, size_t, char *, ...);
// no warning
//extern int smprintf (char *restrict, size_t, char *restrict, ...);
// warning
//extern int smprintf (char *restrict, size_t, const char *, ...);
// no warning
//extern int smprintf (char *restrict, size_t, const char *restrict, ...);
// no warning
//extern int smprintf (char *restrict, size_t, const char *restrict, char
*restrict); // warning
//extern int smprintf (char *restrict, size_t, const char *restrict, const char
*restrict); // no warning
char buf[10];
int main ()
{
char fmt[] = "%s";
smprintf (buf, sizeof buf, fmt, fmt);
}
> 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.
I agree.
> This signal to humans is useful regardless of whether tools like GCC use
> the signal to generate warnings or optimizations.
I disagree. Given the confusion around what 'restrict' is actually about,
the "signal to humans" is fuzzy. As it stands, GCC >= 8 is the best bet for
a programmer to understand 'restrict'.
> > 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).
... possibly also because ISO C 99 § 6.7.3.1 is impenetrable.
... possibly also because GCC 8 was not around to teach the programmers.
> > 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
I meant the "glibc bug" the other way around: Someone could tell the glibc
people
that it makes sense to _add_ 'restrict' to the declarations of splice,
printf_arginfo_size_function, openpty, re_set_registers, copy_file_range.
Bruno
- Re: restrict, (continued)
- Re: restrict, Jeffrey Walton, 2020/02/10
- Re: restrict, Tim Rühsen, 2020/02/10
- Re: restrict, Paul Eggert, 2020/02/16
- Re: restrict, Bruno Haible, 2020/02/16
- Re: restrict, Bruno Haible, 2020/02/16
- Re: restrict, Paul Eggert, 2020/02/16
- Re: restrict, Bruno Haible, 2020/02/16
- Re: restrict, Tim Rühsen, 2020/02/17
- Re: restrict, Bruno Haible, 2020/02/17
- Re: restrict, Paul Eggert, 2020/02/17
- Re: restrict,
Bruno Haible <=
- Re: restrict, Paul Eggert, 2020/02/17
- Re: restrict - summary, Bruno Haible, 2020/02/17
- Re: restrict - summary, Bruno Haible, 2020/02/22
- Re: restrict - summary, Eric Blake, 2020/02/24
- Re: restrict - summary, Bruno Haible, 2020/02/23
- Re: restrict - summary, Bruno Haible, 2020/02/23