[PATCH 6/7] widl: Use C++ template implementation for parameterized types.

Rémi Bernon rbernon at codeweavers.com
Mon Feb 22 03:03:04 CST 2021


Based on a patch from Steve Lhomme.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 tools/widl/header.c    | 21 +++++++++++------
 tools/widl/typetree.c  | 52 ++++++++++++++++++++++++++++++++++++++----
 tools/widl/typetree.h  |  6 +++++
 tools/widl/widltypes.h |  1 +
 4 files changed, 68 insertions(+), 12 deletions(-)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index aad31e7ba4e..b8fe3c1c445 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1591,10 +1591,12 @@ static void write_forward(FILE *header, type_t *iface)
   fprintf(header, "#ifdef __cplusplus\n");
   if (iface->namespace && !is_global_namespace(iface->namespace))
     fprintf(header, "#define %s %s\n", iface->c_name, iface->qualified_name);
-  write_namespace_start(header, iface->namespace);
-  if (strchr(iface->name, '<')) write_line(header, 0, "template<> struct %s;", iface->name);
-  else write_line(header, 0, "interface %s;", iface->name);
-  write_namespace_end(header, iface->namespace);
+  if (!iface->impl_name)
+  {
+    write_namespace_start(header, iface->namespace);
+    write_line(header, 0, "interface %s;", iface->name);
+    write_namespace_end(header, iface->namespace);
+  }
   fprintf(header, "#endif /* __cplusplus */\n");
   fprintf(header, "#endif\n\n" );
 }
@@ -1720,7 +1722,12 @@ static void write_com_interface_end(FILE *header, type_t *iface)
       if (strchr(iface->name, '<')) fprintf(header, "template<> struct ");
       else fprintf(header, "interface ");
   }
-  if (type_iface_get_inherit(iface))
+  if (iface->impl_name)
+  {
+    fprintf(header, "%s : %s\n", iface->name, iface->impl_name);
+    write_line(header, 1, "{");
+  }
+  else if (type_iface_get_inherit(iface))
   {
     fprintf(header, "%s : public %s\n", iface->name,
             type_iface_get_inherit(iface)->name);
@@ -1734,9 +1741,9 @@ static void write_com_interface_end(FILE *header, type_t *iface)
   }
   /* dispinterfaces don't have real functions, so don't write C++ functions for
    * them */
-  if (!dispinterface)
+  if (!dispinterface && !iface->impl_name)
     write_cpp_method_def(header, iface);
-  if (!type_iface_get_inherit(iface))
+  if (!type_iface_get_inherit(iface) && !iface->impl_name)
     write_line(header, 0, "END_INTERFACE\n");
   write_line(header, -1, "};");
   if (!is_global_namespace(iface->namespace)) {
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index e16b7713e91..090a16ba182 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -53,6 +53,7 @@ type_t *make_type(enum type_type type)
     t->signature = NULL;
     t->qualified_name = NULL;
     t->short_name = NULL;
+    t->impl_name = NULL;
     memset(&t->details, 0, sizeof(t->details));
     t->typestring_offset = 0;
     t->ptrdesc = 0;
@@ -128,6 +129,13 @@ static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct name
     return n;
 }
 
+static size_t append_pointer_stars(char **buf, size_t *len, size_t pos, type_t *type)
+{
+    size_t n = 0;
+    for (; type && type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) n += strappend(buf, len, pos + n, "*");
+    return n;
+}
+
 static size_t append_type_signature(char **buf, size_t *len, size_t pos, type_t *type);
 
 static size_t append_var_list_signature(char **buf, size_t *len, size_t pos, var_list_t *var_list)
@@ -267,9 +275,9 @@ char *format_parameterized_type_name(type_t *type, typeref_list_t *params)
     pos += strappend(&buf, &len, pos, "%s<", type->name);
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
-        for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
-        pos += append_namespaces(&buf, &len, pos, type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL);
-        for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) pos += strappend(&buf, &len, pos, "*");
+        type = type_pointer_get_root_type(ref->type);
+        pos += strappend(&buf, &len, pos, "%s", type->qualified_name);
+        pos += append_pointer_stars(&buf, &len, pos, ref->type);
         if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ",");
     }
     pos += strappend(&buf, &len, pos, ">");
@@ -293,7 +301,7 @@ static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *para
     pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count);
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
-        for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
+        type = type_pointer_get_root_type(ref->type);
         pos += append_namespaces(&buf, &len, pos, type->namespace, "_", "__C", type->name, NULL);
     }
 
@@ -344,13 +352,45 @@ static char *format_parameterized_type_short_name(type_t *type, typeref_list_t *
     pos += strappend(&buf, &len, pos, "%s%s", prefix, type->name);
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
-        for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
+        type = type_pointer_get_root_type(ref->type);
         pos += strappend(&buf, &len, pos, "_%s", type->name);
     }
 
     return buf;
 }
 
+static char *format_parameterized_type_impl_name(type_t *type, typeref_list_t *params, const char *prefix)
+{
+    size_t len = 0, pos = 0;
+    char *buf = NULL;
+    typeref_t *ref;
+    type_t *iface;
+
+    pos += strappend(&buf, &len, pos, "%s%s_impl<", prefix, type->name);
+    if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
+    {
+        type = type_pointer_get_root_type(ref->type);
+        if (type->type_type == TYPE_RUNTIMECLASS)
+        {
+            pos += strappend(&buf, &len, pos, "ABI::Windows::Foundation::Internal::AggregateType<%s", type->qualified_name);
+            pos += append_pointer_stars(&buf, &len, pos, ref->type);
+            iface = type_runtimeclass_get_default_iface(type);
+            pos += strappend(&buf, &len, pos, ", %s", iface->qualified_name);
+            pos += append_pointer_stars(&buf, &len, pos, ref->type);
+            pos += strappend(&buf, &len, pos, ">");
+        }
+        else
+        {
+            pos += strappend(&buf, &len, pos, "%s", type->qualified_name);
+            pos += append_pointer_stars(&buf, &len, pos, ref->type);
+        }
+        if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", ");
+    }
+    pos += strappend(&buf, &len, pos, ">");
+
+    return buf;
+}
+
 type_t *type_new_function(var_list_t *args)
 {
     var_t *arg;
@@ -1245,11 +1285,13 @@ type_t *type_parameterized_type_specialize_define(type_t *type)
         error_loc("pinterface/pdelegate %s previously not declared a pinterface/pdelegate at %s:%d\n",
                   iface->name, iface->loc_info.input_name, iface->loc_info.line_number);
 
+    iface->impl_name = format_parameterized_type_impl_name(type, repl, "");
     iface->signature = format_parameterized_type_signature(type, repl);
     iface->defined = TRUE;
     if (iface->type_type == TYPE_DELEGATE)
     {
         iface = iface->details.delegate.iface;
+        iface->impl_name = format_parameterized_type_impl_name(type, repl, "I");
         iface->signature = format_parameterized_type_signature(type, repl);
         iface->defined = TRUE;
     }
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 0b7cd385cc2..b9833dc4e8f 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -411,6 +411,12 @@ static inline type_t *type_pointer_get_ref_type(const type_t *type)
     return type_pointer_get_ref(type)->type;
 }
 
+static inline type_t *type_pointer_get_root_type(type_t *type)
+{
+    for (; type && type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
+    return type;
+}
+
 static inline type_t *type_bitfield_get_field(const type_t *type)
 {
     type = type_get_real_type(type);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index bedba40d903..7c4465418dd 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -505,6 +505,7 @@ struct _type_t {
   const char *signature;
   const char *qualified_name;
   const char *short_name;
+  const char *impl_name;
   unsigned int typestring_offset;
   unsigned int ptrdesc;           /* used for complex structs */
   int typelib_idx;
-- 
2.30.0




More information about the wine-devel mailing list