From patchwork Mon Sep 28 19:12:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 40528 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3179D39540C4; Mon, 28 Sep 2020 19:13:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3179D39540C4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1601320382; bh=vz8QchO9cmYjlrvcRjFTzSFLrDWK4NlG4rgcy0Z2ls0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=VHXl4ppm9cVLwA7f3rCBM7D7Y1/PU4RmzZGftsDH/2iqUojtcpTCQfRZWMaAEvZHh nZFFTu9+rbMNouY7G3Q+zXtPmVNVhyYoHxcfmcsP6CCzOLB0lNsqrapexVVHpNvuhG dDOstIlSFWcXwRMBmnFyVOcMqmb+NWU/QHuL7n3I= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by sourceware.org (Postfix) with ESMTPS id 66FB33861830 for ; Mon, 28 Sep 2020 19:12:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 66FB33861830 Received: by mail-wr1-x443.google.com with SMTP id x14so2511590wrl.12 for ; Mon, 28 Sep 2020 12:12:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=vz8QchO9cmYjlrvcRjFTzSFLrDWK4NlG4rgcy0Z2ls0=; b=iKoXeVB866UBhgmQ3meXhqkk5gEs/JzxyasSa6x5ab6JTjbyg7gusf8BT9hIpcqVVK 52p7LgAJTuXwveH10RkCoGVMzDY6Y+GurjFM7ZECEnisLqoID3PxAibIkLaMRoGa1OwU WnO9zEfpQwlMsdnrDWBosTybbVbjFogiAdLv45Vj85LwoXQ5Zv970Makg+O4LnpZl9cq bXlEu9gjTVDu0HbVRkVDEdXnF2DoBwBt4sVxJ2ryvaTEmbvms3fCKxDyykcQbKBYNlIT 27BcPD3zNUC65zRCpX2BPFHF3qKHa06mojcUYvTdWd/LnrpEKRUgZJ8VABS5EzLl9VPI vEdg== X-Gm-Message-State: AOAM5312mXnlkHZZZJ88xiRVxGhtL/ezS0c8qsW+qkyK3dZjkUGpIbIQ X0N6NVQX0hlgUmYUSvd92Hv4AQZ5LC4Rsg== X-Google-Smtp-Source: ABdhPJxiovG5tEEYTxk/MpoF6F52R8oux8Nz02/E+YQwQi67lZw1/Wi5MOd0u/CLQO5ZyrON/8wPTw== X-Received: by 2002:adf:dd0b:: with SMTP id a11mr3152720wrm.422.1601320376258; Mon, 28 Sep 2020 12:12:56 -0700 (PDT) Received: from localhost.localdomain ([170.253.60.68]) by smtp.googlemail.com with ESMTPSA id u17sm3072159wri.45.2020.09.28.12.12.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Sep 2020 12:12:55 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v4] : Add nitems() Date: Mon, 28 Sep 2020 21:12:37 +0200 Message-Id: <20200928191237.32063-1-colomar.6.4.3@gmail.com> X-Mailer: git-send-email 2.28.0 MIME-Version: 1.0 X-Spam-Status: No, score=-9.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Alejandro Colomar via Libc-alpha From: Alejandro Colomar Reply-To: Alejandro Colomar Cc: fweimer@redhat.com, gcc@gcc.gnu.org, ville.voutilainen@gmail.com, linux-man@vger.kernel.org, Alejandro Colomar , rusty@rustcorp.com.au, linux-kernel@vger.kernel.org, libstdc++@gcc.gnu.org, libc-coord@lists.openwall.com, jwakely@redhat.com, enh@google.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" '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 Some BSDs already provide a macro nitems() in , 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. __nitems(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 --- A few changes since v3: - Macros don't need reserved names in their parameters, so I simplified those names. - I fixed some wrong indentation levels. - Renamed __array_len() to __nitems() for consistency. misc/sys/param.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/misc/sys/param.h b/misc/sys/param.h index d7c319b157..08d4093961 100644 --- a/misc/sys/param.h +++ b/misc/sys/param.h @@ -102,5 +102,52 @@ #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 + constexpr inline std::size_t + nitems(const _Tp(&)[_Len]) __THROW + { + return _Len; + } +# else /* __cplusplus < 201103L */ +template + char + (&__nitems_chararr(const _Tp(&)[_Len]))[_Len]; +# define nitems(arr) (sizeof(__nitems_chararr(arr))) +# endif /* __cplusplus < 201103L */ +#else /* !defined(__cplusplus) */ +# define __nitems(arr) (sizeof((arr)) / sizeof((arr)[0])) +# define nitems(arr) (__nitems(arr) + __must_be_array(arr)) +#endif /* !defined(__cplusplus) */ + #endif /* sys/param.h */