From patchwork Fri Sep 25 13:20:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 40506 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 7F1B6398B40F; Fri, 25 Sep 2020 13:20:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7F1B6398B40F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1601040022; bh=ctCRRBMXBs6kMpZcuPxnX56lRnYkUGrCUb67xAJsOfY=; 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=RHqWZ22aXdDsGxtE9OaEmEfdPmLkrUFi4qx7zGxD0YYw8JfA/PI5JwfFFOpNNmosV ckAF/pTUr8scZcxmQcEqnq3+tMBNulNxquali2Rb2vNep2V2UfB56675xPwcQEX4Ux xMKRmlp7+8gtG78evt+1nB4A09MPrK87ROp46idM= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by sourceware.org (Postfix) with ESMTPS id B4ADE398B17D for ; Fri, 25 Sep 2020 13:20:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org B4ADE398B17D Received: by mail-wm1-x344.google.com with SMTP id v12so3272732wmh.3 for ; Fri, 25 Sep 2020 06:20:14 -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=ctCRRBMXBs6kMpZcuPxnX56lRnYkUGrCUb67xAJsOfY=; b=e8H6FXEQrKXqCmMDDWFXcJoCsIbtWeVbpQhv897YL1lUVu99U9Qp1kpW0TfkdgHBKG oUiqt15eWzV/0lqG4piWKOXWLc/hxq99gAZMMev1bgbN/f8HZIo2JFc0jSLoOzfsosVx YMP6SvXENedLMzp3zTdLBAbCNcG8Y7AnOgTqvQzcjr2EjW09MpkUeNnUNSSUgWePkd9r ipaB4SOxi7hwKAIddAvGkAhpGTmc0uCVMbNXM1QPOjS3smu2lcMWa0xMXh+OIuXVE6I6 HPXHfsc9er6pRYZ7UU3qKOrQCdazhCZbGYiT9fJU1QDYsMNheXRxSDJoBE0hPtPXOP7g shPA== X-Gm-Message-State: AOAM532OyDnCFW4HkdGMS8b7JUqCva9DwugD4dV/Orqz375IzT6bIaKj febtTbhIm2E4Bo7Ly3jjOd8gqyQeI4THMQ== X-Google-Smtp-Source: ABdhPJx7WgtlsBquBISAJGIrFfzINAei+kh2aFn9YKbsA0GYSp5DIoWlYBfSFuxhbbFmeBKDRV1m2g== X-Received: by 2002:a1c:1d08:: with SMTP id d8mr3285621wmd.78.1601040013526; Fri, 25 Sep 2020 06:20:13 -0700 (PDT) Received: from localhost.localdomain ([170.253.60.68]) by smtp.googlemail.com with ESMTPSA id l4sm3004917wrc.14.2020.09.25.06.20.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Sep 2020 06:20:12 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v2] : Add nitems() and snitems() macros Date: Fri, 25 Sep 2020 15:20:01 +0200 Message-Id: <20200925132000.235033-1-colomar.6.4.3@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200922145844.31867-1-colomar.6.4.3@gmail.com> References: <20200922145844.31867-1-colomar.6.4.3@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-11.2 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 '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 , 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 | 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 + constexpr inline std::size_t + nitems(const _Tp(&)[_Len]) __THROW + { + return _Len; + } + +template + constexpr inline std::ptrdiff_t + snitems(const _Tp(&)[_Len]) __THROW + { + return _Len; + } + +# else /* __cplusplus < 201103L */ +template + char + (&__nitems_chararr(const _Tp(&)[_Len]))[_Len]; + +# define nitems(_Arr) (sizeof(__nitems_chararr(_Arr))) +# define snitems(_Arr) (static_cast(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 */