From: Alejandro Colomar <colomar.6.4.3@gmail.com>
To: libc-alpha@sourceware.org
Cc: libc-coord@lists.openwall.com, libstdc++@gcc.gnu.org,
gcc@gcc.gnu.org, linux-kernel@vger.kernel.org,
linux-man@vger.kernel.org, fweimer@redhat.com,
jwakely@redhat.com, ville.voutilainen@gmail.com, enh@google.com,
rusty@rustcorp.com.au
Subject: Re: [PATCH v2] <sys/param.h>: Add nitems() and snitems() macros
Date: Fri, 25 Sep 2020 16:10:02 +0200 [thread overview]
Message-ID: <f6257d7d-1cea-b45c-a858-b80bbc1f18b1@gmail.com> (raw)
In-Reply-To: <20200925132000.235033-1-colomar.6.4.3@gmail.com>
On 2020-09-25 15:20, Alejandro Colomar wrote:
> 'nitems()' calculates the length of an array in number of items.
> It is safe: if a pointer is passed to the macro (or function, in C++),
> the compilation is broken due to:
> - In >= C11: _Static_assert()
> - In C89, C99: Negative anonymous bitfield
> - In C++: The template requires an array
>
> 'snitems()' is equivalent to nitems(),
> but it returns a 'ptrdiff_t' instead of a 'size_t'.
> It is useful for comparison with signed integer values.
>
> Some BSDs already provide a macro nitems() in <sys/param.h>,
> although it usually doesn't provide safety against pointers.
>
> This patch uses the same name for compatibility reasons,
> and to be the least disruptive with existing code.
>
> This patch also adds some other macros, which are required by 'nitems()':
>
> __is_same_type(_A, _B):
> Returns non-zero if the two input arguments are of the same type.
>
> __is_array(_Arr):
> Returns non-zero if the input argument is of an array type.
>
> __must_be(_Expr, _Msg):
> Allows using _Static_assert() everywhere an expression can be used.
> It evaluates '(int)0' or breaks the compilation.
>
> __must_be_array(_Arr):
> It evaluates to '(int)0' if the argument is of an array type.
> Else, it breaks compilation.
>
> __array_len(_Arr):
> It implements the basic sizeof division needed to calculate the array
length.
>
>
> P.S.: I'd like to put this patch in the public domain.
>
>
> Signed-off-by: Alejandro Colomar <colomar.6.4.3@gmail.com>
> ---
I patched my own system's <sys/param.h> with this,
and while 'nitems()' works fine,
I had to include <stddef.h> in my main.c to be able to use 'snitems()',
because I didn't have 'ptrdiff_t',
eventhough <sys/param.h> already includes <stddef.h>.
I completely ignore the mechanisms behind system headers including
other system headers.
Moreover, I didn't find 'ptrdiff_t' defined in any of my systems headers
I used 'user@debian:/usr/include$ grep -rn ptrdiff_t'. Does GCC do magic?
What's the problem with that? How should I fix the patch?
My system: Debian bullseye/sid; x86-64; gcc 10; libc 2.31-3
Thanks,
Alex
> misc/sys/param.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 60 insertions(+)
>
> diff --git a/misc/sys/param.h b/misc/sys/param.h
> index d7c319b157..88e95c2dba 100644
> --- a/misc/sys/param.h
> +++ b/misc/sys/param.h
> @@ -102,5 +102,65 @@
> #define MIN(a,b) (((a)<(b))?(a):(b))
> #define MAX(a,b) (((a)>(b))?(a):(b))
>
> +/* Macros related to the types of variables */
> +# define __is_same_type(_A, _B)
__builtin_types_compatible_p(__typeof__(_A), \
> +
__typeof__(_B))
> +# define __is_array(_Arr) (!__is_same_type((_Arr), &(_Arr)[0]))
> +
> +/* Macros for embedding _Static_assert() in expressions */
> +# if __STDC_VERSION__ >= 201112L
> +# define __must_be(_Expr, _Msg) (
\
> + 0 * (int)sizeof(
\
> + struct {
\
> + _Static_assert((_Expr), _Msg);
\
> + char _ISO_C_forbids_a_struct_with_no_members;
\
> + }
\
> + )
\
> +)
> +# else
> +# define __must_be(_Expr, _Msg) (
\
> + 0 * (int)sizeof(
\
> + struct {
\
> + int : (-!(_Expr));
\
> + char _ISO_C_forbids_a_struct_with_no_members;
\
> + }
\
> + )
\
> +)
> +# endif
> +
> +# define __must_be_array(_Arr) __must_be(__is_array(_Arr), "Must be
an array!")
> +
> +/* Macros for array sizes */
> +#if defined(__cplusplus)
> +# if __cplusplus >= 201103L
> +template<typename _Tp, std::size_t _Len>
> + constexpr inline std::size_t
> + nitems(const _Tp(&)[_Len]) __THROW
> + {
> + return _Len;
> + }
> +
> +template<typename _Tp, std::size_t _Len>
> + constexpr inline std::ptrdiff_t
> + snitems(const _Tp(&)[_Len]) __THROW
> + {
> + return _Len;
> + }
> +
> +# else /* __cplusplus < 201103L */
> +template<typename _Tp, std::size_t _Len>
> + char
> + (&__nitems_chararr(const _Tp(&)[_Len]))[_Len];
> +
> +# define nitems(_Arr) (sizeof(__nitems_chararr(_Arr)))
> +# define snitems(_Arr)
(static_cast<std::ptrdiff_t>(nitems(_Arr)))
> +# endif /* __cplusplus < 201103L */
> +
> +#else /* !defined(__cplusplus) */
> +# define __array_len(_Arr) (sizeof(_Arr) / sizeof((_Arr)[0]))
> +# define nitems(_Arr) (__array_len(_Arr) +
__must_be_array(_Arr))
> +# define snitems(_Arr) ((ptrdiff_t)nitems(_Arr))
> +#endif /* !defined(__cplusplus) */
> +
>
> #endif /* sys/param.h */
>
next prev parent reply other threads:[~2020-09-25 14:10 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-20 23:00 Expose 'array_length()' macro in <sys/cdefs.h> or <sys/param.h> Alejandro Colomar
2020-09-21 8:38 ` Florian Weimer
2020-09-21 10:11 ` Alejandro Colomar
2020-09-21 10:33 ` Florian Weimer
2020-09-21 12:47 ` Alejandro Colomar
2020-09-21 15:47 ` [libc-coord] " enh
2020-09-22 16:25 ` Rich Felker
2020-09-22 16:44 ` Jonathan Wakely
2020-09-22 16:53 ` Ville Voutilainen
2020-09-21 14:01 ` Jonathan Wakely
2020-09-21 21:52 ` Expose 'array_length()' macro in <sys/param.h> Alejandro Colomar
2020-09-21 22:04 ` Jonathan Wakely
2020-09-21 22:13 ` Ville Voutilainen
2020-09-22 9:10 ` Alejandro Colomar
2020-09-22 9:40 ` Jonathan Wakely
2020-09-22 10:01 ` Florian Weimer
2020-09-22 10:35 ` Alejandro Colomar
2020-09-22 11:40 ` Florian Weimer
2020-09-22 14:58 ` [RFC] <sys/param.h>: Add nitems() and snitems() macros Alejandro Colomar
2020-09-25 13:20 ` [PATCH v2] " Alejandro Colomar
2020-09-25 14:10 ` Alejandro Colomar [this message]
2020-09-25 14:48 ` Jonathan Wakely
2020-09-25 16:30 ` Alejandro Colomar
2020-09-25 17:39 ` Jonathan Wakely
2020-09-25 17:42 ` Jonathan Wakely
2020-09-25 17:46 ` Alejandro Colomar
2020-09-25 19:37 ` [PATCH v3] <sys/param.h>: Add nitems() Alejandro Colomar
2020-09-22 9:16 ` [libc-coord] Re: Expose 'array_length()' macro in <sys/param.h> Florian Weimer
2020-09-30 15:58 ` Expose 'array_length()' macro in <sys/cdefs.h> or <sys/param.h> Joseph Myers
2020-09-30 20:39 ` Alejandro Colomar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f6257d7d-1cea-b45c-a858-b80bbc1f18b1@gmail.com \
--to=colomar.6.4.3@gmail.com \
--cc=enh@google.com \
--cc=fweimer@redhat.com \
--cc=gcc@gcc.gnu.org \
--cc=jwakely@redhat.com \
--cc=libc-alpha@sourceware.org \
--cc=libc-coord@lists.openwall.com \
--cc=libstdc++@gcc.gnu.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-man@vger.kernel.org \
--cc=rusty@rustcorp.com.au \
--cc=ville.voutilainen@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).