- #ifdef HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
psi_sort_struct_arg_cmp, psi_sort_struct_arg_swp);
}
-static inline int validate_decl_struct_darg(PSI_Data *data, decl_arg *darg) {
+static inline int validate_decl_struct_darg(PSI_Data *data, decl_arg *darg, void *current) {
decl_type *real = real_decl_type(darg->type);
/* pre-validate any structs/unions/enums */
switch (real->type) {
case PSI_T_STRUCT:
+ if (current && current == real->strct) {
+ return 1;
+ }
if (!validate_decl_struct(data, real->strct)) {
return 0;
}
break;
case PSI_T_UNION:
+ if (current && current == real->unn) {
+ return 1;
+ }
if (!validate_decl_union(data, real->unn)) {
return 0;
}
break;
case PSI_T_ENUM:
+ if (current && current == real->enm) {
+ return 1;
+ }
if (!validate_decl_enum(data, real->enm)) {
return 0;
}
}
}
+ ZEND_ASSERT(size);
+
return size;
}
-static inline size_t align_decl_arg(decl_arg *darg, size_t *pos, size_t *len) {
+static inline size_t alignof_decl_type(decl_type *t);
+static inline size_t alignof_decl_arg(decl_arg *darg);
+static inline size_t alignof_decl_union(decl_union *u);
+static inline size_t alignof_decl_struct(decl_struct *s);
+
+static inline size_t alignof_decl_args(decl_args *args) {
+ size_t i, maxalign = 0;
+
+ for (i = 0; i < args->count; ++i) {
+ decl_arg *darg = args->args[i];
+ size_t align = alignof_decl_arg(darg);
+
+ if (align > maxalign) {
+ maxalign = align;
+ }
+ }
+
+ return maxalign;
+}
+
+static inline size_t alignof_decl_struct(decl_struct *s) {
+ if (!s->align) {
+ s->align = alignof_decl_args(s->args);
+ }
+ return s->align;
+}
+
+static inline size_t alignof_decl_union(decl_union *u) {
+ if (!u->align) {
+ u->align = alignof_decl_args(u->args);
+ }
+ return u->align;
+}
+
+static inline size_t alignof_decl_type(decl_type *t) {
+ decl_type *real = real_decl_type(t);
+ size_t align;
+
+ switch (real->type) {
+ case PSI_T_STRUCT:
+ align = alignof_decl_struct(real->strct);
+ break;
+ case PSI_T_UNION:
+ align = alignof_decl_union(real->unn);
+ break;
+ case PSI_T_ENUM:
+ default:
+ align = psi_t_alignment(real->type);
+ }
+
+ return align;
+}
+
+static inline size_t alignof_decl_arg(decl_arg *darg) {
size_t align;
if (darg->var->pointer_level && (!darg->var->array_size || darg->var->pointer_level > 2)) {
align = psi_t_alignment(PSI_T_POINTER);
} else {
- decl_type *real = real_decl_type(darg->type);
-
- switch (real->type) {
- case PSI_T_STRUCT:
- align = real->strct->align;
- break;
- case PSI_T_UNION:
- align = real->unn->align;
- break;
- default:
- align = psi_t_alignment(real->type);
- break;
- }
+ align = alignof_decl_type(darg->type);
}
+ return align;
+}
+
+static inline size_t align_decl_arg(decl_arg *darg, size_t *pos, size_t *len) {
+ size_t align = alignof_decl_arg(darg);
+
+ ZEND_ASSERT(align);
+
*len = sizeof_decl_arg(darg);
*pos = psi_align(align, *pos);
ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
darg->var->arg = darg;
- if (darg->layout) {
+ if (!validate_decl_struct_darg(data, darg, s)) {
+ return 0;
+ } else if (darg->layout) {
pos = darg->layout->pos;
align = align_decl_arg(darg, &pos, &len);
data->error(data, darg->token, PSI_WARNING,
"Computed size %zu of %s.%s does not match"
" pre-defined size %zu of type '%s'",
- darg->layout->len, s->name, darg->var->name, len,
+ len, s->name, darg->var->name, darg->layout->len,
darg->type->name);
- return 0;
}
if (darg->layout->pos != pos) {
data->error(data, darg->token, PSI_WARNING,
"Computed offset %zu of %s.%s does not match"
" pre-defined offset %zu",
- darg->layout->len, s->name, darg->var->name, len);
- return 0;
+ pos, s->name, darg->var->name, darg->layout->pos);
}
- } else if (!validate_decl_struct_darg(data, darg)) {
- return 0;
- } else {
+ } else {
if (i) {
pos = s->args->args[i-1]->layout->pos +
s->args->args[i-1]->layout->len;
}
static inline int validate_decl_union(PSI_Data *data, decl_union *u) {
- size_t i, pos, len, size, align;
+ size_t i, pos, len, size = 0, align;
if (!u->size && !u->args->count) {
data->error(data, u->token, PSI_WARNING,
ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
darg->var->arg = darg;
- if (darg->layout) {
+ if (!validate_decl_struct_darg(data, darg, u)) {
+ return 0;
+ } else if (darg->layout) {
pos = darg->layout->pos;
align = align_decl_arg(darg, &pos, &len);
if (darg->layout->pos != 0) {
data->error(data, darg->token, PSI_WARNING,
- "Offset of %s.%s must be 0",
+ "Offset of %s.%s should be 0",
u->name, darg->var->name);
- return 0;
+ darg->layout->pos = 0;
}
if (darg->layout->len != len) {
data->error(data, 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,
+ len, u->name, darg->var->name, darg->layout->len,
darg->type->name);
- return 0;
}
- } else if (!validate_decl_struct_darg(data, darg)) {
- return 0;
} else {
pos = 0;
size_t i, count = C->count++, check_round, check_count;
decl_typedefs *check_defs = P->defs;
decl_structs *check_structs = P->structs;
+ decl_unions *check_unions = P->unions;
decl_enums *check_enums = P->enums;
unsigned silent = C->flags & PSI_PARSER_SILENT;
for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
decl_typedefs *recheck_defs = NULL;
decl_structs *recheck_structs = NULL;
+ decl_unions *recheck_unions = NULL;
decl_enums *recheck_enums = NULL;
check_count = CHECK_TOTAL;
recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]);
}
}
+ for (i = 0; i < CHECK_COUNT(unions); ++i) {
+ if (validate_decl_union(PSI_DATA(C), check_unions->list[i])) {
+ C->unions = add_decl_union(C->unions, check_unions->list[i]);
+ } else {
+ recheck_unions = add_decl_union(recheck_unions, check_unions->list[i]);
+ }
+ }
for (i = 0; i < CHECK_COUNT(enums); ++i) {
if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) {
C->enums = add_decl_enum(C->enums, check_enums->list[i]);
REVALIDATE(defs);
REVALIDATE(structs);
+ REVALIDATE(unions);
REVALIDATE(enums);
if (check_round == 0 && !silent) {