Re: restrict - summary

2020-02-17 Thread Bruno Haible
Thanks to Paul and all for the enlightening discussion about what 'restrict'
actually means.

What I intend to do it gnulib is:

  * In the function *definitions*, do not use 'restrict' at all.

Rationale:
  - Gnulib code is not time-critical. 'restrict' enables micro-
optimizations, at the price of undefined behaviour for some
callers.
  - Humans have a poor understanding of what 'restrict' means,
and the GCC warnings cover only a subset of the undefined
behaviour situations (namely, GCC can only warn about equal
pointers, but not about overlapping array slices).

  * In the function *declarations* for POSIX functions, I will use
'restrict' exactly as written in POSIX.

Rationale:
  - 'restrict' modifies the contract between the caller and the
implementor of a function. Whatever 'restrict' precisely means,
the contract that programmers will look at is the POSIX standard.

  * In the function *declarations* for non-POSIX functions, I will use
'restrict' when there is a significant benefit, and only on non-const
pointer parameters.

Rationale:
  - I want to see useful warnings from GCC. "Useful" means: with
the normal programming style; passing 'void *' arguments to
functions that expect 'char *', 'FILE *', etc. is not the
normal programming style I want to care about.
  - The semantics of 'restrict' is a bit confusing, and the semantics
of 'restrict' on const pointer parameters is additionally confusing.
  - It is typically sufficient - both for warnings and optimization -
to put 'restrict' on the non-const pointer parameters only.

Bruno




Re: restrict - summary

2020-02-22 Thread Bruno Haible
Here comes the first part: the 'restrict' in the POSIX function declarations.

Note that the POSIX declarations of posix_spawn and posix_spawnp [1] are
incorrect: They lack a 'restrict' for the file_actions argument.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html


2020-02-22  Bruno Haible  

Use 'restrict' in all POSIX function declarations.
* lib/iconv.in.h (iconv): Use 'restrict'.
* lib/inttypes.in.h (strtoimax, strtoumax): Likewise.
* lib/monetary.in.h (strfmon_l): Likewise.
* lib/pthread.in.h (pthread_create, pthread_mutex_init,
pthread_mutexattr_gettype, pthread_mutexattr_getrobust,
pthread_mutex_timedlock, pthread_rwlock_init,
pthread_rwlock_timedrdlock, pthread_rwlock_timedwrlock,
pthread_cond_init, pthread_cond_wait, pthread_cond_timedwait): Likewise.
* lib/search.in.h (tdelete): Likewise.
* lib/signal.in.h (pthread_sigmask, sigprocmask): Likewise.
* lib/stdio.in.h (dprintf, fgets, fopen, fprintf, fputs, fread, freopen,
fscanf, fwrite, getdelim, getline, printf, scanf, snprintf, sprintf,
vdprintf, vfprintf, vfscanf, vprintf, vscanf, vsnprintf, vsprintf):
Likewise.
* lib/stdlib.in.h (mbtowc, realpath, strtod, strtold, strtoll,
strtoull): Likewise.
* lib/string.in.h (strncat): Likewise.
* lib/sys_socket.in.h (accept, getpeername, getsockname, getsockopt,
recvfrom): Likewise.
* lib/sys_stat.in.h (fstatat, lstat, stat): Likewise.
* lib/time.in.h (strftime): Likewise.
* lib/unistd.in.h (readlink, readlinkat): Likewise.
* lib/wchar.in.h (mbrtowc, mbrlen, mbsrtowcs, mbsnrtowcs, wcrtomb,
wcsrtombs, wcsnrtombs, wmemcpy, wcscpy, wcpcpy, wcsncpy, wcpncpy,
wcscat, wcsncat, wcsxfrm, wcsstr, wcstok, wcsftime): Likewise.
* m4/iconv_h.m4 (gl_ICONV_H): Require AC_C_RESTRICT.
* m4/inttypes.m4 (gl_INTTYPES_INCOMPLETE): Likewise.
* m4/monetary_h.m4 (gl_MONETARY_H): Likewise.
* m4/search_h.m4 (gl_SEARCH_H): Likewise.
* m4/signal_h.m4 (gl_SIGNAL_H): Likewise.
* m4/stdio_h.m4 (gl_STDIO_H): Likewise.
* m4/stdlib_h.m4 (gl_STDLIB_H): Likewise.
* m4/sys_socket_h.m4 (gl_HEADER_SYS_SOCKET): Likewise.
* m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Likewise.
* m4/unistd_h.m4 (gl_UNISTD_H): Likewise.
* m4/wchar_h.m4 (gl_WCHAR_H): Likewise.
* m4/string_h.m4 (gl_HEADER_STRING_H_BODY): Make consistent with the
other *_h.m4 files.
* m4/time_h.m4 (gl_HEADER_TIME_H): Likewise.

diff --git a/lib/iconv.in.h b/lib/iconv.in.h
index 125fa37..904e8f6 100644
--- a/lib/iconv.in.h
+++ b/lib/iconv.in.h
@@ -80,19 +80,22 @@ _GL_WARN_ON_USE (iconv_open, "iconv_open is not working 
correctly everywhere - "
 #  endif
 _GL_FUNCDECL_RPL (iconv, size_t,
   (iconv_t cd,
-   @ICONV_CONST@ char **inbuf, size_t *inbytesleft,
-   char **outbuf, size_t *outbytesleft));
+   @ICONV_CONST@ char **restrict inbuf,
+   size_t *restrict inbytesleft,
+   char **restrict outbuf, size_t *restrict outbytesleft));
 _GL_CXXALIAS_RPL (iconv, size_t,
   (iconv_t cd,
-   @ICONV_CONST@ char **inbuf, size_t *inbytesleft,
-   char **outbuf, size_t *outbytesleft));
+   @ICONV_CONST@ char **restrict inbuf,
+   size_t *restrict inbytesleft,
+   char **restrict outbuf, size_t *restrict outbytesleft));
 # else
 /* Need to cast, because on some versions of Solaris, ICONV_CONST does
not have the right value for C++.  */
 _GL_CXXALIAS_SYS_CAST (iconv, size_t,
(iconv_t cd,
-@ICONV_CONST@ char **inbuf, size_t *inbytesleft,
-char **outbuf, size_t *outbytesleft));
+@ICONV_CONST@ char **restrict inbuf,
+size_t *restrict inbytesleft,
+char **restrict outbuf, size_t *restrict 
outbytesleft));
 # endif
 _GL_CXXALIASWARN (iconv);
 # ifndef ICONV_CONST
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
index d6efc7e..9f04a6c 100644
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -1093,15 +1093,19 @@ _GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - "
 #   define strtoimax rpl_strtoimax
 #  endif
 _GL_FUNCDECL_RPL (strtoimax, intmax_t,
-  (const char *, char **, int) _GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (strtoimax, intmax_t, (const char *, char **, int));
+  (const char *restrict, char **restrict, int)
+  _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoimax, intmax_t,
+  (const char *restrict, char **restrict, int));
 # else
 #  if !@HAVE_DECL_STRTOIMAX@
 #   undef strtoimax
 _GL_FUNCDECL_SYS (strtoimax, intmax_t,
-  (const char *,

Re: restrict - summary

2020-02-23 Thread Bruno Haible
Here comes the second part: Use of 'restrict' in non-POSIX function
declarations, excluding libunistring code.


2020-02-23  Bruno Haible  

crypto/gc: Use 'restrict'.
* lib/gc.h (gc_pbkdf2_hmac, gc_pbkdf2_sha1): Use 'restrict'.
* m4/gc.m4 (gl_GC): Require AC_C_RESTRICT.

crypto/hmac-*: Use 'restrict'.
* lib/hmac.h (hmac_md5, hmac_sha1, hmac_sha256, hmac_sha512): Use
'restrict'.
* modules/crypto/hmac-md5 (configure.ac): Require AC_C_RESTRICT.
* modules/crypto/hmac-sha1 (configure.ac): Likewise.
* modules/crypto/hmac-sha256 (configure.ac): Likewise.
* modules/crypto/hmac-sha512 (configure.ac): Likewise.

crypto/sm3: Use 'restrict'.
* lib/sm3.h (sm3_finish_ctx, sm3_read_ctx, sm3_buffer): Use 'restrict'.
* m4/sm3.m4 (gl_SM3): Require AC_C_RESTRICT.

crypto/*-buffer: Use 'restrict'.
* lib/gl_openssl.h (GL_CRYPTO_FN (_finish_ctx), GL_CRYPTO_FN (_buffer),
GL_CRYPTO_FN (_read_ctx)): Use 'restrict'.

crypto/sha512-buffer: Use 'restrict'.
* lib/sha512.h (sha512_finish_ctx, sha384_finish_ctx, sha512_read_ctx,
sha384_read_ctx, sha512_buffer, sha384_buffer): Use 'restrict'.
* modules/crypto/sha512-buffer (configure.ac): Require AC_C_RESTRICT.

crypto/sha256-buffer: Use 'restrict'.
* lib/sha256.h (sha256_finish_ctx, sha224_finish_ctx, sha256_read_ctx,
sha224_read_ctx, sha256_buffer, sha224_buffer): Use 'restrict'.
* modules/crypto/sha256-buffer (configure.ac): Require AC_C_RESTRICT.

crypto/sha1-buffer: Use 'restrict'.
* lib/sha1.h (sha1_finish_ctx, sha1_read_ctx, sha1_buffer): Use
'restrict'.
* modules/crypto/sha1-buffer (configure.ac): Require AC_C_RESTRICT.

crypto/md5-buffer: Use 'restrict'.
* lib/md5.h (__md5_finish_ctx, __md5_read_ctx, __md5_buffer): Use
'restrict'.
* modules/crypto/md5-buffer (configure.ac): Require AC_C_RESTRICT.

crypto/md4: Use 'restrict'.
* lib/md4.h (md4_finish_ctx, md4_read_ctx, md4_buffer): Use 'restrict'.
* modules/crypto/md4 (configure.ac): Require AC_C_RESTRICT.

crypto/md2: Use 'restrict'.
* lib/md2.h (md2_finish_ctx, md2_read_ctx, md2_buffer): Use 'restrict'.
* modules/crypto/md2 (configure.ac): Require AC_C_RESTRICT.

crypto/rijndael: Use 'restrict'.
* lib/rijndael-api-fst.h (rijndaelBlockEncrypt, rijndaelPadEncrypt,
rijndaelBlockDecrypt, rijndaelPadDecrypt): Use 'restrict'.
* modules/crypto/rijndael (configure.ac): Require AC_C_RESTRICT.

crypto/arctwo: Use 'restrict'.
* lib/arctwo.h (arctwo_encrypt, arctwo_decrypt): Use 'restrict'.
* modules/crypto/arctwo (configure.ac): Require AC_C_RESTRICT.

crypto/arcfour: Use 'restrict'.
* lib/arcfour.h (arcfour_stream): Use 'restrict'.
* modules/crypto/arcfour (configure.ac): Require AC_C_RESTRICT.

careadlinkat: Use 'restrict'.
* lib/careadlinkat.h (careadlinkat): Use 'restrict'.
* modules/careadlinkat (configure.ac): Require AC_C_RESTRICT.
* modules/relocatable-prog-wrapper (configure.ac): Likewise.

regex-quote: Use 'restrict'.
* lib/regex-quote.h (regex_quote_copy): Use 'restrict'.
* modules/regex-quote (configure.ac): Require AC_C_RESTRICT.

system-quote: Use 'restrict'.
* lib/system-quote.h (system_quote_copy): Use 'restrict'.
* modules/system-quote (configure.ac): Require AC_C_RESTRICT.

sh-quote: Use 'restrict'.
* lib/sh-quote.h (shell_quote_copy): Use 'restrict'.
* modules/sh-quote (configure.ac): Require AC_C_RESTRICT.

quotearg: Use 'restrict'.
* lib/quotearg.h (quotearg_buffer): Use 'restrict'.
* m4/quotearg.m4 (gl_QUOTEARG): Require AC_C_RESTRICT.

parse-datetime: Use 'restrict'.
* lib/parse-datetime.h (parse_datetime, parse_datetime2): Use
'restrict'.
* m4/parse-datetime.m4 (gl_PARSE_DATETIME): Require AC_C_RESTRICT.

nstrftime: Use 'restrict'.
* lib/strftime.h (nstrftime): Use 'restrict'.
* m4/nstrftime.m4 (gl_FUNC_GNU_STRFTIME): Require AC_C_RESTRICT.

mbstok_r: Use 'restrict'.
* lib/string.in.h (mbstok_r): Use 'restrict'.

xmemcoll: Use 'restrict'.
* lib/xmemcoll.h (xmemcoll): Use 'restrict'.
* modules/xmemcoll (configure.ac): Require AC_C_RESTRICT.

memcoll: Use 'restrict'.
* lib/memcoll.h (memcoll): Use 'restrict'.
* m4/memcoll.m4 (gl_MEMCOLL): Require AC_C_RESTRICT.

vasnprintf: Use 'restrict'.
* lib/vasnprintf.h (asnprintf, vasnprintf): Use 'restrict'.
* modules/vasnprintf (configure.ac): Require AC_C_RESTRICT.

c-vasnprintf: Use 'restrict'.
* lib/c-vasnprintf.h (c_vasnprintf): Use 'restrict'.
* modules/c-vasnprintf (configure.ac): Require AC_C_RESTRICT.

Re: restrict - summary

2020-02-23 Thread Bruno Haible
This patch, finally, makes use of 'restrict' also in the libunistring header
files.


2020-02-23  Bruno Haible  

uni*/base: Use 'restrict'.
* lib/unitypes.in.h (_UC_RESTRICT): New macro, based on '_Restrict_'
from lib/regex.h.
* lib/unistr.in.h (u8_cpy, u16_cpy, u32_cpy, u8_strcpy, u16_strcpy,
u32_strcpy, u8_stpcpy, u16_stpcpy, u32_stpcpy, u8_strncpy, u16_strncpy,
u32_strncpy, u8_stpncpy, u16_stpncpy, u32_stpncpy, u8_strcat,
u16_strcat, u32_strcat, u8_strncat, u16_strncat, u32_strncat, u8_strtok,
u16_strtok, u32_strtok): Use '_UC_RESTRICT'.
* lib/uninorm.in.h (u8_normalize, u16_normalize, u32_normalize): Use
'_UC_RESTRICT'.
* lib/uniconv.in.h (u8_conv_to_encoding, u16_conv_to_encoding,
u32_conv_to_encoding): Use '_UC_RESTRICT'.
* lib/unicase.in.h (u8_toupper, u16_toupper, u32_toupper, u8_tolower,
u16_tolower, u32_tolower, u8_totitle, u16_totitle, u32_totitle,
u8_ct_toupper, u16_ct_toupper, u32_ct_toupper, u8_ct_tolower,
u16_ct_tolower, u32_ct_tolower, u8_ct_totitle, u16_ct_totitle,
u32_ct_totitle, u8_casefold, u16_casefold, u32_casefold, u8_ct_casefold,
u16_ct_casefold, u32_ct_casefold, u8_casexfrm, u16_casexfrm,
u32_casexfrm, ulc_casexfrm): Use '_UC_RESTRICT'.
* lib/unilbrk.in.h (u8_possible_linebreaks, u16_possible_linebreaks,
u32_possible_linebreaks, ulc_possible_linebreaks, u8_width_linebreaks,
u16_width_linebreaks, u32_width_linebreaks, ulc_width_linebreaks): Use
'_UC_RESTRICT'.
* lib/uniwbrk.in.h (ulc_wordbreaks): Use '_UC_RESTRICT'.
* lib/unistdio.in.h (ulc_sprintf, ulc_snprintf, ulc_asnprintf,
ulc_vsprintf, ulc_vsnprintf, ulc_vasnprintf, u8_u8_sprintf,
u8_u8_snprintf, u8_u8_asnprintf, u8_u8_vsprintf, u8_u8_vsnprintf,
u8_u8_vasnprintf, u16_u16_sprintf, u16_u16_snprintf, u16_u16_asnprintf,
u16_u16_vsprintf, u16_u16_vsnprintf, u16_u16_vasnprintf,
u32_u32_sprintf, u32_u32_snprintf, u32_u32_asnprintf, u32_u32_vsprintf,
u32_u32_vsnprintf, u32_u32_vasnprintf): Use '_UC_RESTRICT'.

diff --git a/lib/unitypes.in.h b/lib/unitypes.in.h
index c7c268f..5fff76a 100644
--- a/lib/unitypes.in.h
+++ b/lib/unitypes.in.h
@@ -43,4 +43,17 @@ typedef uint32_t ucs4_t;
 # endif
 #endif
 
+/* Qualifier in a function declaration, that asserts that the caller must
+   pass a pointer to a different object in the specified pointer argument
+   than in the other pointer arguments.  */
+#ifndef _UC_RESTRICT
+# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
+#  define _UC_RESTRICT __restrict
+# elif 199901L <= __STDC_VERSION__ || defined restrict
+#  define _UC_RESTRICT restrict
+# else
+#  define _UC_RESTRICT
+# endif
+#endif
+
 #endif /* _UNITYPES_H */
diff --git a/lib/unicase.in.h b/lib/unicase.in.h
index 45c5f91..d74afa1 100644
--- a/lib/unicase.in.h
+++ b/lib/unicase.in.h
@@ -96,15 +96,15 @@ extern const char *
 extern uint8_t *
u8_toupper (const uint8_t *s, size_t n, const char *iso639_language,
uninorm_t nf,
-   uint8_t *resultbuf, size_t *lengthp);
+   uint8_t *_UC_RESTRICT resultbuf, size_t *lengthp);
 extern uint16_t *
u16_toupper (const uint16_t *s, size_t n, const char *iso639_language,
 uninorm_t nf,
-uint16_t *resultbuf, size_t *lengthp);
+uint16_t *_UC_RESTRICT resultbuf, size_t *lengthp);
 extern uint32_t *
u32_toupper (const uint32_t *s, size_t n, const char *iso639_language,
 uninorm_t nf,
-uint32_t *resultbuf, size_t *lengthp);
+uint32_t *_UC_RESTRICT resultbuf, size_t *lengthp);
 
 /* Return the lowercase mapping of a string.
The nf argument identifies the normalization form to apply after the
@@ -112,15 +112,15 @@ extern uint32_t *
 extern uint8_t *
u8_tolower (const uint8_t *s, size_t n, const char *iso639_language,
uninorm_t nf,
-   uint8_t *resultbuf, size_t *lengthp);
+   uint8_t *_UC_RESTRICT resultbuf, size_t *lengthp);
 extern uint16_t *
u16_tolower (const uint16_t *s, size_t n, const char *iso639_language,
 uninorm_t nf,
-uint16_t *resultbuf, size_t *lengthp);
+uint16_t *_UC_RESTRICT resultbuf, size_t *lengthp);
 extern uint32_t *
u32_tolower (const uint32_t *s, size_t n, const char *iso639_language,
 uninorm_t nf,
-uint32_t *resultbuf, size_t *lengthp);
+uint32_t *_UC_RESTRICT resultbuf, size_t *lengthp);
 
 /* Return the titlecase mapping of a string.
The nf argument identifies the normalization form to apply after the
@@ -128,15 +128,15 @@ extern uint32_t *
 extern uint8_t *
u8_totitle (const uint8_t *s, size_t n, const char *iso639_languag

Re: restrict - summary

2020-02-24 Thread Eric Blake

On 2/22/20 4:51 PM, Bruno Haible wrote:

Here comes the first part: the 'restrict' in the POSIX function declarations.

Note that the POSIX declarations of posix_spawn and posix_spawnp [1] are
incorrect: They lack a 'restrict' for the file_actions argument.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html


Bug reported to the POSIX folks:
https://www.austingroupbugs.net/view.php?id=1328

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org