diff mbox

[4/5] fix checking of overlapping initializer

Message ID 20170222153006.3035-5-luc.vanoostenryck@gmail.com (mailing list archive)
State Mainlined, archived
Headers show

Commit Message

Luc Van Oostenryck Feb. 22, 2017, 3:30 p.m. UTC
The current routine checking if some initializers overlap with each
others only check the offset of the initialierd fields, not taking
in account that array elements can be initialized by range with the
'[a ... b]' notation.

Fix this by changing the check so that now we compare the offset of
the current field with the end of the previous one.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 expand.c                    | 25 +++++++++++++++++++++++--
 validation/field-override.c |  1 -
 2 files changed, 23 insertions(+), 3 deletions(-)
diff mbox

Patch

diff --git a/expand.c b/expand.c
index 48cfa33d8..80699c4d6 100644
--- a/expand.c
+++ b/expand.c
@@ -896,6 +896,20 @@  static unsigned long bit_offset(const struct expression *expr)
 	return offset;
 }
 
+static unsigned long bit_range(const struct expression *expr)
+{
+	unsigned long range = 0;
+	unsigned long size = 0;
+	while (expr->type == EXPR_POS) {
+		unsigned long nr = expr->init_nr;
+		size = expr->ctype->bit_size;
+		range += (nr - 1) * size;
+		expr = expr->init_expr;
+	}
+	range += size;
+	return range;
+}
+
 static int compare_expressions(const void *_a, const void *_b)
 {
 	const struct expression *a = _a;
@@ -914,21 +928,28 @@  static void sort_expression_list(struct expression_list **list)
 static void verify_nonoverlapping(struct expression_list **list)
 {
 	struct expression *a = NULL;
+	unsigned long max = 0;
 	struct expression *b;
 
 	if (!Woverride_init)
 		return;
 
 	FOR_EACH_PTR(*list, b) {
+		unsigned long off, end;
 		if (!b->ctype || !b->ctype->bit_size)
 			continue;
-		if (a && bit_offset(a) == bit_offset(b)) {
+		off = bit_offset(b);
+		if (a && off < max) {
 			warning(a->pos, "Initializer entry defined twice");
 			info(b->pos, "  also defined here");
 			if (!Woverride_init_all)
 				return;
 		}
-		a = b;
+		end = off + bit_range(b);
+		if (end > max) {
+			max = end;
+			a = b;
+		}
 	} END_FOR_EACH_PTR(b);
 }
 
diff --git a/validation/field-override.c b/validation/field-override.c
index cae30b4a2..5b77af73e 100644
--- a/validation/field-override.c
+++ b/validation/field-override.c
@@ -69,7 +69,6 @@  static struct s b[2] = {
 /*
  * check-name: field-override
  * check-command: sparse -Woverride-init -Woverride-init-all $file
- * check-known-to-fail
  *
  * check-error-start
 field-override.c:2:10: warning: Initializer entry defined twice