widl: Create exactly one type_t object per named union type.

Based on a patch by Richard Pospesel.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-08-19 21:17:38 -05:00 committed by Alexandre Julliard
parent 42321d7a11
commit 833639bd09
3 changed files with 41 additions and 61 deletions

View File

@ -50,10 +50,6 @@ struct _import_t
int import_performed;
};
typelist_t incomplete_types = LIST_INIT(incomplete_types);
static void fix_incomplete_types(type_t *complete_type);
static str_list_t *append_str(str_list_t *list, char *str);
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
@ -1880,41 +1876,9 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in
nt->t = t;
nt->next = namespace->type_hash[hash];
namespace->type_hash[hash] = nt;
if ((t == tsUNION))
fix_incomplete_types(type);
return type;
}
static int is_incomplete(const type_t *t)
{
return !t->defined &&
(type_get_type_detect_alias(t) == TYPE_STRUCT ||
type_get_type_detect_alias(t) == TYPE_UNION ||
type_get_type_detect_alias(t) == TYPE_ENCAPSULATED_UNION);
}
void add_incomplete(type_t *t)
{
struct typenode *tn = xmalloc(sizeof *tn);
tn->type = t;
list_add_tail(&incomplete_types, &tn->entry);
}
static void fix_incomplete_types(type_t *complete_type)
{
struct typenode *tn, *next;
LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry)
{
if (type_is_equal(complete_type, tn->type))
{
tn->type->details.structure = complete_type->details.structure;
list_remove(&tn->entry);
free(tn);
}
}
}
static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs)
{
declarator_t *decl;
@ -1966,8 +1930,6 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
cur = type_new_alias(&name->declspec, name->name);
cur->attrs = attrs;
if (is_incomplete(cur))
add_incomplete(cur);
reg_type(cur, cur->name, current_namespace, 0);
}
}

View File

@ -283,8 +283,6 @@ type_t *type_new_enum(const char *name, struct namespace *namespace, int defined
{
if (defined)
reg_type(t, name, namespace, tsENUM);
else
add_incomplete(t);
}
return t;
}
@ -317,36 +315,57 @@ type_t *type_new_struct(char *name, struct namespace *namespace, int defined, va
type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields)
{
type_t *tag_type = name ? find_type(name, NULL, tsUNION) : NULL;
type_t *t = make_type(TYPE_UNION);
type_t *t = NULL;
if (name)
t = find_type(name, NULL, tsUNION);
if (!t)
{
t = make_type(TYPE_UNION);
t->name = name;
if (tag_type && tag_type->details.structure)
t->details.structure = tag_type->details.structure;
else if (defined)
if (name)
reg_type(t, name, NULL, tsUNION);
}
if (!t->defined && defined)
{
t->details.structure = xmalloc(sizeof(*t->details.structure));
t->details.structure->fields = fields;
t->defined = TRUE;
}
if (name)
{
if (defined)
reg_type(t, name, NULL, tsUNION);
else
add_incomplete(t);
}
return t;
}
type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases)
{
type_t *t = get_type(TYPE_ENCAPSULATED_UNION, name, NULL, tsUNION);
if (!union_field) union_field = make_var( xstrdup("tagged_union") );
type_t *t = NULL;
if (name)
t = find_type(name, NULL, tsUNION);
if (!t)
{
t = make_type(TYPE_ENCAPSULATED_UNION);
t->name = name;
if (name)
reg_type(t, name, NULL, tsUNION);
}
t->type_type = TYPE_ENCAPSULATED_UNION;
if (!t->defined)
{
if (!union_field)
union_field = make_var(xstrdup("tagged_union"));
union_field->declspec.type = type_new_nonencapsulated_union(NULL, TRUE, cases);
t->details.structure = xmalloc(sizeof(*t->details.structure));
t->details.structure->fields = append_var(NULL, switch_field);
t->details.structure->fields = append_var(t->details.structure->fields, union_field);
t->defined = TRUE;
}
return t;
}

View File

@ -596,7 +596,6 @@ type_t *find_type(const char *name, struct namespace *namespace, int t);
type_t *make_type(enum type_type type);
type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t);
type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, int t);
void add_incomplete(type_t *t);
var_t *make_var(char *name);
var_list_t *append_var(var_list_t *list, var_t *var);