diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-12-05 03:36:57 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-12-10 23:26:23 +0100 |
commit | 706254f20d357735884c5e7b78c03d49bcad9cd3 (patch) | |
tree | 8081897f6f9a7f59fe3e66f5e97d20b03442c3e6 | |
parent | c0123a2f917241e52c5844655abbd83f56ff1017 (diff) | |
download | sparse-706254f20d357735884c5e7b78c03d49bcad9cd3.tar.gz |
fix expansion of initializer (default)
Currently, constant_symbol_value() is doing the expansion
of a constant initializer when an explicit one is found
but nothing is done if the initilizer is an implicit one.
Fix this by:
* adding an helper to lookup the corresponding type from
offset;
* using this helper to get the correct kind for the value:
- a 0-valued EXPR_VALUE for integers
- a 0.0-valued EXPR_FVALUE for floats.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | expand.c | 65 | ||||
-rw-r--r-- | validation/expand/default-init-struct.c | 1 |
2 files changed, 63 insertions, 3 deletions
@@ -621,6 +621,66 @@ static int expand_addressof(struct expression *expr) return expand_expression(expr->unop); } +/// +// lookup the type of a struct's memeber at the requested offset +static struct symbol *find_member(struct symbol *sym, int offset) +{ + struct ptr_list *head, *list; + + head = (struct ptr_list *) sym->symbol_list; + list = head; + if (!head) + return NULL; + do { + int nr = list->nr; + int i; + for (i = 0; i < nr; i++) { + struct symbol *ent = (struct symbol *) list->list[i]; + int curr = ent->offset; + if (curr == offset) + return ent; + if (curr > offset) + return NULL; + } + } while ((list = list->next) != head); + return NULL; +} + +/// +// lookup a suitable default initializer value at the requested offset +static struct expression *default_initializer(struct symbol *sym, int offset) +{ + static struct expression value; + struct symbol *type; + +redo: + switch (sym->type) { + case SYM_NODE: + sym = sym->ctype.base_type; + goto redo; + case SYM_STRUCT: + type = find_member(sym, offset); + if (!type) + return NULL; + break; + case SYM_ARRAY: + type = sym->ctype.base_type; + break; + default: + return NULL; + } + + if (is_integral_type(type)) + value.type = EXPR_VALUE; + else if (is_float_type(type)) + value.type = EXPR_FVALUE; + else + return NULL; + + value.ctype = type; + return &value; +} + /* * Look up a trustable initializer value at the requested offset. * @@ -646,10 +706,11 @@ static struct expression *constant_symbol_value(struct symbol *sym, int offset) if (entry->init_offset < offset) continue; if (entry->init_offset > offset) - return NULL; + break; return entry->init_expr; } END_FOR_EACH_PTR(entry); - return NULL; + + value = default_initializer(sym, offset); } return value; } diff --git a/validation/expand/default-init-struct.c b/validation/expand/default-init-struct.c index c843a1ab..085dd2d6 100644 --- a/validation/expand/default-init-struct.c +++ b/validation/expand/default-init-struct.c @@ -15,7 +15,6 @@ int test_struct(void) /* * check-name: default-init-struct * check-command: test-linearize -Wno-decl -fdump-ir $file - * check-known-to-fail * * check-output-ignore * check-output-contains: phisrc\\..*return.*\\$0 |