From 5e0fe2cd1a8bef0b415451717eb5c313ce90f675 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 12 Nov 2022 00:48:10 +0100 Subject: 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 Signed-off-by: Alejandro Colomar --- src/nxt_clang.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src/nxt_clang.h') 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. */ -- cgit