From 9e647d8ca0928abe9680b8e83affe98f68443a3b Mon Sep 17 00:00:00 2001 From: markster Date: Sat, 8 Jan 2005 19:00:46 +0000 Subject: Warn if flags is signed instead of unsigned (bug #3279) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4713 f38db490-d61c-443f-a65b-d21fe96a405b --- include/asterisk/channel.h | 4 +-- include/asterisk/utils.h | 81 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 16 deletions(-) (limited to 'include/asterisk') diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 765e7ff4d..2bd38b217 100755 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -218,7 +218,7 @@ struct ast_channel { unsigned int pickupgroup; /*! channel flags of AST_FLAG_ type */ - int flags; + unsigned int flags; /*! For easy linking */ struct ast_channel *next; @@ -251,7 +251,7 @@ struct ast_bridge_config { char *end_sound; char *start_sound; int firstpass; - int flags; + unsigned int flags; }; struct chanmon; diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index 9798543ba..ff42c1312 100755 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -18,19 +18,76 @@ #include #include -#define ast_test_flag(p,flag) ((p)->flags & (flag)) - -#define ast_set_flag(p,flag) ((p)->flags |= (flag)) - -#define ast_clear_flag(p,flag) ((p)->flags &= ~(flag)) - -#define ast_copy_flags(dest,src,flagz) do { (dest)->flags &= ~(flagz); \ - (dest)->flags |= ((src)->flags & (flagz)); } while(0) - -#define ast_set2_flag(p,value,flag) ((value) ? ast_set_flag(p,flag) : ast_clear_flag(p,flag)) +/* Note: + It is very important to use only unsigned variables to hold + bit flags, as otherwise you can fall prey to the compiler's + sign-extension antics if you try to use the top two bits in + your variable. + + The flag macros below use a set of compiler tricks to verify + that the caller is using an "unsigned int" variable to hold + the flags, and nothing else. If the caller uses any other + type of variable, a warning message similar to this: + + warning: comparison of distinct pointer types lacks cast + + will be generated. + + The "dummy" variable below is used to make these comparisons. + + Also note that at -O2 or above, this type-safety checking + does _not_ produce any additional object code at all. +*/ + +extern unsigned int __unsigned_int_flags_dummy; + +#define ast_test_flag(p,flag) ({ \ + typeof ((p)->flags) __p = (p)->flags; \ + typeof (__unsigned_int_flags_dummy) __x = 0; \ + (void) (&__p == &__x); \ + ((p)->flags & (flag)); \ + }) + +#define ast_set_flag(p,flag) do { \ + typeof ((p)->flags) __p = (p)->flags; \ + typeof (__unsigned_int_flags_dummy) __x = 0; \ + (void) (&__p == &__x); \ + ((p)->flags |= (flag)); \ + } while(0) + +#define ast_clear_flag(p,flag) do { \ + typeof ((p)->flags) __p = (p)->flags; \ + typeof (__unsigned_int_flags_dummy) __x = 0; \ + (void) (&__p == &__x); \ + ((p)->flags &= ~(flag)); \ + } while(0) + +#define ast_copy_flags(dest,src,flagz) do { \ + typeof ((dest)->flags) __d = (dest)->flags; \ + typeof ((src)->flags) __s = (src)->flags; \ + typeof (__unsigned_int_flags_dummy) __x = 0; \ + (void) (&__d == &__x); \ + (void) (&__s == &__x); \ + (dest)->flags &= ~(flagz); \ + (dest)->flags |= ((src)->flags & (flagz)); \ + } while (0) + +#define ast_set2_flag(p,value,flag) do { \ + typeof ((p)->flags) __p = (p)->flags; \ + typeof (__unsigned_int_flags_dummy) __x = 0; \ + (void) (&__p == &__x); \ + if (value) \ + (p)->flags |= (flag); \ + else \ + (p)->flags &= ~(flag); \ + } while (0) #define AST_FLAGS_ALL UINT_MAX +struct ast_flags { + unsigned int flags; +}; + static inline int ast_strlen_zero(const char *s) { return (*s == '\0'); @@ -41,10 +98,6 @@ struct ast_hostent { char buf[1024]; }; -struct ast_flags { - unsigned int flags; -}; - extern char *ast_strip(char *buf); extern struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp); extern int ast_base64encode(char *dst, unsigned char *src, int srclen, int max); -- cgit v1.2.3