harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/type_store.c | 7+++++--
Mtests/06-structs.ha | 2++
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 {