MinGW g++ requires initialized selectany to have extern linkage.
When supported, we define WCHAR as char16_t, which requires u"" string literal. When not supported, and when WCHAR is unsigned short, it then requires to use an array initializer instead of a L"" string literal.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index a472af49066..23de3e12aca 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1836,8 +1836,18 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n"); + fprintf(header, "#ifdef __cplusplus\n"); + fprintf(header, "#if defined(WINE_UNICODE_NATIVE)\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#else\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name); + for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]); + fprintf(header, "0};\n"); + fprintf(header, "#endif /* __cplusplus */\n"); + fprintf(header, "#else\n"); /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */ fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#endif\n"); fprintf(header, "#else\n"); fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name); for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.collections.idl | 4 ++-- tools/widl/typetree.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/windows.foundation.collections.idl b/include/windows.foundation.collections.idl index cf47adfa7e4..ed05016b96d 100644 --- a/include/windows.foundation.collections.idl +++ b/include/windows.foundation.collections.idl @@ -34,8 +34,8 @@ cpp_quote("namespace ABI { namespace Windows { namespace Foundation { namespace cpp_quote("template <class T> struct GetAbiType { typedef T type; };") cpp_quote("template <class T> struct GetLogicalType { typedef T type; };") cpp_quote("template <class L, class A> struct AggregateType {};") -cpp_quote("template <class L, class A> struct GetAbiType<AggregateType<L, A>> { typedef A type; };") -cpp_quote("template <class L, class A> struct GetLogicalType<AggregateType<L, A>> { typedef L type; };") +cpp_quote("template <class L, class A> struct GetAbiType<AggregateType<L, A> > { typedef A type; };") +cpp_quote("template <class L, class A> struct GetLogicalType<AggregateType<L, A> > { typedef L type; };") cpp_quote("}}}}") cpp_quote("extern "C" {") cpp_quote("#endif") diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index eec98e5c23c..6522e09dacf 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -279,7 +279,7 @@ char *format_parameterized_type_name(type_t *type, typeref_list_t *params) 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, ">"); + pos += strappend(&buf, &len, pos, " >");
return buf; } @@ -360,7 +360,7 @@ static char *format_parameterized_type_impl_name(type_t *type, typeref_list_t *p 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, ">"); + pos += strappend(&buf, &len, pos, " >"); } else { @@ -369,7 +369,7 @@ static char *format_parameterized_type_impl_name(type_t *type, typeref_list_t *p } if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", "); } - pos += strappend(&buf, &len, pos, ">"); + pos += strappend(&buf, &len, pos, " >");
return buf; }
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/typetree.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 6522e09dacf..9220cfb50e9 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -124,7 +124,12 @@ static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct name size_t n = 0; n += strappend(buf, len, pos + n, "%s", prefix); if (nested) n += append_namespace(buf, len, pos + n, namespace, separator, abi_prefix); - n += strappend(buf, len, pos + n, "%s", suffix); + if (suffix) n += strappend(buf, len, pos + n, "%s", suffix); + else if (nested) + { + n -= strlen(separator); + (*buf)[n] = 0; + } return n; }
Signed-off-by: Jacek Caban jacek@codeweavers.com
This generates additional macros to help keeping implementation simple, guarded with WIDL_using ifdefs, like this:
#ifdef WIDL_using_Windows_Foo #define IFooVtbl __x_ABI_CWindows_CFoo_CIFooVtbl #define IFoo __x_ABI_CWindows_CFoo_CIFoo #define IFoo_DoFoo __x_ABI_CWindows_CFoo_CIFoo_DoFoo #endif /* WIDL_using_Windows_Foo */
Implementation files can define the desired WIDL_using preprocessor macros before including the header, and then implement or use the interface methods with the simple non-prefixed names instead.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 45 ++++++++++++++++++++++++++++++++++++++++++ tools/widl/typetree.c | 19 ++++++++++++++++++ tools/widl/widltypes.h | 1 + 3 files changed, 65 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 23de3e12aca..9f36df9c641 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -48,6 +48,8 @@ static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declon static void write_apicontract_guard_start(FILE *header, const expr_t *expr); static void write_apicontract_guard_end(FILE *header, const expr_t *expr);
+static void write_widl_using_macros(FILE *header, type_t *iface); + static void indent(FILE *h, int delta) { int c; @@ -634,6 +636,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) fprintf(f, "#else\n"); write_type_left(f, &ds, NAME_C, declonly, TRUE); fprintf(f, ";\n"); + if (winrt_mode) write_widl_using_macros(f, t); fprintf(f, "#endif\n\n"); } if (contract) write_apicontract_guard_end(f, contract); @@ -1644,6 +1647,47 @@ static void write_com_interface_start(FILE *header, const type_t *iface) fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); }
+static void write_widl_using_method_macros(FILE *header, const type_t *iface, const type_t *top_iface) +{ + const statement_t *stmt; + const char *name = top_iface->short_name ? top_iface->short_name : top_iface->name; + + if (type_iface_get_inherit(iface)) write_widl_using_method_macros(header, type_iface_get_inherit(iface), top_iface); + + STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) + { + const var_t *func = stmt->u.var; + const char *func_name; + + if (is_override_method(iface, top_iface, func)) continue; + if (is_callas(func->attrs)) continue; + + func_name = get_name(func); + fprintf(header, "#define %s_%s %s_%s\n", name, func_name, top_iface->c_name, func_name); + } +} + +static void write_widl_using_macros(FILE *header, type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + const char *name = iface->short_name ? iface->short_name : iface->name; + char *macro; + + if (!strcmp(iface->name, iface->c_name)) return; + + macro = format_namespace(iface->namespace, "WIDL_using_", "_", NULL, NULL); + fprintf(header, "#ifdef %s\n", macro); + + if (uuid) fprintf(header, "#define IID_%s IID_%s\n", name, iface->c_name); + if (iface->type_type == TYPE_INTERFACE) fprintf(header, "#define %sVtbl %sVtbl\n", name, iface->c_name); + fprintf(header, "#define %s %s\n", name, iface->c_name); + + if (iface->type_type == TYPE_INTERFACE) write_widl_using_method_macros(header, iface, iface); + + fprintf(header, "#endif /* %s */\n", macro); + free(macro); +} + static void write_com_interface_end(FILE *header, type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); @@ -1721,6 +1765,7 @@ static void write_com_interface_end(FILE *header, type_t *iface) fprintf(header, "#else\n"); write_inline_wrappers(header, type, type, iface->c_name); fprintf(header, "#endif\n"); + if (winrt_mode) write_widl_using_macros(header, iface); fprintf(header, "#endif\n"); fprintf(header, "\n"); fprintf(header, "#endif\n"); diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 9220cfb50e9..a1e7abc31e5 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->impl_name = NULL; + t->short_name = NULL; memset(&t->details, 0, sizeof(t->details)); t->typestring_offset = 0; t->ptrdesc = 0; @@ -347,6 +348,22 @@ static char *format_parameterized_type_signature(type_t *type, typeref_list_t *p return buf; }
+static char *format_parameterized_type_short_name(type_t *type, typeref_list_t *params, const char *prefix) +{ + size_t len = 0, pos = 0; + char *buf = NULL; + typeref_t *ref; + + pos += strappend(&buf, &len, pos, "%s%s", prefix, type->name); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + 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; @@ -1201,11 +1218,13 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t new_type->name = format_parameterized_type_name(type, params); reg_type(new_type, new_type->name, new_type->namespace, 0); new_type->c_name = format_parameterized_type_c_name(type, params, ""); + new_type->short_name = format_parameterized_type_short_name(type, params, "");
if (new_type->type_type == TYPE_DELEGATE) { new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0); compute_delegate_iface_names(new_type, type, params); + new_type->details.delegate.iface->short_name = format_parameterized_type_short_name(type, params, "I"); }
return new_type; diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index d37d732744b..0ecd8f34d6a 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 *impl_name; + const char *short_name; unsigned int typestring_offset; unsigned int ptrdesc; /* used for complex structs */ int typelib_idx;
Signed-off-by: Jacek Caban jacek@codeweavers.com
On 2/26/21 9:43 AM, Rémi Bernon wrote:
MinGW g++ requires initialized selectany to have extern linkage.
When supported, we define WCHAR as char16_t, which requires u"" string literal. When not supported, and when WCHAR is unsigned short, it then requires to use an array initializer instead of a L"" string literal.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
tools/widl/header.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index a472af49066..23de3e12aca 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1836,8 +1836,18 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n");
- fprintf(header, "#ifdef __cplusplus\n");
- fprintf(header, "#if defined(WINE_UNICODE_NATIVE)\n");
- fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name);
- fprintf(header, "#else\n");
- fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name);
- for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
- fprintf(header, "0};\n");
- fprintf(header, "#endif /* __cplusplus */\n");
Oops, this should probably be one line below to match the corresponding #if... I'll send a v2.
- fprintf(header, "#else\n"); /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */ fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name);
- fprintf(header, "#endif\n"); fprintf(header, "#else\n"); fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name); for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
MinGW g++ requires initialized selectany to have extern linkage.
When supported, we define WCHAR as char16_t, which requires u"" string literal. When not supported, and when WCHAR is unsigned short, it then requires to use an array initializer instead of a L"" string literal.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index a472af49066..8993038baca 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1836,8 +1836,18 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n"); + fprintf(header, "#ifdef __cplusplus\n"); + fprintf(header, "#if defined(WINE_UNICODE_NATIVE)\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#else\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name); + for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]); + fprintf(header, "0};\n"); + fprintf(header, "#endif\n"); + fprintf(header, "#else /* __cplusplus */\n"); /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */ fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#endif\n"); fprintf(header, "#else\n"); fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name); for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
On 2/26/21 9:47 AM, Rémi Bernon wrote:
MinGW g++ requires initialized selectany to have extern linkage.
When supported, we define WCHAR as char16_t, which requires u"" string literal. When not supported, and when WCHAR is unsigned short, it then requires to use an array initializer instead of a L"" string literal.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
tools/widl/header.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index a472af49066..8993038baca 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1836,8 +1836,18 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n");
- fprintf(header, "#ifdef __cplusplus\n");
- fprintf(header, "#if defined(WINE_UNICODE_NATIVE)\n");
- fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name);
- fprintf(header, "#else\n");
- fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name);
- for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
- fprintf(header, "0};\n");
- fprintf(header, "#endif\n");
- fprintf(header, "#else /* __cplusplus */\n"); /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */ fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name);
- fprintf(header, "#endif\n"); fprintf(header, "#else\n"); fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name); for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
The commit comment is also a bit inaccurate too now, as I late folded the u"" string literal case with the array initializer, trying to keep things simple... Sorry.
Not sure if it's worth another version, the details could probably be cut, just tell me.
Hi Rémi,
On 26.02.2021 09:43, Rémi Bernon wrote:
MinGW g++ requires initialized selectany to have extern linkage.
When supported, we define WCHAR as char16_t, which requires u"" string literal. When not supported, and when WCHAR is unsigned short, it then requires to use an array initializer instead of a L"" string literal.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
tools/widl/header.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index a472af49066..23de3e12aca 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1836,8 +1836,18 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n");
- fprintf(header, "#ifdef __cplusplus\n");
- fprintf(header, "#if defined(WINE_UNICODE_NATIVE)\n");
- fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name);
- fprintf(header, "#else\n");
- fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name);
- for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
- fprintf(header, "0};\n");
If we need the second case anyway, then I'm not sure if there is a point in the first one. I would expect the {...} initializer to produce the same result without having to worry about actual WCHAR type. With that, maybe we could reorder things a bit to simplify it. Would something like that work?
#if !defined(__MINGW32__) && !defined(_MSC_VER)
static const WCHAR RuntimeClass_...[] = {...};
#elif defined(__GNUC__) && !defined(__cplusplus)
const DECLSPEC_SELECTANY WCHAR RuntimeClas_...[] = L"...";
#else
extern const DECLSPEC_SELECTANY WCHAR RuntimeClas_...[] = {...};
#endif
Thanks,
Jacek
On 2/26/21 1:46 PM, Jacek Caban wrote:
Hi Rémi,
On 26.02.2021 09:43, Rémi Bernon wrote:
MinGW g++ requires initialized selectany to have extern linkage.
When supported, we define WCHAR as char16_t, which requires u"" string literal. When not supported, and when WCHAR is unsigned short, it then requires to use an array initializer instead of a L"" string literal.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
tools/widl/header.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index a472af49066..23de3e12aca 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1836,8 +1836,18 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n"); + fprintf(header, "#ifdef __cplusplus\n"); + fprintf(header, "#if defined(WINE_UNICODE_NATIVE)\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#else\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name); + for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]); + fprintf(header, "0};\n");
If we need the second case anyway, then I'm not sure if there is a point in the first one. I would expect the {...} initializer to produce the same result without having to worry about actual WCHAR type. With that, maybe we could reorder things a bit to simplify it. Would something like that work?
#if !defined(__MINGW32__) && !defined(_MSC_VER)
static const WCHAR RuntimeClass_...[] = {...};
#elif defined(__GNUC__) && !defined(__cplusplus)
const DECLSPEC_SELECTANY WCHAR RuntimeClas_...[] = L"...";
#else
extern const DECLSPEC_SELECTANY WCHAR RuntimeClas_...[] = {...};
#endif
Thanks,
Jacek
Yeah, I guess it's more or less equivalent to folding my two __cplusplus cases above to use extern qualifier and an array initializer.