summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorAlejandro Colomar <alx@kernel.org>2022-11-12 00:48:10 +0100
committerAlejandro Colomar <alx@nginx.com>2022-11-16 13:09:18 +0100
commit4c7e1ee46506cdb63523b04a828fbdaa73743ddf (patch)
tree30275a99269276e0e380a771b5b02f63409fcac5 /src
parentd0f5370f343a7786a1ab5d0325aa90518695662c (diff)
downloadunit-4c7e1ee46506cdb63523b04a828fbdaa73743ddf.tar.gz
unit-4c7e1ee46506cdb63523b04a828fbdaa73743ddf.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 * int *ip = &i; * 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 * result in 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. * * p = (int *) cs; /* Extremely unsafe; it will almost * certainly result in Undefined * Behaviour. */ * p = char_cast(int *, cs); // Compiler error. Cast not allowed. * * p = (char *) ip; /* Technically OK, but probably * not what you want. */ * p = char_cast(char *, ip); // Compiler error. Cast not allowed. * * 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.h37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/nxt_clang.h b/src/nxt_clang.h
index 94638346..9c19d77d 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. */