From: Jani Nikula <jani.nikula@linux.intel.com>
To: Kees Cook <keescook@chromium.org>,
Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Kees Cook <keescook@chromium.org>,
"Gustavo A . R . Silva" <gustavoars@kernel.org>,
Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>,
David Laight <David.Laight@aculab.com>,
Nick Desaulniers <ndesaulniers@google.com>,
Martin Uecker <Martin.Uecker@med.uni-goettingen.de>,
Jonathan Corbet <corbet@lwn.net>,
linux-doc@vger.kernel.org, Miguel Ojeda <ojeda@kernel.org>,
linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org
Subject: Re: [PATCH] compiler.h: Explain how __is_constexpr() works
Date: Fri, 01 Mar 2024 10:16:47 +0200 [thread overview]
Message-ID: <87zfvi5pu8.fsf@intel.com> (raw)
In-Reply-To: <20240301044428.work.411-kees@kernel.org>
On Thu, 29 Feb 2024, Kees Cook <keescook@chromium.org> wrote:
> The __is_constexpr() macro is dark magic. Shed some light on it with
> a comment to explain how and why it works.
Hey, it was a fun little puzzle to figure out using the C standard. Now
you're ruining it for everyone! ;)
The description matches my recollection of how it works. Especially the
meaning of the first 8 threw me off way back when. And looks like I've
replied to that effect for v1.
FWIW,
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
but I'm sure there are more pedantic reviewers for all the minor
details.
>
> Acked-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Cc: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: David Laight <David.Laight@aculab.com>
> Cc: Nick Desaulniers <ndesaulniers@google.com>
> Cc: Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: linux-doc@vger.kernel.org
> v2: *thread necromancy* rewrite based on feedback to v1
> v1: https://lore.kernel.org/all/20220131204357.1133674-1-keescook@chromium.org/
> ---
> include/linux/compiler.h | 39 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 39 insertions(+)
>
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index bb1339c7057b..38cd9f3c8f6a 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -231,6 +231,45 @@ static inline void *offset_to_ptr(const int *off)
> * This returns a constant expression while determining if an argument is
> * a constant expression, most importantly without evaluating the argument.
> * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
> + *
> + * Details:
> + * - sizeof() return an integer constant expression, and does not evaluate
> + * the value of its operand; it only examines the type of its operand.
> + * - The results of comparing two integer constant expressions is also
> + * an integer constant expression.
> + * - The first literal "8" isn't important. It could be any literal value.
> + * - The second literal "8" is to avoid warnings about unaligned pointers;
> + * this could otherwise just be "1".
> + * - (long)(x) is used to avoid warnings about 64-bit types on 32-bit
> + * architectures.
> + * - The C Standard defines "null pointer constant", "(void *)0", as
> + * distinct from other void pointers.
> + * - If (x) is an integer constant expression, then the "* 0l" resolves
> + * it into an integer constant expression of value 0. Since it is cast to
> + * "void *", this makes the second operand a null pointer constant.
> + * - If (x) is not an integer constant expression, then the second operand
> + * resolves to a void pointer (but not a null pointer constant: the value
> + * is not an integer constant 0).
> + * - The conditional operator's third operand, "(int *)8", is an object
> + * pointer (to type "int").
> + * - The behavior (including the return type) of the conditional operator
> + * ("operand1 ? operand2 : operand3") depends on the kind of expressions
> + * given for the second and third operands. This is the central mechanism
> + * of the macro:
> + * - When one operand is a null pointer constant (i.e. when x is an integer
> + * constant expression) and the other is an object pointer (i.e. our
> + * third operand), the conditional operator returns the type of the
> + * object pointer operand (i.e. "int *). Here, within the sizeof(), we
> + * would then get:
> + * sizeof(*((int *)(...)) == sizeof(int) == 4
> + * - When one operand is a void pointer (i.e. when x is not an integer
> + * constant expression) and the other is an object pointer (i.e. our
> + * third operand), the conditional operator returns a "void *" type.
> + * Here, within the sizeof(), we would then get:
> + * sizeof(*((void *)(...)) == sizeof(void) == 1
> + * - The equality comparison to "sizeof(int)" therefore depends on (x):
> + * sizeof(int) == sizeof(int) (x) was a constant expression
> + * sizeof(int) != sizeof(void) (x) was not a constant expression
> */
> #define __is_constexpr(x) \
> (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
--
Jani Nikula, Intel
next prev parent reply other threads:[~2024-03-01 8:16 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-01 4:44 [PATCH] compiler.h: Explain how __is_constexpr() works Kees Cook
2024-03-01 8:16 ` Jani Nikula [this message]
2024-03-01 9:32 ` David Laight
2024-03-01 13:21 ` [+externe Mail+] " Uecker, Martin
2024-03-01 13:43 ` David Laight
2024-03-01 13:56 ` Uecker, Martin
2024-03-02 1:17 ` Andy Shevchenko
2024-03-02 1:46 ` Kees Cook
2024-03-04 16:52 ` Nick Desaulniers
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=87zfvi5pu8.fsf@intel.com \
--to=jani.nikula@linux.intel.com \
--cc=David.Laight@aculab.com \
--cc=Martin.Uecker@med.uni-goettingen.de \
--cc=corbet@lwn.net \
--cc=gustavoars@kernel.org \
--cc=keescook@chromium.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@rasmusvillemoes.dk \
--cc=miguel.ojeda.sandonis@gmail.com \
--cc=ndesaulniers@google.com \
--cc=ojeda@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.