+ psi_sort_struct_args((void **) s->args->args, s->args->count);
+
+ if (s->args->count) {
+ decl_arg *darg = s->args->args[s->args->count-1];
+
+ size = darg->layout->pos + darg->layout->len;
+ if (s->size < size) {
+ s->size = psi_align(size, s->align);
+ }
+ }
+
+ return 1;
+}
+
+static inline int validate_decl_union(PSI_Data *data, decl_union *u) {
+ size_t i, pos, len, size, align;
+
+ if (!u->size && !u->args->count) {
+ data->error(u->token, PSI_WARNING,
+ "Cannot compute size of empty union %s",
+ u->name);
+ return 0;
+ }
+
+ for (i = 0; i < u->args->count; ++i) {
+ decl_arg *darg = u->args->args[i];
+
+ if (!validate_decl_arg(data, darg)) {
+ return 0;
+ }
+
+ ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
+ darg->var->arg = darg;
+
+ if (darg->layout) {
+ pos = darg->layout->pos;
+
+ align = align_decl_arg(darg, &pos, &len);
+
+ if (darg->layout->pos != 0) {
+ data->error(darg->token, PSI_WARNING,
+ "Offset of %s.%s must be 0",
+ u->name, darg->var->name);
+ return 0;
+ }
+ if (darg->layout->len != len) {
+ data->error(darg->token, PSI_WARNING,
+ "Computed size %zu of %s.%s does not match"
+ " pre-defined size %zu of type '%s'",
+ darg->layout->len, u->name, darg->var->name, size,
+ darg->type->name);
+ return 0;