Sparse will warn on casts removing the address space of a pointer if the destination type is not unsigned long. But the type 'uintptr_t' should be more suited for this. So, also accept casts of address-space qualified pointers to uintptr_t. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- evaluate.c | 2 +- validation/cast-from-as.c | 60 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 validation/cast-from-as.c diff --git a/evaluate.c b/evaluate.c index 7c63d788e..d9cd41d1f 100644 --- a/evaluate.c +++ b/evaluate.c @@ -3022,7 +3022,7 @@ static struct symbol *evaluate_cast(struct expression *expr) tas = ttype->ctype.as; } - if (stype == &ulong_ctype && !Wcast_from_as) + if ((stype == &ulong_ctype || stype == uintptr_ctype) && !Wcast_from_as) sas = &bad_address_space; else if (sclass == TYPE_PTR) { examine_pointer_target(stype); diff --git a/validation/cast-from-as.c b/validation/cast-from-as.c new file mode 100644 index 000000000..8dda83ea5 --- /dev/null +++ b/validation/cast-from-as.c @@ -0,0 +1,60 @@ + +#define __kernel __attribute__((address_space(0))) +#define __user __attribute__((address_space(__user))) +#define __iomem __attribute__((address_space(__iomem))) +#define __percpu __attribute__((address_space(__percpu))) +#define __rcu __attribute__((address_space(__rcu))) + + +typedef struct s obj_t; + +static void expl(obj_t __kernel *k, obj_t __iomem *o, + obj_t __user *p, obj_t __percpu *pc, + obj_t __rcu *r) +{ + (__UINTPTR_TYPE__)(k); // OK + (unsigned long)(k); // OK + (void *)(k); // OK + (obj_t*)(k); // OK + (obj_t __kernel*)(k); // OK + + (__UINTPTR_TYPE__)(o); // OK + (unsigned long)(o); // OK + (void *)(o); + (obj_t*)(o); + (obj_t __iomem*)(o); // OK + + (__UINTPTR_TYPE__)(p); // OK + (unsigned long)(p); // OK + (void *)(p); + (obj_t*)(p); + (obj_t __user*)(p); // OK + + (__UINTPTR_TYPE__)(pc); // OK + (unsigned long)(pc); // OK + (void *)(pc); + (obj_t*)(pc); + (obj_t __percpu*)(pc); // OK + + (__UINTPTR_TYPE__)(r); // OK + (unsigned long)(r); // OK + (void *)(r); + (obj_t*)(r); + (obj_t __rcu*)(r); // OK +} + +/* + * check-name: cast-from-as + * check-command: sparse -Wno-cast-from-as $file + * + * check-error-start +cast-from-as.c:23:10: warning: cast removes address space '__iomem' of expression +cast-from-as.c:24:10: warning: cast removes address space '__iomem' of expression +cast-from-as.c:29:10: warning: cast removes address space '__user' of expression +cast-from-as.c:30:10: warning: cast removes address space '__user' of expression +cast-from-as.c:35:10: warning: cast removes address space '__percpu' of expression +cast-from-as.c:36:10: warning: cast removes address space '__percpu' of expression +cast-from-as.c:41:10: warning: cast removes address space '__rcu' of expression +cast-from-as.c:42:10: warning: cast removes address space '__rcu' of expression + * check-error-end + */ -- 2.21.0