commit a87c174a1935f60e917f77c22d9c2cb7202b9088
parent aeaef421d1e340ef046bd22afad34a16a1c1b107
Author: Eyal Sawady <ecs@d2evs.net>
Date: Sat, 23 Oct 2021 05:35:41 +0000
shift_fields: fix embedded structs/union offsets
Previously, we didn't add the parent's offset when the child didn't have
a name, causing the child to continue having an offset of 0. In
addition, we added the child's offset before recursively calling
shift_fields, leading to the child's offset being applied to its
grandchildren twice.
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/type_store.c b/src/type_store.c
@@ -259,13 +259,16 @@ shift_fields(struct type_store *store, struct struct_field *parent)
xcalloc(1, sizeof(struct struct_field));
next = &new->next;
new->type = field->type;
- new->offset = field->offset;
+ new->offset = parent->offset;
if (field->name) {
new->name = strdup(field->name);
- new->offset += parent->offset;
} else {
shift_fields(store, new);
}
+ // Sub-subfields are shifted by field->offset in the recursive
+ // shift_fields call, delay adding it to new->offset to avoid
+ // shifting by field->offset twice
+ new->offset += field->offset;
}
parent->type = type_store_lookup_type(store, &new);
diff --git a/tests/06-structs.ha b/tests/06-structs.ha
@@ -71,12 +71,14 @@ fn nested() void = {
bar = 69,
baz = 1337,
};
+ assert(offset(s.foo) == 0 && offset(s.bar) == 8 && offset(s.baz) == 16);
assert(s.foo == 42 && s.bar == 69 && s.baz == 1337);
let s = embed2 {
foo = 42,
bar = 69,
baz = 1337,
};
+ assert(offset(s.bar) == 0 && offset(s.baz) == 8 && offset(s.foo) == 16);
assert(s.foo == 42 && s.bar == 69 && s.baz == 1337);
let s = struct {