Based on a patch by Richard Pospesel.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47149 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- tools/widl/header.c | 37 +++++++++++++++++++------------------ tools/widl/parser.y | 10 +++++++--- tools/widl/widltypes.h | 3 +++ 3 files changed, 29 insertions(+), 21 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index c20fe69917..61fadcf72f 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -43,7 +43,7 @@ user_type_list_t user_type_list = LIST_INIT(user_type_list); context_handle_list_t context_handle_list = LIST_INIT(context_handle_list); generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
-static void write_type_def_or_decl(FILE *f, const decl_spec_t *t, int field, const char *name); +static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name);
static void indent(FILE *h, int delta) { @@ -252,7 +252,7 @@ static void write_fields(FILE *h, var_list_t *fields) default: ; } - write_type_def_or_decl(h, &v->declspec, TRUE, name); + write_type_v(h, &v->declspec, TRUE, v->declonly, name); fprintf(h, ";\n"); } } @@ -328,7 +328,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i else { switch (type_get_type_detect_alias(t)) { case TYPE_ENUM: - if (!declonly && t->defined && !t->written) { + if (!declonly && !t->written) { + assert(t->defined); if (name) fprintf(h, "enum %s {\n", name); else fprintf(h, "enum {\n"); t->written = TRUE; @@ -341,7 +342,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i break; case TYPE_STRUCT: case TYPE_ENCAPSULATED_UNION: - if (!declonly && t->defined && !t->written) { + if (!declonly && !t->written) { + assert(t->defined); if (name) fprintf(h, "struct %s {\n", name); else fprintf(h, "struct {\n"); t->written = TRUE; @@ -356,7 +358,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i else fprintf(h, "struct %s", name ? name : ""); break; case TYPE_UNION: - if (!declonly && t->defined && !t->written) { + if (!declonly && !t->written) { + assert(t->defined); if (t->name) fprintf(h, "union %s {\n", t->name); else fprintf(h, "union {\n"); t->written = TRUE; @@ -547,12 +550,7 @@ static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declo write_type_right(h, t, is_field); }
-static void write_type_def_or_decl(FILE *f, const decl_spec_t *t, int field, const char *name) -{ - write_type_v(f, t, field, FALSE, name); -} - -static void write_type_definition(FILE *f, type_t *t) +static void write_type_definition(FILE *f, type_t *t, int declonly) { int in_namespace = t->namespace && !is_global_namespace(t->namespace); int save_written = t->written; @@ -564,14 +562,14 @@ static void write_type_definition(FILE *f, type_t *t) write_namespace_start(f, t->namespace); } indent(f, 0); - write_type_left(f, &ds, NAME_DEFAULT, FALSE, TRUE); + write_type_left(f, &ds, NAME_DEFAULT, declonly, TRUE); fprintf(f, ";\n"); if(in_namespace) { t->written = save_written; write_namespace_end(f, t->namespace); fprintf(f, "extern "C" {\n"); fprintf(f, "#else\n"); - write_type_left(f, &ds, NAME_C, FALSE, TRUE); + write_type_left(f, &ds, NAME_C, declonly, TRUE); fprintf(f, ";\n"); fprintf(f, "#endif\n\n"); } @@ -805,10 +803,10 @@ static void write_generic_handle_routines(FILE *header) } }
-static void write_typedef(FILE *header, type_t *type) +static void write_typedef(FILE *header, type_t *type, int declonly) { fprintf(header, "typedef "); - write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name); + write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name); fprintf(header, ";\n"); }
@@ -852,7 +850,7 @@ static void write_declaration(FILE *header, const var_t *v) fprintf(header, "extern "); break; } - write_type_def_or_decl(header, &v->declspec, FALSE, v->name); + write_type_v(header, &v->declspec, FALSE, v->declonly, v->name); fprintf(header, ";\n\n"); } } @@ -1092,6 +1090,9 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i } else fprintf(h, ","); } + /* In theory we should be writing the definition using write_type_v(..., arg->declonly), + * but that causes redefinition in e.g. proxy files. In fact MIDL disallows + * defining UDTs inside of an argument list. */ write_type_decl(h, &arg->declspec, arg->name); if (method == 2) { const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE); @@ -1733,7 +1734,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons write_coclass(header, stmt->u.type); else { - write_type_definition(header, stmt->u.type); + write_type_definition(header, stmt->u.type, stmt->declonly); } break; case STMT_TYPEREF: @@ -1754,7 +1755,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons { const type_list_t *type_entry = stmt->u.type_list; for (; type_entry; type_entry = type_entry->next) - write_typedef(header, type_entry->type); + write_typedef(header, type_entry->type, stmt->declonly); break; } case STMT_LIBRARY: diff --git a/tools/widl/parser.y b/tools/widl/parser.y index afbe2b1799..bdbd44040c 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -116,7 +116,7 @@ static statement_t *make_statement_pragma(const char *str); static statement_t *make_statement_cppquote(const char *str); static statement_t *make_statement_importlib(const char *str); static statement_t *make_statement_module(type_t *type); -static statement_t *make_statement_typedef(var_list_t *names); +static statement_t *make_statement_typedef(var_list_t *names, int declonly); static statement_t *make_statement_import(const char *str); static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt); static statement_list_t *append_statements(statement_list_t *, statement_list_t *); @@ -1115,7 +1115,7 @@ type: tVOID { $$ = type_new_void(); } typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list { $1 = append_attribs($1, $3); reg_typedefs($4, $5, check_typedef_attrs($1)); - $$ = make_statement_typedef($5); + $$ = make_statement_typedef($5, !$4->type->defined); } ;
@@ -1546,6 +1546,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator v->declspec.type = decl->type; v->declspec.qualifier = decl->qualifier; v->attrs = attrs; + v->declonly = !type->defined;
if (is_attr(type->attrs, ATTR_CALLCONV) && !is_func(type)) error_loc("calling convention applied to non-function type\n"); @@ -1750,6 +1751,7 @@ var_t *make_var(char *name) v->attrs = NULL; v->eval = NULL; init_loc_info(&v->loc_info); + v->declonly = FALSE; return v; }
@@ -2912,6 +2914,7 @@ static statement_t *make_statement_type_decl(type_t *type) { statement_t *stmt = make_statement(STMT_TYPE); stmt->u.type = type; + stmt->declonly = !type->defined; return stmt; }
@@ -2982,7 +2985,7 @@ static statement_t *make_statement_module(type_t *type) return stmt; }
-static statement_t *make_statement_typedef(declarator_list_t *decls) +static statement_t *make_statement_typedef(declarator_list_t *decls, int declonly) { declarator_t *decl, *next; statement_t *stmt; @@ -2993,6 +2996,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) stmt = make_statement(STMT_TYPEDEF); stmt->u.type_list = NULL; type_list = &stmt->u.type_list; + stmt->declonly = declonly;
LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry ) { diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 3886360bd4..7a7bd8991e 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -478,6 +478,8 @@ struct _var_t {
struct _loc_info_t loc_info;
+ unsigned int declonly : 1; + /* parser-internal */ struct list entry; }; @@ -560,6 +562,7 @@ struct _statement_t { typelib_t *lib; type_list_t *type_list; } u; + unsigned int declonly : 1; /* for STMT_TYPE and STMT_TYPEDEF */ };
struct _warning_t {
Regardless of whether we are writing a typelib.
Based on a patch by Richard Pospesel.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- tools/widl/parser.y | 2 +- tools/widl/typetree.c | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 18 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index bdbd44040c..9db8ebd6fc 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1880,7 +1880,7 @@ 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 == tsSTRUCT || t == tsUNION)) + if ((t == tsUNION)) fix_incomplete_types(type); return type; } diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index a066125b16..05e96844d8 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -291,31 +291,27 @@ type_t *type_new_enum(const char *name, struct namespace *namespace, int defined
type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields) { - type_t *tag_type = name ? find_type(name, namespace, tsSTRUCT) : NULL; - type_t *t; + type_t *t = NULL;
- /* avoid creating duplicate typelib type entries */ - if (tag_type && do_typelib) return tag_type; + if (name) + t = find_type(name, namespace, tsSTRUCT);
- t = make_type(TYPE_STRUCT); - t->name = name; - t->namespace = namespace; + if (!t) + { + t = make_type(TYPE_STRUCT); + t->name = name; + t->namespace = namespace; + if (name) + reg_type(t, name, namespace, tsSTRUCT); + }
- if (tag_type && tag_type->details.structure) - t->details.structure = tag_type->details.structure; - else if (defined) + 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, namespace, tsSTRUCT); - else - add_incomplete(t); - } + return t; }
Based on a patch by Richard Pospesel.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- tools/widl/parser.y | 38 ------------------------- tools/widl/typetree.c | 63 +++++++++++++++++++++++++++--------------- tools/widl/widltypes.h | 1 - 3 files changed, 41 insertions(+), 61 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 9db8ebd6fc..a52afc7921 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -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); } } diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 05e96844d8..a7fd561db8 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -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); - t->name = name; - if (tag_type && tag_type->details.structure) - t->details.structure = tag_type->details.structure; - else if (defined) + type_t *t = NULL; + + if (name) + t = find_type(name, NULL, tsUNION); + + if (!t) + { + t = make_type(TYPE_UNION); + t->name = name; + 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") ); - 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; + 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; }
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 7a7bd8991e..5e28329278 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -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);
Based on a patch by Richard Pospesel.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47035 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- tools/widl/typetree.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index a7fd561db8..faa582034f 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -265,25 +265,27 @@ type_t *type_new_void(void)
type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums) { - type_t *tag_type = name ? find_type(name, namespace, tsENUM) : NULL; - type_t *t = make_type(TYPE_ENUM); - t->name = name; - t->namespace = namespace; - - if (tag_type && tag_type->details.enumeration) - t->details.enumeration = tag_type->details.enumeration; - else if (defined) + type_t *t = NULL; + + if (name) + t = find_type(name, namespace,tsENUM); + + if (!t) + { + t = make_type(TYPE_ENUM); + t->name = name; + t->namespace = namespace; + if (name) + reg_type(t, name, namespace, tsENUM); + } + + if (!t->defined && defined) { t->details.enumeration = xmalloc(sizeof(*t->details.enumeration)); t->details.enumeration->enums = enums; t->defined = TRUE; }
- if (name) - { - if (defined) - reg_type(t, name, namespace, tsENUM); - } return t; }