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

Alexandre Julliard julliard at winehq.org
Mon Jul 24 15:51:20 CDT 2017


Module: wine
Branch: master
Commit: b42a15513eaa973b40ab967014b311af64acbb98
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b42a15513eaa973b40ab967014b311af64acbb98

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Fri Jul 21 13:03:41 2017 +0200

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
fabfa59aea5c5b3201142382038beb3e76cb7567, 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
fabfa59aea5c5b3201142382038beb3e76cb7567: 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: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 tools/widl/header.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index e48b488..b5fe232 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -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");
     }
   }




More information about the wine-cvs mailing list