bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: restrict


From: Paul Eggert
Subject: Re: restrict
Date: Mon, 17 Feb 2020 10:03:11 -0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.4.1

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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]