aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-12-05 03:36:57 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-12-10 23:26:23 +0100
commit706254f20d357735884c5e7b78c03d49bcad9cd3 (patch)
tree8081897f6f9a7f59fe3e66f5e97d20b03442c3e6
parentc0123a2f917241e52c5844655abbd83f56ff1017 (diff)
downloadsparse-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.c65
-rw-r--r--validation/expand/default-init-struct.c1
2 files changed, 63 insertions, 3 deletions
diff --git a/expand.c b/expand.c
index 9ab259b1..cd348bf5 100644
--- a/expand.c
+++ b/expand.c
@@ -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