On Mon, Oct 05, 2020 at 10:04:43AM +0100, Ben Dooks wrote: > On 05/10/2020 02:59, Luc Van Oostenryck wrote: > > Ben, these are small changes I think should be applied with > > your series, on top of the patches I send yesterday. > > I've pushed everything at: > > git://github.com/lucvoo/sparse-dev.git format-check > > If you're fine with these, I can squeeze them with the series. > > > > There are also a few tests I don't agree with: > > const void *ptr = ... > > printf("%s", ptr); > > These tests silently accept this, but they should warn. > > But this can be fixed at a later step. > > ok, thanks. Hi, I've now pushed it on a separate branch on the official tree: git://git.kernel.org/pub/scm/devel/sparse/sparse.git format-check It will thus not be rebased anymore and any changes will need to be incrementally on top of it. > I'm going to try and work out the best way to deal with the kernel > extra funsies. I have a few ideas but yet to make a coherent document > about them. Well, the reason I've not yet merged it with the main branch is because enabling -Wformat creates really a lot of warnings in the kernel and people definitively use this. Most of these warnings (if not all) is caused by using check_assignment_types() which was good as a quick & dirty solution in the early stages but isn't at all adequate as a true solution and this for several reasons. I've also begin to take a look at this with a relatively satisfying result by adopting the following strategy: Since no 'checking' function in evaluate.c has the needed characteristics, simplest is to create in verify-format.c what is needed. This also gives the flexibility needed to support things like -Wformat-signedness. I add here below only small extract because it's for now quite messy and need quite a bit of polishing. -- Luc enum { CLASS_OTHER, CLASS_INT, CLASS_BITWISE, CLASS_FLOAT, CLASS_PTR, }; /// // retrieve a 'type class' for quick testing and extract the base type static int type_class(struct symbol *type, struct symbol **base) { if (type->type == SYM_NODE) type = type->ctype.base_type; if (type->type == SYM_ENUM) type = type->ctype.base_type; *base = type; if (type->type == SYM_BASETYPE) { struct symbol *kind = type->ctype.base_type; if (kind == &int_type) return CLASS_INT; if (kind == &fp_type) return CLASS_FLOAT; } if (type->type == SYM_PTR) return CLASS_PTR; if (type->type == SYM_RESTRICT) return CLASS_BITWISE; return CLASS_OTHER; } static const char *printf_fmt_flt(struct format_type *fmt, struct symbol *source) { const char *typediff = "different base types"; struct symbol *target = fmt->type; struct symbol *base; if (type_class(source, &base) != CLASS_FLOAT) return typediff; if (base == target) return NULL; return typediff; } static const char *printf_fmt_string(struct format_type *fmt, struct symbol *source) { const char *typediff = "different base types"; struct symbol *target = fmt->type; examine_pointer_target(target); examine_pointer_target(source); if (type_class(source, &source) != CLASS_PTR) return typediff; if (source->ctype.as) return "different address spaces"; // get the base type type_class(source->ctype.base_type, &source); type_class(source, &source); if (target == &const_string_ctype) { if (source == &char_ctype) return NULL; if (source == &uchar_ctype) return NULL; if (source == &schar_ctype) return NULL; } if (target == &const_wstring_ctype) { if (source == wchar_ctype) return NULL; } return typediff; }