+/**
+ * Finish the construction of a struct type by calculating
+ * its size, offsets, alignment.
+ */
+static void finish_struct_type(compound_type_t *type) {
+ if (type->declaration == NULL)
+ return;
+ declaration_t *struct_decl = type->declaration;
+ if (! struct_decl->init.complete)
+ return;
+
+ il_size_t size = 0;
+ il_size_t new_size;
+ il_alignment_t alignment = 1;
+ bool need_pad = false;
+
+ declaration_t *entry = struct_decl->scope.declarations;
+ for (; entry != NULL; entry = entry->next) {
+ if (entry->namespc != NAMESPACE_NORMAL)
+ continue;
+
+ type_t *m_type = skip_typeref(entry->type);
+ il_alignment_t m_alignment = m_type->base.alignment;
+
+ new_size = (size + m_alignment - 1) & -m_alignment;
+ if (m_alignment > alignment)
+ alignment = m_alignment;
+ if (new_size > size)
+ need_pad = true;
+ entry->offset = new_size;
+ size = new_size + m_type->base.size;
+ }
+ if (type->base.alignment != 0) {
+ alignment = type->base.alignment;
+ }
+
+ new_size = (size + alignment - 1) & -alignment;
+ if (new_size > size)
+ need_pad = true;
+
+ if (warning.padded && need_pad) {
+ warningf(&struct_decl->source_position,
+ "'%#T' needs padding", type, struct_decl->symbol);
+ }
+ if (warning.packed && !need_pad) {
+ warningf(&struct_decl->source_position,
+ "superfluous packed attribute on '%#T'",
+ type, struct_decl->symbol);
+ }
+
+ type->base.size = new_size;
+ type->base.alignment = alignment;
+}
+
+/**
+ * Finish the construction of an union type by calculating
+ * its size and alignment.
+ */
+static void finish_union_type(compound_type_t *type) {
+ if (type->declaration == NULL)
+ return;
+ declaration_t *union_decl = type->declaration;
+ if (! union_decl->init.complete)
+ return;
+
+ il_size_t size = 0;
+ il_alignment_t alignment = 1;
+
+ declaration_t *entry = union_decl->scope.declarations;
+ for (; entry != NULL; entry = entry->next) {
+ if (entry->namespc != NAMESPACE_NORMAL)
+ continue;
+
+ type_t *m_type = skip_typeref(entry->type);
+
+ entry->offset = 0;
+ if (m_type->base.size > size)
+ size = m_type->base.size;
+ if (m_type->base.alignment > alignment)
+ alignment = m_type->base.alignment;
+ }
+ if (type->base.alignment != 0) {
+ alignment = type->base.alignment;
+ }
+ size = (size + alignment - 1) & -alignment;
+ type->base.size = size;
+ type->base.alignment = alignment;
+}
+