widl: Track whether the type has been defined yet in the statement_t and var_t structures.

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>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-08-19 21:17:36 -05:00 committed by Alexandre Julliard
parent 5ea3a044b8
commit 55234f65a8
3 changed files with 29 additions and 21 deletions

View File

@ -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:

View File

@ -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 )
{

View File

@ -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 {