Currently when we use typeof() all the modifiers from the source type are ignored and thus not present in the resulting type. This give all sort of problems. One simple example is: const int obj; typeof(obj) *ptr; *ptr = 0; We can expect that 'ptr' will have the type 'const int *' and thus that sparse will warn on the assignment in the last line but it's not case because 'ptr' has in fact the type 'int *'. The patch fix this by preserving some of the modifiers when using typeof(). WARNING: it may be that the old behaviour was so more or less on purpose as it provide a way to remove some modifiers by casting while still being able to use generic macros. For exmaple, it was possible to write the following macro: #define noconst(x) (typeof(x)) and use 'noconst()' as a cast to remove 'const' from types. Of course, the problem with this macros is that it remove *all* modifiers, not only 'const'. With the patch, it won't be possible anymore to do this sort of things, which maybe is fine for 'const' but it's why MOD_NOREFREF is still dropped as it create problems in the Linew kernel, for example in the macro to convert back a percpu variable into a plain one. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- symbol.c | 8 ++++++-- symbol.h | 2 ++ validation/typeof-mods.c | 1 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/symbol.c b/symbol.c index 92a7a625..a65ad17b 100644 --- a/symbol.c +++ b/symbol.c @@ -466,12 +466,16 @@ struct symbol *examine_symbol_type(struct symbol * sym) case SYM_TYPEOF: { struct symbol *base = evaluate_expression(sym->initializer); if (base) { + unsigned long mod = 0; + if (is_bitfield_type(base)) warning(base->pos, "typeof applied to bitfield type"); - if (base->type == SYM_NODE) + if (base->type == SYM_NODE) { + mod |= base->ctype.modifiers & MOD_TYPEOF; base = base->ctype.base_type; + } sym->type = SYM_NODE; - sym->ctype.modifiers = 0; + sym->ctype.modifiers = mod; sym->ctype.base_type = base; return examine_node_type(sym); } diff --git a/symbol.h b/symbol.h index afc4e232..51be81fb 100644 --- a/symbol.h +++ b/symbol.h @@ -248,6 +248,8 @@ struct symbol { #define MOD_IGNORE (MOD_TOPLEVEL | MOD_STORAGE | MOD_ADDRESSABLE | \ MOD_ASSIGNED | MOD_USERTYPE | MOD_ACCESSED | MOD_EXPLICITLY_SIGNED) #define MOD_PTRINHERIT (MOD_VOLATILE | MOD_CONST | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST) +/* modifiers preserved by typeof() operator */ +#define MOD_TYPEOF (MOD_VOLATILE | MOD_CONST | MOD_NOCAST | MOD_SPECIFIER) /* Current parsing/evaluation function */ diff --git a/validation/typeof-mods.c b/validation/typeof-mods.c index 8c98ab8c..9822e96f 100644 --- a/validation/typeof-mods.c +++ b/validation/typeof-mods.c @@ -102,7 +102,6 @@ static void test_nocast(void) /* * check-name: typeof-mods - * check-known-to-fail * * check-error-start * check-error-end -- 2.10.2 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html