Commit b42a1551 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

widl: Handle C++ aggregate returns in a MSVC compatible way.

This mainly affects 64-bit winelib applications, and potentially mingw-w64 usage of the Wine headers. As explained in commit fabfa59a, MSVC returns aggregates through an implicit parameter immediately after the this/interface pointer. GCC's "ms_abi" attribute is supposed to match this, but unfortunately current versions of g++ (confirmed up to at least g++ 6.3) place the implicit return pointer before the this/interface pointer. See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52792. This commit takes an approach similar to the earlier commit fabfa59a: For ABI compatibility the return pointer is listed as an explicit parameter in the vtbl entry, while an inline helper is provided for source code compatibility. Signed-off-by: 's avatarHenri Verbeet <hverbeet@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent f91b4bd4
......@@ -1043,13 +1043,62 @@ static void write_cpp_method_def(FILE *header, const type_t *iface)
const var_t *func = stmt->u.var;
if (!is_callas(func->attrs)) {
const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
const var_list_t *args = type_get_function_args(func->type);
const var_t *arg;
if (!callconv) callconv = "STDMETHODCALLTYPE";
if (is_aggregate_return(func)) {
fprintf(header, "#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS\n");
indent(header, 0);
fprintf(header, "virtual ");
write_type_decl_left(header, type_function_get_rettype(func->type));
fprintf(header, "* %s %s(\n", callconv, get_name(func));
++indentation;
indent(header, 0);
write_type_decl_left(header, type_function_get_rettype(func->type));
fprintf(header, " *__ret");
--indentation;
if (args) {
fprintf(header, ",\n");
write_args(header, args, iface->name, 2, TRUE);
}
fprintf(header, ") = 0;\n");
indent(header, 0);
write_type_decl_left(header, type_function_get_rettype(func->type));
fprintf(header, " %s %s(\n", callconv, get_name(func));
write_args(header, args, iface->name, 2, TRUE);
fprintf(header, ")\n");
indent(header, 0);
fprintf(header, "{\n");
++indentation;
indent(header, 0);
write_type_decl_left(header, type_function_get_rettype(func->type));
fprintf(header, " __ret;\n");
indent(header, 0);
fprintf(header, "return *%s(&__ret", get_name(func));
if (args)
LIST_FOR_EACH_ENTRY(arg, args, const var_t, entry)
fprintf(header, ", %s", arg->name);
fprintf(header, ");\n");
--indentation;
indent(header, 0);
fprintf(header, "}\n");
fprintf(header, "#else\n");
}
indent(header, 0);
fprintf(header, "virtual ");
write_type_decl_left(header, type_function_get_rettype(func->type));
fprintf(header, " %s %s(\n", callconv, get_name(func));
write_args(header, type_get_function_args(func->type), iface->name, 2, TRUE);
write_args(header, args, iface->name, 2, TRUE);
fprintf(header, ") = 0;\n");
if (is_aggregate_return(func))
fprintf(header, "#endif\n");
fprintf(header, "\n");
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment