diff options
author | Alejandro Colomar <alx@kernel.org> | 2022-11-12 00:48:10 +0100 |
---|---|---|
committer | Alejandro Colomar <alx@nginx.com> | 2022-11-15 13:09:49 +0100 |
commit | 5e0fe2cd1a8bef0b415451717eb5c313ce90f675 (patch) | |
tree | 8f3b5ced47d2e0118a4369a47076fbb0fc416f74 /src | |
parent | 5a1597072496067f6cf36320687d6e9d9b5fa604 (diff) | |
download | unit-5e0fe2cd1a8bef0b415451717eb5c313ce90f675.tar.gz unit-5e0fe2cd1a8bef0b415451717eb5c313ce90f675.tar.bz2 |
Added nxt_char_cast() macro for casting safely.
This macro is similar to C++'s static_cast(). It allows a very-limited
set of casts to be performed, but rejects most casts. Basically, it
only allows converting from char to u_char and vice-versa, while
respecting the const qualifier.
/*
* SYNOPSIS
* type char_cast(type, string);
*
* ARGUMENTS
* type Type to which 'string' should be cast.
* string String that should be cast to 'type'. It should be a
* pointer, or a pointer to a pointer, to a character type,
* possibly const-qualified.
*
* DESCRIPTION
* This macro resembles C++'s static_cast(). It performs a cast,
* as if '(type) string' was written, but it performs additional
* checks that make sure the cast is limited to character types,
* that the input expression is also of a character type, and that
* it doesn't remove a const qualifier.
*
* It also makes it easier to find all casts easily with grep(1).
*
* CAVEATS
* It doesn't allow using 'volatile'. However, this isn't a big
* issue, since we don't use it with strings. If necessary, the
* macro can be improved to support volatile.
*
* EXAMPLES
* char *s = "foo";
* const char *cs = "bar";
*
* p = (char *) s; /* OK. Although unsafe, because it can be
* confused with the case in the next line. */
* p = (char *) cs; /* Very unsafe; it will probably cause
* Undefined Behaviour. */
*
* p = char_cast(char *, s); // OK.
* p = char_cast(char *, cs); // Compiler error. Cast not allowed.
*
* p = (const char *) s; // OK.
* p = (const char *) cs; // OK.
*
* p = char_cast(const char *, s); // OK.
* p = char_cast(const char *, cs); // OK.
*
* SEE ALSO
* _Generic(3)
*/
Acked-by: Andrew Clayton <a.clayton@nginx.com>
Signed-off-by: Alejandro Colomar <alx@nginx.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/nxt_clang.h | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/src/nxt_clang.h b/src/nxt_clang.h index f465d562..d89e2d69 100644 --- a/src/nxt_clang.h +++ b/src/nxt_clang.h @@ -13,6 +13,43 @@ #define nxt_cdecl +#if (NXT_HAVE_C11_GENERIC) +#define nxt_char_cast(t, p) \ + _Generic(&*(p), \ + u_char *: \ + _Generic((t) NULL, \ + char *: (t) (p), \ + const char *: (t) (p), \ + default: (p)), \ + u_char **: \ + _Generic((t) NULL, \ + char **: (t) (p), \ + default: (p)), \ + const u_char *: \ + _Generic((t) NULL, \ + const char *: (t) (p), \ + default: (p)), \ + char *: \ + _Generic((t) NULL, \ + u_char *: (t) (p), \ + const u_char *: (t) (p), \ + default: (p)), \ + char **: \ + _Generic((t) NULL, \ + u_char **: (t) (p), \ + default: (p)), \ + const char *: \ + _Generic((t) NULL, \ + const u_char *: (t) (p), \ + default: (p)), \ + default: \ + (p) \ + ) +#else +#define nxt_char_cast(t, p) ((t) (p)) +#endif + + #if (NXT_CLANG) /* Any __asm__ directive disables loop vectorization in GCC and Clang. */ |