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 {