diff options
| -rw-r--r-- | lib.c | 2 | ||||
| -rw-r--r-- | lib.h | 1 | ||||
| -rw-r--r-- | sparse.c | 33 | ||||
| -rw-r--r-- | validation/compound-sizes.c | 88 |
4 files changed, 124 insertions, 0 deletions
@@ -259,6 +259,7 @@ int dump_macro_defs = 0; int dbg_entry = 0; int dbg_dead = 0; +int dbg_compound = 0; unsigned long fdump_ir; int fmem_report = 0; @@ -719,6 +720,7 @@ static char **handle_switch_W(char *arg, char **next) static struct flag debugs[] = { { "entry", &dbg_entry}, { "dead", &dbg_dead}, + { "compound", &dbg_compound}, }; @@ -168,6 +168,7 @@ extern int dump_macro_defs; extern int dbg_entry; extern int dbg_dead; +extern int dbg_compound; extern unsigned int fmax_warnings; extern int fmem_report; @@ -272,6 +272,37 @@ static void check_context(struct entrypoint *ep) check_bb_context(ep, ep->entry->bb, in_context, out_context); } +/* list_compound_symbol - symbol info for arrays, structures, unions */ +static void list_compound_symbol(struct symbol *sym) +{ + struct symbol *base; + + /* Only show symbols that have a positive size */ + if (sym->bit_size <= 0) + return; + if (!sym->ctype.base_type) + return; + /* Don't show unnamed types */ + if (!sym->ident) + return; + + if (sym->type == SYM_NODE) + base = sym->ctype.base_type; + else + base = sym; + switch (base->type) { + case SYM_STRUCT: case SYM_UNION: case SYM_ARRAY: + break; + default: + return; + } + + info(sym->pos, "%s: compound size %u, alignment %lu", + show_typename(sym), + bits_to_bytes(sym->bit_size), + sym->ctype.alignment); +} + static void check_symbols(struct symbol_list *list) { struct symbol *sym; @@ -287,6 +318,8 @@ static void check_symbols(struct symbol_list *list) check_context(ep); } + if (dbg_compound) + list_compound_symbol(sym); } END_FOR_EACH_PTR(sym); if (Wsparse_error && die_if_error) diff --git a/validation/compound-sizes.c b/validation/compound-sizes.c new file mode 100644 index 00000000..d8ccf605 --- /dev/null +++ b/validation/compound-sizes.c @@ -0,0 +1,88 @@ +// This tests sparse "-vcompound" output. +#define NULL ((void*)0) +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +// Do not list functions. +static int do_nothing(void) +{} + +// no: +static inline int zero(void) +{ + return 0 / 1; +} + +// no: +struct inventory { + unsigned char description[64]; + unsigned char department[64]; + uint32_t dept_number; + uint32_t item_cost; + uint64_t stock_number; + uint32_t tally[12]; // per month +}; + +// no +static struct inventory *get_inv(uint64_t stocknum) +{ + return NULL; +} + +// no +union un { + struct inventory inv; + unsigned char bytes[0]; +}; + +// yes +static union un un; + +// yes +static struct inventory inven[100]; + +// no +typedef struct inventory inventory_t; + +// no +static struct inventory *invptr; + +// yes +static inventory_t invent[10]; + +// no +static float floater; +static double double_float; + +// yes +static float floats[42]; +static double doubles[84]; + +// no +int main(void) +{ + // no, these are not global. + struct inventory inv[10]; + inventory_t invt[10]; + // what about statics? + static struct inventory invtop; + static inventory_t inv_top; + static uint64_t stocknums[100]; + + invptr = get_inv(42000); + return 0; +} + +/* + * check-name: compound-sizes + * check-command: sparse -vcompound $file + * check-assert: _Alignof(long long) == 8 + * + * check-error-start +compound-sizes.c:39:17: union un static [toplevel] un: compound size 192, alignment 8 +compound-sizes.c:42:25: struct inventory static [toplevel] inven[100]: compound size 19200, alignment 8 +compound-sizes.c:51:33: struct inventory static [toplevel] [usertype] invent[10]: compound size 1920, alignment 8 +compound-sizes.c:58:25: float static [toplevel] floats[42]: compound size 168, alignment 4 +compound-sizes.c:59:25: double static [toplevel] doubles[84]: compound size 672, alignment 8 + * check-error-end + */ |
