From: "Rémi Bernon" Subject: [PATCH 6/7] widl: Use C++ template implementation for parameterized types. Message-Id: <20210222090305.557337-6-rbernon@codeweavers.com> Date: Mon, 22 Feb 2021 10:03:04 +0100 In-Reply-To: <20210222090305.557337-1-rbernon@codeweavers.com> References: <20210222090305.557337-1-rbernon@codeweavers.com> Based on a patch from Steve Lhomme. Signed-off-by: Rémi Bernon --- 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