From: "Rémi Bernon" Subject: [PATCH v3 4/5] widl: Implement initial support for generics. Message-Id: <20200903124203.2460412-4-rbernon@codeweavers.com> Date: Thu, 3 Sep 2020 14:42:02 +0200 In-Reply-To: <20200903124203.2460412-1-rbernon@codeweavers.com> References: <20200903124203.2460412-1-rbernon@codeweavers.com> This allows the following syntax: #ifdef __WIDL__ #pragma winrt ns_prefix #endif import "wtypes.idl"; namespace Windows { namespace Foo { [object] interface IFoo { HRESULT DoFoo([in] T value, [out, retval] U *out_value); } } namespace Bar { [object] interface IBaz {} [object] interface IBar { HRESULT DoBar([in] Windows.Foo.IFoo *foo); } } } Generating the following IFoo method: HRESULT (STDMETHODCALLTYPE *DoFoo)( __x_ABI_CWindows_CFoo_CIFoo *This, void*/*__x_ABI_CWindows_CFoo_CIFoo_CT*/ value, void*/*__x_ABI_CWindows_CFoo_CIFoo_CU*/ *out_value); And the following (unchanged) IBar method: HRESULT (STDMETHODCALLTYPE *DoBar)( __x_ABI_CWindows_CBar_CIBar *This, __x_ABI_CWindows_CFoo_CIFoo *foo); It should be enough to add the UWP dll stubs in idl files, but it's casting generics to void*. MIDL does something different apparently and even generates a new interface for every parameter type. Signed-off-by: Rémi Bernon --- tools/widl/expr.c | 1 + tools/widl/header.c | 4 ++++ tools/widl/parser.y | 27 +++++++++++++++++++++++---- tools/widl/typegen.c | 4 ++++ tools/widl/typelib.c | 1 + tools/widl/typetree.h | 1 + tools/widl/widltypes.h | 1 + 7 files changed, 35 insertions(+), 4 deletions(-) diff --git a/tools/widl/expr.c b/tools/widl/expr.c index d1ee599a39e..950a1e46b6f 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -460,6 +460,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_COCLASS: case TYPE_INTERFACE: case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_ARRAY: case TYPE_BITFIELD: /* nothing to do */ diff --git a/tools/widl/header.c b/tools/widl/header.c index c8a12556cc9..fcc73169d00 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -454,6 +454,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i case TYPE_COCLASS: fprintf(h, "%s", name); break; + case TYPE_GENERIC: + fprintf(h, "void*/*%s*/", name); + break; case TYPE_VOID: fprintf(h, "void"); break; @@ -518,6 +521,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_BITFIELD: fprintf(h, " : %u", type_bitfield_get_bits(t)->cval); break; + case TYPE_GENERIC: case TYPE_VOID: case TYPE_BASIC: case TYPE_ENUM: diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 7d5aaebf339..324836565a9 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -274,7 +274,7 @@ static typelib_t *current_typelib; %type namespacedef %type base_type int_std %type enumdef structdef uniondef typedecl -%type type qualified_seq qualified_type +%type type qualified_seq qualified_type generics_type generics_decl %type coclass_int %type coclass_ints %type arg ne_union_field union_field s_field case enum declaration @@ -830,6 +830,11 @@ qualified_type: | aNAMESPACE '.' { init_lookup_namespace($1); } qualified_seq { $$ = $4; } ; +generics_list: generics_type | generics_type '*' | generics_list ',' generics_list; +generics_args: | '<' generics_list '>'; + +generics_type: qualified_type generics_args; + coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); if (type_get_type_detect_alias($$) != TYPE_COCLASS) @@ -895,13 +900,16 @@ dispinterfacedef: dispinterfacehdr '{' ; inherit: { $$ = NULL; } - | ':' qualified_type { $$ = $2; } + | ':' generics_type { $$ = $2; } ; interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } | tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } ; +generics_decl: aIDENTIFIER { $$ = get_type(TYPE_GENERIC, $1, current_namespace, 0); }; +generics_decls: generics_decl | generics_decls ',' generics_decls; + interfacehdr: attributes interface { $$ = $2; check_def($2); $2->attrs = check_iface_attrs($2->name, $1); @@ -923,11 +931,21 @@ interfacedef: interfacehdr inherit semicolon_opt { $$ = $1; type_interface_define($$, find_type_or_error2($3, 0), $6); } + | interfacehdr + '<' { push_namespace($1->name); } generics_decls '>' inherit + '{' int_statements '}' semicolon_opt + { + $$ = $1; + if($$ == $6) error_loc("Interface can't inherit from itself\n"); + type_interface_define($$, $6, $8); + check_async_uuid($$); + pop_namespace($1->name); + } | dispinterfacedef semicolon_opt { $$ = $1; } ; interfacedec: - interface ';' { $$ = $1; } + interface generics_args ';' { $$ = $1; } | dispinterface ';' { $$ = $1; } ; @@ -1110,7 +1128,7 @@ structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, current_nam ; type: tVOID { $$ = type_new_void(); } - | qualified_type { $$ = $1; } + | generics_type { $$ = $1; } | base_type { $$ = $1; } | enumdef { $$ = $1; } | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } @@ -2422,6 +2440,7 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_ENCAPSULATED_UNION: case TYPE_ARRAY: case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_VOID: case TYPE_MODULE: case TYPE_COCLASS: diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 04280cbb722..f872e039010 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -351,6 +351,8 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE))) return TGT_RANGE; return TGT_ENUM; + case TYPE_GENERIC: + return TGT_IFACE_POINTER; case TYPE_POINTER: if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) @@ -1936,6 +1938,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) size = union_memsize(type_union_get_cases(t), align); break; case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_INTERFACE: assert( pointer_size ); size = pointer_size; @@ -2060,6 +2063,7 @@ static unsigned int type_buffer_alignment(const type_t *t) /* else fall through */ case TYPE_POINTER: return 4; + case TYPE_GENERIC: case TYPE_INTERFACE: case TYPE_ALIAS: case TYPE_VOID: diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c index cf027558d0a..060ef45218a 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -193,6 +193,7 @@ unsigned short get_type_vt(type_t *t) break; case TYPE_POINTER: + case TYPE_GENERIC: return VT_PTR; case TYPE_ARRAY: diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index e288c574002..6afa5d25fe5 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -220,6 +220,7 @@ static inline int type_is_complete(const type_t *type) case TYPE_MODULE: case TYPE_COCLASS: case TYPE_POINTER: + case TYPE_GENERIC: case TYPE_ARRAY: case TYPE_BITFIELD: return TRUE; diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 085a0ff55f5..e957ef19c1a 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -431,6 +431,7 @@ enum type_type TYPE_POINTER, TYPE_ARRAY, TYPE_BITFIELD, + TYPE_GENERIC, }; struct _type_t { -- 2.28.0