-- v3: widl: Do not write type definitions for types defined in an imported header. widl: Update the type location in define_type(). widl: Factor out a define_type() helper. widl: Invert "declonly". widl: Allow using UDTs with the keyword even when the identifier is also a typedef.
From: Elizabeth Figura zfigura@codeweavers.com
yyloc is an internal variable; we want to assign to yylloc here.
This fixes error reporting.
Fixes: 3b12583db0cf68b356f20d7bbd091651af246eff --- tools/widl/parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 9b6a4c36732..e5e28fd7b24 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -515,7 +515,7 @@ cppquote: tCPPQUOTE '(' aSTRING ')' { $$ = $3; }
import_start: tIMPORT aSTRING ';' { $$ = $2; push_import( $2, &yylloc ); } ; -import: import_start imp_statements aEOF { yyloc = pop_import(); } +import: import_start imp_statements aEOF { yylloc = pop_import(); } ;
importlib: tIMPORTLIB '(' aSTRING ')'
From: Elizabeth Figura zfigura@codeweavers.com
E.g. in cases like
typedef int apple; struct apple { ... };
allow subsequently using "struct apple" in future expressions. Note that this already worked for UDT definitions (so the above example by itself was legal in widl), but any attempt to use the defined type would result in a syntax error. --- tools/widl/parser.y | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index e5e28fd7b24..097d927dbc2 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -500,11 +500,11 @@ warnings:
typedecl: enumdef - | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } + | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } | structdef - | tSTRUCT aIDENTIFIER { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } + | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } | uniondef - | tUNION aIDENTIFIER { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL); } + | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL); } | attributes enumdef { $$ = $2; $$->attrs = check_enum_attrs($1); } | attributes structdef { $$ = $2; $$->attrs = check_struct_attrs($1); } | attributes uniondef { $$ = $2; $$->attrs = check_union_attrs($1); } @@ -1338,17 +1338,17 @@ structdef: tSTRUCT m_typename '{' fields '}' { $$ = type_new_struct($2, current_ ;
unqualified_type: - tVOID { $$ = type_new_void(); } - | base_type { $$ = $1; } - | enumdef { $$ = $1; } - | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } - | structdef { $$ = $1; } - | tSTRUCT aIDENTIFIER { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } - | uniondef { $$ = $1; } - | tUNION aIDENTIFIER { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL); } - | tSAFEARRAY '(' type ')' { $$ = make_safearray($3); } - | aKNOWNTYPE { $$ = find_type_or_error(current_namespace, $1); } - ; + tVOID { $$ = type_new_void(); } + | base_type { $$ = $1; } + | enumdef { $$ = $1; } + | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } + | structdef { $$ = $1; } + | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } + | uniondef { $$ = $1; } + | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL); } + | tSAFEARRAY '(' type ')' { $$ = make_safearray($3); } + | aKNOWNTYPE { $$ = find_type_or_error(current_namespace, $1); } + ;
type: unqualified_type
From: Elizabeth Figura zfigura@codeweavers.com
This makes the logic around it a bit simpler, and I find it easier to understand as well. --- tools/widl/header.c | 58 +++++++++++++++++++++--------------------- tools/widl/header.h | 2 +- tools/widl/parser.y | 16 ++++++------ tools/widl/typegen.c | 8 +++--- tools/widl/widltypes.h | 8 ++++-- 5 files changed, 48 insertions(+), 44 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 624d38094f9..ab931f0193e 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -40,7 +40,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_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name, enum name_type name_type); +static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, bool define, const char *name, enum name_type name_type);
static void write_apicontract_guard_start(FILE *header, const expr_t *expr); static void write_apicontract_guard_end(FILE *header, const expr_t *expr); @@ -218,7 +218,7 @@ static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type) default: ; } - write_type_v(h, &v->declspec, TRUE, v->declonly, name, name_type); + write_type_v(h, &v->declspec, TRUE, v->is_defined, name, name_type); fprintf(h, ";\n"); if (contract) write_apicontract_guard_end(h, contract); } @@ -279,7 +279,7 @@ static void write_pointer_left(FILE *h, type_t *ref) fprintf(h, "*"); }
-void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly, int write_callconv) +void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv) { type_t *t = ds->type; const char *decl_name, *name; @@ -300,7 +300,7 @@ 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) fprintf(h, "enum %s", decl_name ? decl_name : ""); + if (!define) fprintf(h, "enum %s", decl_name ? decl_name : ""); else if (!t->written) { assert(t->defined); if (decl_name) fprintf(h, "enum %s {\n", decl_name); @@ -316,7 +316,7 @@ 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) fprintf(h, "struct %s", decl_name ? decl_name : ""); + if (!define) fprintf(h, "struct %s", decl_name ? decl_name : ""); else if (!t->written) { assert(t->defined); if (decl_name) fprintf(h, "struct %s {\n", decl_name); @@ -334,7 +334,7 @@ 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) fprintf(h, "union %s", decl_name ? decl_name : ""); + if (!define) fprintf(h, "union %s", decl_name ? decl_name : ""); else if (!t->written) { assert(t->defined); if (decl_name) fprintf(h, "union %s {\n", decl_name); @@ -350,7 +350,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i break; case TYPE_POINTER: { - write_type_left(h, type_pointer_get_ref(t), name_type, declonly, FALSE); + write_type_left(h, type_pointer_get_ref(t), name_type, define, FALSE); write_pointer_left(h, type_pointer_get_ref_type(t)); if (ds->qualifier & TYPE_QUALIFIER_CONST) fprintf(h, "const "); break; @@ -360,14 +360,14 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i fprintf(h, "%s", t->name); else { - write_type_left(h, type_array_get_element(t), name_type, declonly, !type_array_is_decl_as_ptr(t)); + write_type_left(h, type_array_get_element(t), name_type, define, !type_array_is_decl_as_ptr(t)); if (type_array_is_decl_as_ptr(t)) write_pointer_left(h, type_array_get_element_type(t)); } break; case TYPE_FUNCTION: { - write_type_left(h, type_function_get_ret(t), name_type, declonly, TRUE); + write_type_left(h, type_function_get_ret(t), name_type, define, TRUE);
/* A pointer to a function has to write the calling convention inside * the parentheses. There's no way to handle that here, so we have to @@ -446,7 +446,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i case TYPE_BITFIELD: { const decl_spec_t ds = {.type = type_bitfield_get_field(t)}; - write_type_left(h, &ds, name_type, declonly, TRUE); + write_type_left(h, &ds, name_type, define, TRUE); break; } case TYPE_ALIAS: @@ -454,7 +454,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i const decl_spec_t *ds = type_alias_get_aliasee(t); int in_namespace = ds && ds->type && ds->type->namespace && !is_global_namespace(ds->type->namespace); if (!in_namespace) fprintf(h, "%s", t->name); - else write_type_left(h, ds, name_type, declonly, write_callconv); + else write_type_left(h, ds, name_type, define, write_callconv); break; } case TYPE_PARAMETERIZED_TYPE: @@ -546,13 +546,13 @@ void write_type_right(FILE *h, type_t *t, int is_field) } }
-static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name, enum name_type name_type) +static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, bool define, const char *name, enum name_type name_type) { type_t *t = ds->type;
if (!h) return;
- if (t) write_type_left(h, ds, name_type, declonly, TRUE); + if (t) write_type_left(h, ds, name_type, define, TRUE);
if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
@@ -560,7 +560,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_definition(FILE *f, type_t *t, int declonly) +static void write_type_definition(FILE *f, type_t *t, bool define) { int in_namespace = t->namespace && !is_global_namespace(t->namespace); int save_written = t->written; @@ -574,14 +574,14 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) write_namespace_start(f, t->namespace); } indent(f, 0); - write_type_left(f, &ds, NAME_DEFAULT, declonly, TRUE); + write_type_left(f, &ds, NAME_DEFAULT, define, 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, declonly, TRUE); + write_type_left(f, &ds, NAME_C, define, TRUE); fprintf(f, ";\n"); if (winrt_mode) write_widl_using_macros(f, t); fprintf(f, "#endif\n\n"); @@ -591,12 +591,12 @@ static void write_type_definition(FILE *f, type_t *t, int declonly)
void write_type_decl(FILE *f, const decl_spec_t *t, const char *name) { - write_type_v(f, t, FALSE, TRUE, name, NAME_DEFAULT); + write_type_v(f, t, FALSE, false, name, NAME_DEFAULT); }
void write_type_decl_left(FILE *f, const decl_spec_t *ds) { - write_type_left(f, ds, NAME_DEFAULT, TRUE, TRUE); + write_type_left(f, ds, NAME_DEFAULT, false, TRUE); }
static int user_type_registered(const char *name) @@ -817,14 +817,14 @@ static void write_generic_handle_routines(FILE *header) } }
-static void write_typedef(FILE *header, type_t *type, int declonly) +static void write_typedef(FILE *header, type_t *type, bool define) { type_t *t = type_alias_get_aliasee_type(type); if (winrt_mode && t->namespace && !is_global_namespace(t->namespace)) { fprintf(header, "#ifndef __cplusplus\n"); fprintf(header, "typedef "); - write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->c_name, NAME_C); + write_type_v(header, type_alias_get_aliasee(type), FALSE, define, type->c_name, NAME_C); fprintf(header, ";\n"); if (type_get_type_detect_alias(t) != TYPE_ENUM) { @@ -832,7 +832,7 @@ static void write_typedef(FILE *header, type_t *type, int declonly) write_namespace_start(header, t->namespace); indent(header, 0); fprintf(header, "typedef "); - write_type_v(header, type_alias_get_aliasee(type), FALSE, TRUE, type->name, NAME_DEFAULT); + write_type_v(header, type_alias_get_aliasee(type), FALSE, false, type->name, NAME_DEFAULT); fprintf(header, ";\n"); write_namespace_end(header, t->namespace); } @@ -841,7 +841,7 @@ static void write_typedef(FILE *header, type_t *type, int declonly) else { fprintf(header, "typedef "); - write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_DEFAULT); + write_type_v(header, type_alias_get_aliasee(type), FALSE, define, type->name, NAME_DEFAULT); fprintf(header, ";\n"); } } @@ -886,7 +886,7 @@ static void write_declaration(FILE *header, const var_t *v) fprintf(header, "extern "); break; } - write_type_v(header, &v->declspec, FALSE, v->declonly, v->name, NAME_DEFAULT); + write_type_v(header, &v->declspec, FALSE, v->is_defined, v->name, NAME_DEFAULT); fprintf(header, ";\n\n"); } } @@ -1127,10 +1127,10 @@ 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), + /* In theory we should be writing the definition using write_type_v(..., arg->define), * but that causes redefinition in e.g. proxy files. In fact MIDL disallows * defining UDTs inside of an argument list. */ - write_type_v(h, &arg->declspec, FALSE, TRUE, arg->name, name_type); + write_type_v(h, &arg->declspec, FALSE, false, arg->name, name_type); if (method == 2) { const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE); if (expr) { @@ -1498,7 +1498,7 @@ static void write_parameterized_type_forward(FILE *header, type_t *type) fprintf(header, "#endif\n\n" ); }
-static void write_parameterized_implementation(FILE *header, type_t *type, int declonly) +static void write_parameterized_implementation(FILE *header, type_t *type, bool define) { const statement_t *stmt; typeref_list_t *params = type->details.parameterized.params; @@ -2006,11 +2006,11 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) write_runtimeclass(header, stmt->u.type); else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE) - write_type_definition(header, stmt->u.type, stmt->declonly); + write_type_definition(header, stmt->u.type, stmt->is_defined); else { is_object_interface++; - write_parameterized_implementation(header, stmt->u.type, stmt->declonly); + write_parameterized_implementation(header, stmt->u.type, stmt->is_defined); is_object_interface--; } break; @@ -2032,7 +2032,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons { typeref_t *ref; if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) - write_typedef(header, ref->type, stmt->declonly); + write_typedef(header, ref->type, stmt->is_defined); break; } case STMT_LIBRARY: diff --git a/tools/widl/header.h b/tools/widl/header.h index ae06d92bfa8..45066898a66 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -24,7 +24,7 @@ #include "typetree.h"
extern const char* get_name(const var_t *v); -extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly, int write_callconv); +extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv); extern void write_type_right(FILE *h, type_t *t, int is_field); extern void write_type_decl(FILE *f, const decl_spec_t *t, const char *name); extern void write_type_decl_left(FILE *f, const decl_spec_t *ds); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 097d927dbc2..3353ad39432 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -87,7 +87,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, int declonly); +static statement_t *make_statement_typedef(var_list_t *names, bool is_defined); static statement_t *make_statement_import(const char *str); static statement_t *make_statement_parameterized_type(type_t *type, typeref_list_t *params); static statement_t *make_statement_delegate(type_t *ret, var_list_t *args); @@ -1359,7 +1359,7 @@ type: 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, !$4->type->defined); + $$ = make_statement_typedef($5, $4->type->defined); } ;
@@ -1719,7 +1719,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; + v->is_defined = type->defined;
if (is_attr(type->attrs, ATTR_CALLCONV) && !is_func(type)) error_loc("calling convention applied to non-function type\n"); @@ -1922,7 +1922,7 @@ var_t *make_var(char *name) v->attrs = NULL; v->eval = NULL; init_location( &v->where, NULL, NULL ); - v->declonly = FALSE; + v->is_defined = 1; return v; }
@@ -2756,7 +2756,7 @@ static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts { case STMT_TYPE: stmt->u.type = type_parameterized_type_specialize_define(stmt->u.type); - stmt->declonly = FALSE; + stmt->is_defined = 1; list_remove(&stmt->entry); stmts = append_statement(stmts, stmt); break; @@ -2833,7 +2833,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; + stmt->is_defined = type->defined; return stmt; }
@@ -2904,7 +2904,7 @@ static statement_t *make_statement_module(type_t *type) return stmt; }
-static statement_t *make_statement_typedef(declarator_list_t *decls, int declonly) +static statement_t *make_statement_typedef(declarator_list_t *decls, bool is_defined) { declarator_t *decl, *next; statement_t *stmt; @@ -2913,7 +2913,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls, int declonl
stmt = make_statement(STMT_TYPEDEF); stmt->u.type_list = NULL; - stmt->declonly = declonly; + stmt->is_defined = is_defined;
LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry ) { diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 9bfec7c5000..0777de77bf0 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -5055,7 +5055,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { print_file(file, 2, "%s", ""); - write_type_left( file, &arg->declspec, NAME_DEFAULT, TRUE, TRUE ); + write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE ); if (needs_space_after( arg->declspec.type )) fputc( ' ', file ); if (is_array( arg->declspec.type ) && !type_array_is_decl_as_ptr( arg->declspec.type )) fputc( '*', file );
@@ -5071,7 +5071,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun if (add_retval && !is_void( retval->declspec.type )) { print_file(file, 2, "%s", ""); - write_type_left( file, &retval->declspec, NAME_DEFAULT, TRUE, TRUE ); + write_type_left( file, &retval->declspec, NAME_DEFAULT, false, TRUE ); if (needs_space_after( retval->declspec.type )) fputc( ' ', file ); if (!is_array( retval->declspec.type ) && !is_ptr( retval->declspec.type ) && type_memsize( retval->declspec.type ) != pointer_size) @@ -5122,9 +5122,9 @@ int write_expr_eval_routines(FILE *file, const char *iface) { decl_spec_t ds = {.type = (type_t *)eval->cont_type}; print_file(file, 1, "%s", ""); - write_type_left(file, &ds, NAME_DEFAULT, TRUE, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE); fprintf(file, " *%s = (", var_name); - write_type_left(file, &ds, NAME_DEFAULT, TRUE, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE); fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); } print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 1a26bb77cad..9d99c83a25e 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -22,6 +22,7 @@ #define __WIDL_WIDLTYPES_H
#include <stdarg.h> +#include <stdbool.h> #include <assert.h> #include "ndrtypes.h" #include "wine/list.h" @@ -541,7 +542,8 @@ struct _var_t {
struct location where;
- unsigned int declonly : 1; + /* Should we define the UDT in this var, when writing a header? */ + unsigned int is_defined : 1;
/* parser-internal */ struct list entry; @@ -622,7 +624,9 @@ struct _statement_t { typelib_t *lib; typeref_list_t *type_list; } u; - unsigned int declonly : 1; /* for STMT_TYPE and STMT_TYPEDEF */ + /* For STMT_TYPE and STMT_TYPEDEF, should we define the UDT in this + * statement, when writing a header? */ + unsigned int is_defined : 1; };
struct _warning_t {
From: Elizabeth Figura zfigura@codeweavers.com
--- tools/widl/typetree.c | 95 ++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 65 deletions(-)
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 7e4c4fd3a38..1623a2729a6 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -530,6 +530,14 @@ type_t *type_new_void(void) return void_type; }
+static void define_type(type_t *type) +{ + if (type->defined) + error_loc("type %s already defined at %s:%d\n", type->name, type->where.input_name, type->where.first_line ); + + type->defined = TRUE; +} + type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums) { type_t *t = NULL; @@ -546,14 +554,12 @@ type_t *type_new_enum(const char *name, struct namespace *namespace, int defined reg_type(t, name, namespace, tsENUM); }
- if (!t->defined && defined) + if (defined) { t->details.enumeration = xmalloc(sizeof(*t->details.enumeration)); t->details.enumeration->enums = enums; - t->defined = TRUE; + define_type(t); } - else if (defined) - error_loc("redefinition of enum %s\n", name);
return t; } @@ -574,14 +580,12 @@ type_t *type_new_struct(char *name, struct namespace *namespace, int defined, va reg_type(t, name, namespace, tsSTRUCT); }
- if (!t->defined && defined) + if (defined) { t->details.structure = xmalloc(sizeof(*t->details.structure)); t->details.structure->fields = fields; - t->defined = TRUE; + define_type(t); } - else if (defined) - error_loc("redefinition of struct %s\n", name);
return t; } @@ -606,10 +610,8 @@ type_t *type_new_nonencapsulated_union(const char *name, struct namespace *names { t->details.structure = xmalloc(sizeof(*t->details.structure)); t->details.structure->fields = fields; - t->defined = TRUE; + define_type(t); } - else if (defined) - error_loc("redefinition of union %s\n", name);
return t; } @@ -630,19 +632,14 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio } 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(gen_name(), NULL, TRUE, cases); + if (!union_field) + union_field = make_var(xstrdup("tagged_union")); + union_field->declspec.type = type_new_nonencapsulated_union(gen_name(), 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; - } - else - error_loc("redefinition of union %s\n", name); + 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); + define_type(t);
return t; } @@ -732,9 +729,6 @@ type_t *type_interface_declare(char *name, struct namespace *namespace)
type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires) { - if (iface->defined) - error_loc( "interface %s already defined at %s:%d\n", iface->name, - iface->where.input_name, iface->where.first_line ); if (iface == inherit) error_loc("interface %s can't inherit from itself\n", iface->name); @@ -747,7 +741,7 @@ type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; iface->details.iface->requires = requires; - iface->defined = TRUE; + define_type(iface); compute_method_indexes(iface); return iface; } @@ -763,9 +757,6 @@ type_t *type_dispinterface_declare(char *name)
type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t *props, var_list_t *methods) { - if (iface->defined) - error_loc( "dispinterface %s already defined at %s:%d\n", iface->name, - iface->where.input_name, iface->where.first_line ); iface->attrs = check_dispiface_attrs(iface->name, attrs); iface->details.iface = xmalloc(sizeof(*iface->details.iface)); iface->details.iface->disp_props = props; @@ -776,16 +767,13 @@ type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; iface->details.iface->requires = NULL; - iface->defined = TRUE; + define_type(iface); compute_method_indexes(iface); return iface; }
type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *attrs, type_t *iface) { - if (dispiface->defined) - error_loc( "dispinterface %s already defined at %s:%d\n", dispiface->name, - dispiface->where.input_name, dispiface->where.first_line ); dispiface->attrs = check_dispiface_attrs(dispiface->name, attrs); dispiface->details.iface = xmalloc(sizeof(*dispiface->details.iface)); dispiface->details.iface->disp_props = NULL; @@ -796,7 +784,7 @@ type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *att dispiface->details.iface->disp_inherit = iface; dispiface->details.iface->async_iface = NULL; dispiface->details.iface->requires = NULL; - dispiface->defined = TRUE; + define_type(dispiface); compute_method_indexes(dispiface); return dispiface; } @@ -812,13 +800,10 @@ type_t *type_module_declare(char *name)
type_t *type_module_define(type_t* module, attr_list_t *attrs, statement_list_t *stmts) { - if (module->defined) - error_loc( "module %s already defined at %s:%d\n", module->name, - module->where.input_name, module->where.first_line ); module->attrs = check_module_attrs(module->name, attrs); module->details.module = xmalloc(sizeof(*module->details.module)); module->details.module->stmts = stmts; - module->defined = TRUE; + define_type(module); return module; }
@@ -833,12 +818,9 @@ type_t *type_coclass_declare(char *name)
type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, typeref_list_t *ifaces) { - if (coclass->defined) - error_loc( "coclass %s already defined at %s:%d\n", coclass->name, - coclass->where.input_name, coclass->where.first_line ); coclass->attrs = check_coclass_attrs(coclass->name, attrs); coclass->details.coclass.ifaces = ifaces; - coclass->defined = TRUE; + define_type(coclass); return coclass; }
@@ -856,12 +838,9 @@ type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, typer typeref_t *ref, *required, *tmp; typeref_list_t *requires;
- if (runtimeclass->defined) - error_loc( "runtimeclass %s already defined at %s:%d\n", runtimeclass->name, - runtimeclass->where.input_name, runtimeclass->where.first_line ); runtimeclass->attrs = check_runtimeclass_attrs(runtimeclass->name, attrs); runtimeclass->details.runtimeclass.ifaces = ifaces; - runtimeclass->defined = TRUE; + define_type(runtimeclass); if (!type_runtimeclass_get_default_iface(runtimeclass, FALSE) && !get_attrp(runtimeclass->attrs, ATTR_STATIC)) error_loc("runtimeclass %s must have a default interface or static factory\n", runtimeclass->name); @@ -901,11 +880,8 @@ type_t *type_apicontract_declare(char *name, struct namespace *namespace)
type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) { - if (apicontract->defined) - error_loc( "apicontract %s already defined at %s:%d\n", apicontract->name, - apicontract->where.input_name, apicontract->where.first_line ); apicontract->attrs = check_apicontract_attrs(apicontract->name, attrs); - apicontract->defined = TRUE; + define_type(apicontract); return apicontract; }
@@ -934,10 +910,6 @@ type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_lis { type_t *iface;
- if (delegate->defined) - error_loc( "delegate %s already defined at %s:%d\n", delegate->name, - delegate->where.input_name, delegate->where.first_line ); - delegate->attrs = check_interface_attrs(delegate->name, attrs);
iface = make_type(TYPE_INTERFACE); @@ -955,7 +927,7 @@ type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_lis compute_method_indexes(iface);
delegate->details.delegate.iface = iface; - delegate->defined = TRUE; + define_type(delegate); compute_delegate_iface_names(delegate, NULL, NULL);
return delegate; @@ -975,9 +947,6 @@ type_t *type_parameterized_interface_declare(char *name, struct namespace *names type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires) { type_t *iface; - if (type->defined) - error_loc( "pinterface %s already defined at %s:%d\n", type->name, - type->where.input_name, type->where.first_line );
/* The parameterized type UUID is actually a PIID that is then used as a seed to generate * a new type GUID with the rules described in: @@ -998,7 +967,7 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty
iface->name = type->name;
- type->defined = TRUE; + define_type(type); return type; }
@@ -1017,10 +986,6 @@ type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, sta { type_t *iface, *delegate;
- if (type->defined) - error_loc( "pdelegate %s already defined at %s:%d\n", type->name, - type->where.input_name, type->where.first_line ); - type->attrs = check_interface_attrs(type->name, attrs);
delegate = type->details.parameterized.type; @@ -1041,7 +1006,7 @@ type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, sta delegate->name = type->name; compute_delegate_iface_names(delegate, type, type->details.parameterized.params);
- type->defined = TRUE; + define_type(type); return type; }
From: Elizabeth Figura zfigura@codeweavers.com
This improves error reporting for the following IDL:
interface apple;
[uuid(12345678-1234-1234-1234-123456654321)] interface apple {void func(void);} [uuid(12345678-1234-1234-1234-123456654321)] interface apple {void func(void);}
Previously widl would report:
test2.idl:19:34: error: type apple already defined at test2.idl:2
This changes it to refer to line 5, where the interface is actually defined. --- tools/widl/parser.y | 42 ++++++++++++------------ tools/widl/typetree.c | 74 +++++++++++++++++++++++++------------------ tools/widl/typetree.h | 41 ++++++++++++++++-------- 3 files changed, 92 insertions(+), 65 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 3353ad39432..d8363afa981 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -500,11 +500,11 @@ warnings:
typedecl: enumdef - | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } + | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL, &@$); } | structdef - | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } + | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL, &@$); } | uniondef - | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL); } + | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL, &@$); } | attributes enumdef { $$ = $2; $$->attrs = check_enum_attrs($1); } | attributes structdef { $$ = $2; $$->attrs = check_struct_attrs($1); } | attributes uniondef { $$ = $2; $$->attrs = check_union_attrs($1); } @@ -823,7 +823,7 @@ enum: enum_member '=' expr_int_const { $$ = reg_const($1); } ;
-enumdef: tENUM m_typename '{' enums '}' { $$ = type_new_enum($2, current_namespace, TRUE, $4); } +enumdef: tENUM m_typename '{' enums '}' { $$ = type_new_enum($2, current_namespace, TRUE, $4, &@2); } ;
m_exprs: m_expr { $$ = append_expr( NULL, $1 ); } @@ -1032,7 +1032,7 @@ coclass: tCOCLASS typename { $$ = type_coclass_declare($2); } ;
coclassdef: attributes coclass '{' class_interfaces '}' semicolon_opt - { $$ = type_coclass_define($2, $1, $4); } + { $$ = type_coclass_define($2, $1, $4, &@2); } ;
runtimeclass: tRUNTIMECLASS typename { $$ = type_runtimeclass_declare($2, current_namespace); } @@ -1040,14 +1040,14 @@ runtimeclass: tRUNTIMECLASS typename { $$ = type_runtimeclass_declare($2, curre
runtimeclass_def: attributes runtimeclass inherit '{' class_interfaces '}' semicolon_opt { if ($3 && type_get_type($3) != TYPE_RUNTIMECLASS) error_loc("%s is not a runtimeclass\n", $3->name); - $$ = type_runtimeclass_define($2, $1, $5); } + $$ = type_runtimeclass_define($2, $1, $5, &@2); } ;
apicontract: tAPICONTRACT typename { $$ = type_apicontract_declare($2, current_namespace); } ;
apicontract_def: attributes apicontract '{' '}' semicolon_opt - { $$ = type_apicontract_define($2, $1); } + { $$ = type_apicontract_define($2, $1, &@2); } ;
namespacedef: tNAMESPACE aIDENTIFIER { $$ = append_str( NULL, $2 ); } @@ -1080,9 +1080,9 @@ dispint_meths: tMETHODS ':' { $$ = NULL; }
dispinterfacedef: dispattributes dispinterface '{' dispint_props dispint_meths '}' - { $$ = type_dispinterface_define($2, $1, $4, $5); } + { $$ = type_dispinterface_define($2, $1, $4, $5, &@2); } | dispattributes dispinterface '{' interface ';' '}' - { $$ = type_dispinterface_define_from_iface($2, $1, $4); } + { $$ = type_dispinterface_define_from_iface($2, $1, $4, &@2); } ;
inherit @@ -1107,13 +1107,13 @@ interface:
delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt { $$ = type_delegate_declare($4->name, current_namespace); - $$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6))); + $$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6)), &@4); } | m_attributes tDELEGATE type ident '<' { push_parameters_namespace($4->name); } type_parameters '>' '(' m_args ')' { pop_parameters_namespace($4->name); } semicolon_opt { $$ = type_parameterized_delegate_declare($4->name, current_namespace, $7); - $$ = type_parameterized_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $10))); + $$ = type_parameterized_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $10)), &@4); } ;
@@ -1133,12 +1133,12 @@ interfacedef: attributes interface { if ($2->type_type == TYPE_PARAMETERIZED_TY inherit requires '{' int_statements '}' semicolon_opt { if ($2->type_type == TYPE_PARAMETERIZED_TYPE) { - $$ = type_parameterized_interface_define($2, $1, $4, $7, $5); + $$ = type_parameterized_interface_define($2, $1, $4, $7, $5, &@2); pop_parameters_namespace($2->name); } else { - $$ = type_interface_define($2, $1, $4, $7, $5); + $$ = type_interface_define($2, $1, $4, $7, $5, &@2); check_async_uuid($$); } } @@ -1159,7 +1159,7 @@ module: tMODULE typename { $$ = type_module_declare($2); } ;
moduledef: m_attributes module '{' int_statements '}' semicolon_opt - { $$ = type_module_define($2, $1, $4); } + { $$ = type_module_define($2, $1, $4, &@2); } ;
storage_cls_spec: @@ -1334,18 +1334,18 @@ pointer_type: | tPTR { $$ = FC_FP; } ;
-structdef: tSTRUCT m_typename '{' fields '}' { $$ = type_new_struct($2, current_namespace, TRUE, $4); } +structdef: tSTRUCT m_typename '{' fields '}' { $$ = type_new_struct($2, current_namespace, TRUE, $4, &@2); } ;
unqualified_type: tVOID { $$ = type_new_void(); } | base_type { $$ = $1; } | enumdef { $$ = $1; } - | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } + | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL, &@$); } | structdef { $$ = $1; } - | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } + | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL, &@$); } | uniondef { $$ = $1; } - | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL); } + | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL, &@$); } | tSAFEARRAY '(' type ')' { $$ = make_safearray($3); } | aKNOWNTYPE { $$ = find_type_or_error(current_namespace, $1); } ; @@ -1364,10 +1364,10 @@ typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list ;
uniondef: tUNION m_typename '{' ne_union_fields '}' - { $$ = type_new_nonencapsulated_union($2, current_namespace, TRUE, $4); } + { $$ = type_new_nonencapsulated_union($2, current_namespace, TRUE, $4, &@2); } | tUNION m_typename tSWITCH '(' s_field ')' - m_ident '{' cases '}' { $$ = type_new_encapsulated_union($2, $5, $7, $9); } + m_ident '{' cases '}' { $$ = type_new_encapsulated_union($2, $5, $7, $9, &@2); } ;
version: @@ -2742,7 +2742,7 @@ static void check_async_uuid(type_t *iface) stmts = append_statement(stmts, make_statement_declaration(finish_func)); }
- type_interface_define(async_iface, map_attrs(iface->attrs, async_iface_attrs), inherit, stmts, NULL); + type_interface_define(async_iface, map_attrs(iface->attrs, async_iface_attrs), inherit, stmts, NULL, &iface->where); iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface; }
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 1623a2729a6..ea17f16e0c8 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -530,15 +530,17 @@ type_t *type_new_void(void) return void_type; }
-static void define_type(type_t *type) +static void define_type(type_t *type, const struct location *where) { if (type->defined) error_loc("type %s already defined at %s:%d\n", type->name, type->where.input_name, type->where.first_line );
type->defined = TRUE; + type->where = *where; }
-type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums) +type_t *type_new_enum(const char *name, struct namespace *namespace, + int defined, var_list_t *enums, const struct location *where) { type_t *t = NULL;
@@ -558,13 +560,14 @@ type_t *type_new_enum(const char *name, struct namespace *namespace, int defined { t->details.enumeration = xmalloc(sizeof(*t->details.enumeration)); t->details.enumeration->enums = enums; - define_type(t); + define_type(t, where); }
return t; }
-type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields) +type_t *type_new_struct(char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where) { type_t *t = NULL;
@@ -584,13 +587,14 @@ type_t *type_new_struct(char *name, struct namespace *namespace, int defined, va { t->details.structure = xmalloc(sizeof(*t->details.structure)); t->details.structure->fields = fields; - define_type(t); + define_type(t, where); }
return t; }
-type_t *type_new_nonencapsulated_union(const char *name, struct namespace *namespace, int defined, var_list_t *fields) +type_t *type_new_nonencapsulated_union(const char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where) { type_t *t = NULL;
@@ -610,13 +614,14 @@ type_t *type_new_nonencapsulated_union(const char *name, struct namespace *names { t->details.structure = xmalloc(sizeof(*t->details.structure)); t->details.structure->fields = fields; - define_type(t); + define_type(t, where); }
return t; }
-type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases) +type_t *type_new_encapsulated_union(char *name, var_t *switch_field, + var_t *union_field, var_list_t *cases, const struct location *where) { type_t *t = NULL;
@@ -634,12 +639,12 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio
if (!union_field) union_field = make_var(xstrdup("tagged_union")); - union_field->declspec.type = type_new_nonencapsulated_union(gen_name(), NULL, TRUE, cases); + union_field->declspec.type = type_new_nonencapsulated_union(gen_name(), NULL, TRUE, cases, where);
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); - define_type(t); + define_type(t, where);
return t; } @@ -727,7 +732,8 @@ type_t *type_interface_declare(char *name, struct namespace *namespace) return type; }
-type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires) +type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where) { if (iface == inherit) error_loc("interface %s can't inherit from itself\n", @@ -741,7 +747,7 @@ type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; iface->details.iface->requires = requires; - define_type(iface); + define_type(iface, where); compute_method_indexes(iface); return iface; } @@ -755,7 +761,8 @@ type_t *type_dispinterface_declare(char *name) return type; }
-type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t *props, var_list_t *methods) +type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, + var_list_t *props, var_list_t *methods, const struct location *where) { iface->attrs = check_dispiface_attrs(iface->name, attrs); iface->details.iface = xmalloc(sizeof(*iface->details.iface)); @@ -767,12 +774,13 @@ type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; iface->details.iface->requires = NULL; - define_type(iface); + define_type(iface, where); compute_method_indexes(iface); return iface; }
-type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *attrs, type_t *iface) +type_t *type_dispinterface_define_from_iface(type_t *dispiface, + attr_list_t *attrs, type_t *iface, const struct location *where) { dispiface->attrs = check_dispiface_attrs(dispiface->name, attrs); dispiface->details.iface = xmalloc(sizeof(*dispiface->details.iface)); @@ -784,7 +792,7 @@ type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *att dispiface->details.iface->disp_inherit = iface; dispiface->details.iface->async_iface = NULL; dispiface->details.iface->requires = NULL; - define_type(dispiface); + define_type(dispiface, where); compute_method_indexes(dispiface); return dispiface; } @@ -798,12 +806,13 @@ type_t *type_module_declare(char *name) return type; }
-type_t *type_module_define(type_t* module, attr_list_t *attrs, statement_list_t *stmts) +type_t *type_module_define(type_t* module, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where) { module->attrs = check_module_attrs(module->name, attrs); module->details.module = xmalloc(sizeof(*module->details.module)); module->details.module->stmts = stmts; - define_type(module); + define_type(module, where); return module; }
@@ -816,11 +825,12 @@ type_t *type_coclass_declare(char *name) return type; }
-type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, typeref_list_t *ifaces) +type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where) { coclass->attrs = check_coclass_attrs(coclass->name, attrs); coclass->details.coclass.ifaces = ifaces; - define_type(coclass); + define_type(coclass, where); return coclass; }
@@ -833,14 +843,15 @@ type_t *type_runtimeclass_declare(char *name, struct namespace *namespace) return type; }
-type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, typeref_list_t *ifaces) +type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where) { typeref_t *ref, *required, *tmp; typeref_list_t *requires;
runtimeclass->attrs = check_runtimeclass_attrs(runtimeclass->name, attrs); runtimeclass->details.runtimeclass.ifaces = ifaces; - define_type(runtimeclass); + define_type(runtimeclass, where); if (!type_runtimeclass_get_default_iface(runtimeclass, FALSE) && !get_attrp(runtimeclass->attrs, ATTR_STATIC)) error_loc("runtimeclass %s must have a default interface or static factory\n", runtimeclass->name); @@ -878,10 +889,10 @@ type_t *type_apicontract_declare(char *name, struct namespace *namespace) return type; }
-type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) +type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs, const struct location *where) { apicontract->attrs = check_apicontract_attrs(apicontract->name, attrs); - define_type(apicontract); + define_type(apicontract, where); return apicontract; }
@@ -906,7 +917,8 @@ type_t *type_delegate_declare(char *name, struct namespace *namespace) return type; }
-type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts) +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where) { type_t *iface;
@@ -927,7 +939,7 @@ type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_lis compute_method_indexes(iface);
delegate->details.delegate.iface = iface; - define_type(delegate); + define_type(delegate, where); compute_delegate_iface_names(delegate, NULL, NULL);
return delegate; @@ -944,7 +956,8 @@ type_t *type_parameterized_interface_declare(char *name, struct namespace *names return type; }
-type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires) +type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where) { type_t *iface;
@@ -967,7 +980,7 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty
iface->name = type->name;
- define_type(type); + define_type(type, where); return type; }
@@ -982,7 +995,8 @@ type_t *type_parameterized_delegate_declare(char *name, struct namespace *namesp return type; }
-type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts) +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where) { type_t *iface, *delegate;
@@ -1006,7 +1020,7 @@ type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, sta delegate->name = type->name; compute_delegate_iface_names(delegate, type, type->details.parameterized.params);
- define_type(type); + define_type(type, where); return type; }
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 8942454ceda..6e5c606ab35 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -44,28 +44,41 @@ type_t *type_new_basic(enum type_basic_type basic_type); type_t *type_new_int(enum type_basic_type basic_type, int sign); type_t *type_new_void(void); type_t *type_coclass_declare(char *name); -type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums); -type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields); -type_t *type_new_nonencapsulated_union(const char *name, struct namespace *namespace, int defined, var_list_t *fields); -type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); +type_t *type_new_enum(const char *name, struct namespace *namespace, + int defined, var_list_t *enums, const struct location *where); +type_t *type_new_struct(char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where); +type_t *type_new_nonencapsulated_union(const char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where); +type_t *type_new_encapsulated_union(char *name, var_t *switch_field, + var_t *union_field, var_list_t *cases, const struct location *where); type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); type_t *type_runtimeclass_declare(char *name, struct namespace *namespace); type_t *type_interface_declare(char *name, struct namespace *namespace); -type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires); +type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where); type_t *type_dispinterface_declare(char *name); -type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t *props, var_list_t *methods); -type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *attrs, type_t *iface); -type_t *type_module_define(type_t* module, attr_list_t *attrs, statement_list_t *stmts); -type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, typeref_list_t *ifaces); -type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, typeref_list_t *ifaces); +type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, + var_list_t *props, var_list_t *methods, const struct location *where); +type_t *type_dispinterface_define_from_iface(type_t *dispiface, + attr_list_t *attrs, type_t *iface, const struct location *where); +type_t *type_module_define(type_t* module, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where); +type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where); +type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where); type_t *type_apicontract_declare(char *name, struct namespace *namespace); -type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs); +type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs, const struct location *where); type_t *type_delegate_declare(char *name, struct namespace *namespace); -type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts); +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where); type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params); -type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires); +type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where); type_t *type_parameterized_delegate_declare(char *name, struct namespace *namespace, typeref_list_t *params); -type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts); +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where); type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params); type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params); type_t *type_parameterized_type_specialize_define(type_t *type);
From: Elizabeth Figura zfigura@codeweavers.com
midl does not, and this would result in redefinition errors.
An equivalent (and arguably a bit more declarative) way to do this would be to keep track in the parser whether a type or typedef statement is actually a definition or not, and record that information in the statement_t. However, this would require passing additional information alongside the type_t from each relevant bison rule, which would thrash a lot of code. --- tools/widl/parser.y | 6 +++--- tools/widl/typetree.c | 2 ++ tools/widl/widltypes.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index d8363afa981..f5b82f29db3 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1359,7 +1359,7 @@ type: 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, $4->type->defined); + $$ = make_statement_typedef($5, $4->type->defined && !$4->type->defined_in_import); } ;
@@ -1719,7 +1719,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->is_defined = type->defined; + v->is_defined = type->defined && !type->defined_in_import;
if (is_attr(type->attrs, ATTR_CALLCONV) && !is_func(type)) error_loc("calling convention applied to non-function type\n"); @@ -2833,7 +2833,7 @@ static statement_t *make_statement_type_decl(type_t *type) { statement_t *stmt = make_statement(STMT_TYPE); stmt->u.type = type; - stmt->is_defined = type->defined; + stmt->is_defined = type->defined && !type->defined_in_import; return stmt; }
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index ea17f16e0c8..af41906c42b 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -536,6 +536,7 @@ static void define_type(type_t *type, const struct location *where) error_loc("type %s already defined at %s:%d\n", type->name, type->where.input_name, type->where.first_line );
type->defined = TRUE; + type->defined_in_import = parse_only; type->where = *where; }
@@ -935,6 +936,7 @@ type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; iface->details.iface->requires = NULL; + define_type(iface, where); iface->defined = TRUE; compute_method_indexes(iface);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 9d99c83a25e..7bc24fad0d3 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -523,6 +523,7 @@ struct _type_t { struct location where; unsigned int ignore : 1; unsigned int defined : 1; + unsigned int defined_in_import : 1; unsigned int written : 1; unsigned int user_types_registered : 1; unsigned int tfswrite : 1; /* if the type needs to be written to the TFS */
This is the first and only use of `bool` in widl. Later, you're also introducing a new `unsigned int :1` field elsewhere.
I mostly changed this bool and not the other because this one was clearly not saving any space (whereas the other was packed with other fields), and I was thrashing the field name here anyway. I've reverted the change however.
I think something like `is_definition` is also more appropriate for an object property. Same below.
I changed it, although it seems a bit awkward now given 6/6, since the name reflects whether we should define the type when writing the header, not whether the type was defined when parsing (in contrast to the "defined" field of type_t).
On Fri May 31 19:33:41 2024 +0000, Elizabeth Figura wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/5724/diffs?diff_id=116042&start_sha=a28b2868f7155ff91a6ae0279527ed3b9e7ca6c9#06f6f5e1d8c837fb483c79004647ce3f2d069910_540_540)
Done. We don't pass around explicit locations elsewhere, so it required quite a lot of change, but I concur that is a direction we want to go in.
I think something like `is_definition` is also more appropriate for an object property. Same below.
I changed it, although it seems a bit awkward now given 6/6, since the name reflects whether we should define the type when writing the header, not whether the type was defined when parsing (in contrast to the "defined" field of type_t).
Hmm, okay, I don't know then. I find it awkward to store information about codegen action at parse time, on the data, and I think it should be rather only up to the codegen code to decide what to do depending on what the parsed data *is*.
For this reason, I thought that `is_definition` was better describing the nature of the parsed information, rather than what we intend to do with it, and `is_defined` doesn't feel exactly right in this case (maybe better that `define`).
Anyway, it probably doesn't matter much.
On Fri May 31 19:37:29 2024 +0000, Elizabeth Figura wrote:
Done. We don't pass around explicit locations elsewhere, so it required quite a lot of change, but I concur that is a direction we want to go in.
We pass them for attributes, and yeah I think it would be nice to have it for everything else.
This merge request was approved by Rémi Bernon.
On Sat Jun 1 09:47:08 2024 +0000, Rémi Bernon wrote:
I think something like `is_definition` is also more appropriate for
an object property. Same below.
I changed it, although it seems a bit awkward now given 6/6, since the
name reflects whether we should define the type when writing the header, not whether the type was defined when parsing (in contrast to the "defined" field of type_t). Hmm, okay, I don't know then. I find it awkward to store information about codegen action at parse time, on the data, and I think it should be rather only up to the codegen code to decide what to do depending on what the parsed data *is*. For this reason, I thought that `is_definition` was better describing the nature of the parsed information, rather than what we intend to do with it, and `is_defined` doesn't feel exactly right in this case (maybe better that `define`). Anyway, it probably doesn't matter much.
I agree in general. We could always propagate the "defined_in_import" field to statements and vars. I dunno if it's worth changing though.