diff mbox series

[13/17] fix expansion of initializer (default)

Message ID 20191210225921.94897-14-luc.vanoostenryck@gmail.com (mailing list archive)
State Mainlined, archived
Headers show
Series improve expansion of constant symbols | expand

Commit Message

Luc Van Oostenryck Dec. 10, 2019, 10:59 p.m. UTC
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>
---
 expand.c                                | 65 ++++++++++++++++++++++++-
 validation/expand/default-init-struct.c |  1 -
 2 files changed, 63 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/expand.c b/expand.c
index 9ab259b13a82..cd348bf5833e 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 c843a1abb960..085dd2d6dca9 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