diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-05-03 01:32:46 +0200 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-10-05 03:29:19 +0200 |
commit | 56a8674803a512f846a059288f3524b2ee7a950f (patch) | |
tree | 18d25c988549f59dceb4e5b257c58f800738f952 | |
parent | f7117d94e5bab13335a12a6c74fb79c9c4e59c04 (diff) | |
download | sparse-56a8674803a512f846a059288f3524b2ee7a950f.tar.gz |
enum: only warn (once) when mixing bitwiseness
As an extension to the standard C types, parse supports bitwise
types (also called 'restricted') which should in no circonstances
mix with other types.
In the kernel, some enums are defined with such bitwise types
as initializers; the goal being to have slightly more strict enums.
While the semantic of such enums is not very clear, using a mix
of bitwise and not-bitwise initializers completely defeats the
desired stricter typing.
Attract some attention to such mixed initialization by issuing
a single warning for each such declarations.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | parse.c | 7 | ||||
-rw-r--r-- | validation/enum-bitwise-mixed.c | 29 |
2 files changed, 36 insertions, 0 deletions
@@ -854,6 +854,7 @@ static struct token *parse_enum_declaration(struct token *token, struct symbol * unsigned long long lastval = 0; struct symbol *ctype = NULL, *base_type = NULL; Num upper = {-1, 0}, lower = {1, 0}; + int mix_bitwise = 0; parent->examined = 1; parent->ctype.base_type = &int_ctype; @@ -915,6 +916,10 @@ static struct token *parse_enum_declaration(struct token *token, struct symbol * /* nothing */ } else if (is_int_type(base_type) && is_int_type(ctype)) { base_type = &int_ctype; + } else if (is_restricted_type(base_type) != is_restricted_type(ctype)) { + if (!mix_bitwise++) { + warning(expr->pos, "mixed bitwiseness"); + } } else base_type = &bad_ctype; parent->ctype.base_type = base_type; @@ -962,6 +967,8 @@ static struct token *parse_enum_declaration(struct token *token, struct symbol * parent->ctype.modifiers |= (base_type->ctype.modifiers & MOD_UNSIGNED); parent->examined = 0; + if (mix_bitwise) + return token; cast_enum_list(parent->symbol_list, base_type); return token; diff --git a/validation/enum-bitwise-mixed.c b/validation/enum-bitwise-mixed.c new file mode 100644 index 00000000..07d77176 --- /dev/null +++ b/validation/enum-bitwise-mixed.c @@ -0,0 +1,29 @@ +#define __bitwise __attribute__((bitwise)) +#define __force __attribute__((force)) + +typedef long long __bitwise bits; + +enum a { + AR = (__force bits) 0, + AP = 0, + AS = (__force bits) 1, + AQ = 1, +}; +_Static_assert(sizeof(AP) == sizeof(int), "is bad?"); + +enum b { + BP = 0, + BR = (__force bits) 0, + BQ = 1, + BS = (__force bits) 1, +}; +_Static_assert(sizeof(BP) == sizeof(int), "is bad?"); + +/* + * check-name: enum-bitwise-mixed + * + * check-error-start +enum-bitwise-mixed.c:8:14: warning: mixed bitwiseness +enum-bitwise-mixed.c:16:15: warning: mixed bitwiseness + * check-error-end + */ |