Re: restrict - summary
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
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
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
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
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