From patchwork Fri Sep 25 19:37:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 40507 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 8AAF3398B434; Fri, 25 Sep 2020 19:38:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8AAF3398B434 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1601062697; bh=jbsgOVHvmUXSEBjLnfyZSNTlMb8phG4kk/fXxKZ+eRg=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Yze8KfkoodU4bkY2yFgX/c5HndLcXNFp2CYYnDh3+YnbIApD/wsVLP8u1hL08kDB2 BbNzD/WMl6fFpuDKyNa+R24EQ0xnrYfhOptY1K9AGsTns3XR0GabzBSwFhlhRN566Y aXEgzXKxFYb78A3KVBTyfycST2MuKiqjDMEtsvaM= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by sourceware.org (Postfix) with ESMTPS id 0B31A3860C38 for ; Fri, 25 Sep 2020 19:38:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 0B31A3860C38 Received: by mail-wm1-x342.google.com with SMTP id y15so203010wmi.0 for ; Fri, 25 Sep 2020 12:38:13 -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:in-reply-to :references:mime-version:content-transfer-encoding; bh=jbsgOVHvmUXSEBjLnfyZSNTlMb8phG4kk/fXxKZ+eRg=; b=WCUjwzSSkQ3gAfoSPL8OaaUusHvbXsTkHDNfMhCr71XQDPVyrnMVMq93WpxAhFVRHL k4dMGpo3vHhLwwBOesNqL/MdGZwCu93tmXBLC2UyKmQe3GwyqV7B+zgZAfI3efzUtKMc RkAholr57LgRzDNDjqCHbqm7VNid/+fcFI8MUPF9Gq7XMuYt+Htt1PkstxHqnqKdnXXk 0EY1wYYSSZ4rmvXJxUFJFkJMUwstmdzvCIDSXwnmYun4u7AWb9XD+9bEYr2dcLp/0+iE XIHg2/KOxy22YRVwBpniz8eP3xyJRUlzfPQQS9/lQEL4nGFHaFmCC/X5e3sRJ2tPzRX7 8x+A== X-Gm-Message-State: AOAM530393+R3bKRRx+YxcNzpBC21JjPM5ym7WvZuqE+6ef8D6jxsiHa 2eF8Oytq4ijSwOduPHKmAy0aSCUVtn2HZA== X-Google-Smtp-Source: ABdhPJyqlDntoAWN5Ogrw2rGYEXT5bafB540fMrgyreKkEcl6WZOTJklZWUGNDReomLwbqLRszc1eA== X-Received: by 2002:a1c:e389:: with SMTP id a131mr117683wmh.181.1601062692684; Fri, 25 Sep 2020 12:38:12 -0700 (PDT) Received: from localhost.localdomain ([93.115.133.118]) by smtp.googlemail.com with ESMTPSA id m18sm50368wmg.32.2020.09.25.12.38.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Sep 2020 12:38:12 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v3] : Add nitems() Date: Fri, 25 Sep 2020 21:37:29 +0200 Message-Id: <20200925193728.30351-1-colomar.6.4.3@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Status: No, score=-10.1 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=unavailable 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, colomar.6.4.3@gmail.com, 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. __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 --- misc/sys/param.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/misc/sys/param.h b/misc/sys/param.h index d7c319b157..d88cbacc9c 100644 --- a/misc/sys/param.h +++ b/misc/sys/param.h @@ -102,5 +102,56 @@ #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 __array_len(_Arr) (sizeof(_Arr) / sizeof((_Arr)[0])) +# define nitems(_Arr) (__array_len(_Arr) + __must_be_array(_Arr)) +#endif /* !defined(__cplusplus) */ + #endif /* sys/param.h */