From: Nikolay Sivov nsivov@codeweavers.com
The issue comes from per-field structure copy that we generate on 32-bit. For non-pointer fields like "const int" this breaks compilation when assigning to a const field. The best solution would be to remove local struct variable completely and pass first argument address as a stack address. This is what midl does. My understanding is that doing it midl way used to break on some compilers, and we have to keep the copy. Once we encounter pointer type that needs such copy, we'll have to patch it more to cast the const away for example.
Such type modification matches what midl does for structures in _Thunk's, so the fix itself is correct.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- tools/widl/header.c | 21 +++++++++++---------- tools/widl/header.h | 3 ++- tools/widl/typegen.c | 8 ++++---- 3 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 31b476df677..e14194bb62a 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -279,7 +279,8 @@ 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, bool define, int write_callconv) +void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, + int write_callconv, bool noconst) { type_t *t = ds->type; const char *decl_name, *name; @@ -293,7 +294,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b if (ds->func_specifier & FUNCTION_SPECIFIER_INLINE) fprintf(h, "inline ");
- if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (type_is_alias(t) || !is_ptr(t))) + if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (!noconst && (type_is_alias(t) || !is_ptr(t)))) fprintf(h, "const ");
if (type_is_alias(t)) fprintf(h, "%s", name); @@ -350,7 +351,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b break; case TYPE_POINTER: { - write_type_left(h, type_pointer_get_ref(t), name_type, define, FALSE); + write_type_left(h, type_pointer_get_ref(t), name_type, define, FALSE, false); write_pointer_left(h, type_pointer_get_ref_type(t)); if (ds->qualifier & TYPE_QUALIFIER_CONST) fprintf(h, "const "); break; @@ -360,14 +361,14 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b fprintf(h, "%s", t->name); else { - write_type_left(h, type_array_get_element(t), name_type, define, !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), false); 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, define, TRUE); + write_type_left(h, type_function_get_ret(t), name_type, define, TRUE, false);
/* 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 +447,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b case TYPE_BITFIELD: { const decl_spec_t ds = {.type = type_bitfield_get_field(t)}; - write_type_left(h, &ds, name_type, define, TRUE); + write_type_left(h, &ds, name_type, define, TRUE, false); break; } case TYPE_ALIAS: @@ -548,7 +549,7 @@ static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, bool defi
if (!h) return;
- if (t) write_type_left(h, ds, name_type, define, TRUE); + if (t) write_type_left(h, ds, name_type, define, TRUE, false);
if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
@@ -570,14 +571,14 @@ static void write_type_definition(FILE *f, type_t *t, bool define) write_namespace_start(f, t->namespace); } indent(f, 0); - write_type_left(f, &ds, NAME_DEFAULT, define, TRUE); + write_type_left(f, &ds, NAME_DEFAULT, define, TRUE, false); 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, define, TRUE); + write_type_left(f, &ds, NAME_C, define, TRUE, false); fprintf(f, ";\n"); if (winrt_mode) write_widl_using_macros(f, t); fprintf(f, "#endif\n\n"); @@ -592,7 +593,7 @@ void write_type_decl(FILE *f, const decl_spec_t *t, const char *name)
void write_type_decl_left(FILE *f, const decl_spec_t *ds) { - write_type_left(f, ds, NAME_DEFAULT, false, TRUE); + write_type_left(f, ds, NAME_DEFAULT, false, TRUE, false); }
static int user_type_registered(const char *name) diff --git a/tools/widl/header.h b/tools/widl/header.h index 45066898a66..da5a3d1075c 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -24,7 +24,8 @@ #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, bool define, 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, bool noconst); 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/typegen.c b/tools/widl/typegen.c index 1db6ee5093b..d3c7749d216 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, false, TRUE ); + write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE, 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, false, TRUE ); + write_type_left( file, &retval->declspec, NAME_DEFAULT, false, TRUE, 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, false, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE, false); fprintf(file, " *%s = (", var_name); - write_type_left(file, &ds, NAME_DEFAULT, false, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE, false); fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); } print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */