Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp1103175pxk; Fri, 25 Sep 2020 06:24:01 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxUDsERWTDhK/BRmb7ZJSWr7JGgvhQRi475OZ8ZkkegJJq3TU5GSCKWZJTmrC4jT15/nT9q X-Received: by 2002:a50:e44b:: with SMTP id e11mr1311511edm.73.1601040241191; Fri, 25 Sep 2020 06:24:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1601040241; cv=none; d=google.com; s=arc-20160816; b=NeSWuUZxWs0fEvlsUNFUGL4VuBbFLGEgj8suJwgvQYXNiBs8f5eVDuUIjgU55cuc5V KQaooq79LCBFaHtqDPIWPOM1qdf+kPp/q90ynUmtYmAz3y1353Vp+cq6Kr/1gMKVPGJq p74QHuiT1uOf+9fIxHqkkMhjAUrHyxMy8xOaPNri+1skJB68l74fVgep87QQmWc++wfe Fs/b16+S7I+pv9qiEPj+UhO2RIoJkNJiAE2pHnicYWCLRg5NXfIkbNb/Kd2XkUutZCCZ 9p+YnSDxOyD0WCjb2cexzVVfZyyhUkv2Xvf0LcRJ8+8kP/uYYy6LQxnNZhjPu3GcA1jj Dwng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ctCRRBMXBs6kMpZcuPxnX56lRnYkUGrCUb67xAJsOfY=; b=XSk02g5GEc6tWcD5EpyD7jTfncfoxw0/tLkGhng6n8DOe57kyXFIXJTDOnl1hsS8q7 uEn62J63med2gdXjXyGGi8uyJltx+xJiG5Y6C7uux1q/IQzfbNesOnm6My9Cd+TC+6QM cERBxTDuK4imz2zr5V/KNq6Qe5/RqC+C4Q0R1uacGA3+hv/Yw1d3NVWICJcsbJi59lWA 2u6vd2cfIyR+36VUlgR/yNk7L3SL4+eSEUww0RHqedJEeFOBCkjA1edWPEU0x0HXQLpq /0tCrOFOeqZ00VYlirHgMYxnY1yKLbq5NGwcx8OB4hm9ytvJZsuFzbeQYya7JTKloOML IrdQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ldwrKLkh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z10si1853809ejj.296.2020.09.25.06.23.38; Fri, 25 Sep 2020 06:24:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ldwrKLkh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728695AbgIYNUP (ORCPT + 99 others); Fri, 25 Sep 2020 09:20:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727733AbgIYNUP (ORCPT ); Fri, 25 Sep 2020 09:20:15 -0400 Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D0E0BC0613CE; Fri, 25 Sep 2020 06:20:14 -0700 (PDT) Received: by mail-wm1-x343.google.com with SMTP id e17so3033468wme.0; Fri, 25 Sep 2020 06:20:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ctCRRBMXBs6kMpZcuPxnX56lRnYkUGrCUb67xAJsOfY=; b=ldwrKLkhQdaRphySlnkUcnORC/28bvFdDoFF1eRdlRzrVNfzr0v881BAm5vMqA6IaJ AMLT+JPdCJKkfeIpFxgF8MJj37nYcNijBVxa5gjuIGVcOvICMnUU78s5Z7P7nvKvOHsp VR7DoTlpWnWUtLbzdOeIvOlcQgzo4bXZvgmF0ZyxKS+iamy0PnKCYqxr/40agxKNqTyn O3Pob3ArUBG7vJnnsP5gWhgd11Dr4O31MpUg370ITJF96KYeOR1zNPI8gzVsIeg0HpCM LTcFK2szZBfT9uSGwqWxH3XzvqOrEIDwyjCUBgAIpXymtZohhYbVs5wHtfL16KCZm+IP hMBw== 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=bxjwALyCxlfVfIWP4wVqVtsq5DRYMovSkQ4z+TUp6nhJAzRJ7XmYy3WZJYwM/qgBBA JoOm+1TSSMTqr0peoBu8FZCdKz8lUTSF+kNv0XvvcI9JJKD4VLJKrp0lpMvvprJlGfra WSpkpKn2JiwBv3rNNv+9lW/17+lg2fn1TgL5h2+F0Q3IMWAB6tN8jzeCG8vH4iv8iCX+ xyUPi43LEOB6Q0HE0ZgY0auL68Tm4qsnkcw+PibtHa2cE8WxZEBpeZPyXrNHpVVUDLUf FGA4gy50zbU3aETeELw4DcZn80GDGA2AbdxHcUe+9+dUl0Xcri5o8S4nW00LgMHSo+fJ nxHA== X-Gm-Message-State: AOAM533mLE8NTBdTO9KMm1fxkcqT1P5S8bU9/zSqCmcthSSmWnniPvBl y8TZxDpDlcFloLSQg9WcE8Q= 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) From: Alejandro Colomar 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, colomar.6.4.3@gmail.com, rusty@rustcorp.com.au 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 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org '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 */ -- 2.28.0