summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-05-03 01:32:46 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-10-05 03:29:19 +0200
commit56a8674803a512f846a059288f3524b2ee7a950f (patch)
tree18d25c988549f59dceb4e5b257c58f800738f952
parentf7117d94e5bab13335a12a6c74fb79c9c4e59c04 (diff)
downloadsparse-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.c7
-rw-r--r--validation/enum-bitwise-mixed.c29
2 files changed, 36 insertions, 0 deletions
diff --git a/parse.c b/parse.c
index 34a70b44..ac8c0aad 100644
--- a/parse.c
+++ b/parse.c
@@ -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
+ */