widl: Support WinRT delegate type.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Jacek Caban<jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-02-18 10:38:59 +01:00 committed by Alexandre Julliard
parent 6991d7befa
commit 2326d7226d
9 changed files with 104 additions and 5 deletions

View File

@ -466,6 +466,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
case TYPE_RUNTIMECLASS:
case TYPE_PARAMETERIZED_TYPE:
case TYPE_PARAMETER:
case TYPE_DELEGATE:
/* nothing to do */
break;
case TYPE_ALIAS:

View File

@ -470,6 +470,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
case TYPE_RUNTIMECLASS:
fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type));
break;
case TYPE_DELEGATE:
fprintf(h, "%s", type_get_name(type_delegate_get_iface(t), name_type));
break;
case TYPE_VOID:
fprintf(h, "void");
break;
@ -555,6 +558,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
case TYPE_COCLASS:
case TYPE_INTERFACE:
case TYPE_RUNTIMECLASS:
case TYPE_DELEGATE:
break;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@ -974,7 +978,7 @@ int has_out_arg_or_return(const var_t *func)
int is_object(const type_t *iface)
{
const attr_t *attr;
if (type_is_defined(iface) && type_iface_get_inherit(iface))
if (type_is_defined(iface) && (type_get_type(iface) == TYPE_DELEGATE || type_iface_get_inherit(iface)))
return 1;
if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry )
if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
@ -1799,9 +1803,10 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts)
switch (stmt->type)
{
case STMT_TYPE:
if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE)
{
type_t *iface = stmt->u.type;
if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface);
if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE))
{
write_forward(header, iface);
@ -1841,10 +1846,11 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
switch (stmt->type)
{
case STMT_TYPE:
if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE)
{
type_t *iface = stmt->u.type;
type_t *async_iface = type_iface_get_async_iface(iface);
type_t *iface = stmt->u.type, *async_iface;
if (type_get_type(stmt->u.type) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface);
async_iface = type_iface_get_async_iface(iface);
if (is_object(iface)) is_object_interface++;
if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type))
{

View File

@ -278,6 +278,7 @@ static const struct keyword keywords[] = {
{"cpp_quote", tCPPQUOTE, 0},
{"declare", tDECLARE, 1},
{"default", tDEFAULT, 0},
{"delegate", tDELEGATE, 1},
{"dispinterface", tDISPINTERFACE, 0},
{"double", tDOUBLE, 0},
{"enum", tENUM, 0},

View File

@ -106,6 +106,7 @@ static statement_t *make_statement_module(type_t *type);
static statement_t *make_statement_typedef(var_list_t *names, int declonly);
static statement_t *make_statement_import(const char *str);
static statement_t *make_statement_parameterized_type(type_t *type, typeref_list_t *params);
static statement_t *make_statement_delegate(type_t *ret, var_list_t *args);
static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt);
static statement_list_t *append_statements(statement_list_t *, statement_list_t *);
static attr_list_t *append_attribs(attr_list_t *, attr_list_t *);
@ -180,6 +181,7 @@ static typelib_t *current_typelib;
%token tCUSTOM
%token tDECLARE
%token tDECODE tDEFAULT tDEFAULTBIND
%token tDELEGATE
%token tDEFAULTCOLLELEM
%token tDEFAULTVALUE
%token tDEFAULTVTABLE
@ -278,6 +280,7 @@ static typelib_t *current_typelib;
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <expr> contract_req
%type <expr> static_attr
%type <type> delegatedef
%type <stgclass> storage_cls_spec
%type <type_qualifier> type_qualifier m_type_qual_list
%type <function_specifier> function_specifier
@ -384,6 +387,7 @@ gbl_statements: { $$ = NULL; }
| gbl_statements interface ';' { $$ = append_statement($1, make_statement_reference($2)); }
| gbl_statements dispinterface ';' { $$ = append_statement($1, make_statement_reference($2)); }
| gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); }
| gbl_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); }
| gbl_statements coclass ';' { $$ = $1;
reg_type($2, $2->name, current_namespace, 0);
}
@ -408,6 +412,7 @@ imp_statements: { $$ = NULL; }
| imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}'
{ pop_namespace($2); $$ = append_statements($1, $5); }
| imp_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); }
| imp_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); }
| imp_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); }
| imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2));
reg_type($2, $2->name, current_namespace, 0);
@ -1029,6 +1034,12 @@ interface:
{ $$ = type_parameterized_interface_declare($2, current_namespace, $5); }
;
delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt
{ $$ = type_delegate_declare($4->name, current_namespace);
$$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6)));
}
;
required_types:
qualified_type { $$ = append_typeref(NULL, make_typeref($1)); }
| parameterized_type { $$ = append_typeref(NULL, make_typeref($1)); }
@ -2663,6 +2674,7 @@ static int is_allowed_conf_type(const type_t *type)
case TYPE_INTERFACE:
case TYPE_BITFIELD:
case TYPE_RUNTIMECLASS:
case TYPE_DELEGATE:
return FALSE;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@ -3299,6 +3311,14 @@ static statement_t *make_statement_parameterized_type(type_t *type, typeref_list
return stmt;
}
static statement_t *make_statement_delegate(type_t *ret, var_list_t *args)
{
declarator_t *decl = make_declarator(make_var(xstrdup("Invoke")));
decl_spec_t *spec = make_decl_spec(ret, NULL, NULL, STG_NONE, 0, 0);
append_chain_type(decl, type_new_function(args), 0);
return make_statement_declaration(declare_var(NULL, spec, decl, FALSE));
}
static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2)
{
if (!l2) return l1;

View File

@ -354,6 +354,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
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_RUNTIMECLASS ||
type_get_type(type_pointer_get_ref_type(type)) == TYPE_DELEGATE ||
(type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS)))
return TGT_IFACE_POINTER;
else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE))
@ -375,6 +376,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
case TYPE_ALIAS:
case TYPE_BITFIELD:
case TYPE_RUNTIMECLASS:
case TYPE_DELEGATE:
break;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@ -1978,6 +1980,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
case TYPE_RUNTIMECLASS:
case TYPE_PARAMETERIZED_TYPE:
case TYPE_PARAMETER:
case TYPE_DELEGATE:
/* these types should not be encountered here due to language
* restrictions (interface, void, coclass, module), logical
* restrictions (alias - due to type_get_type call above) or
@ -2083,6 +2086,7 @@ static unsigned int type_buffer_alignment(const type_t *t)
case TYPE_RUNTIMECLASS:
case TYPE_PARAMETERIZED_TYPE:
case TYPE_PARAMETER:
case TYPE_DELEGATE:
/* these types should not be encountered here due to language
* restrictions (interface, void, coclass, module), logical
* restrictions (alias - due to type_get_type call above) or

View File

@ -219,6 +219,7 @@ unsigned short get_type_vt(type_t *t)
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TYPE_RUNTIMECLASS:
case TYPE_DELEGATE:
return VT_USERDEFINED;
case TYPE_VOID:

View File

@ -664,6 +664,54 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs)
return apicontract;
}
static void compute_delegate_iface_names(type_t *delegate)
{
type_t *iface = delegate->details.delegate.iface;
iface->namespace = delegate->namespace;
iface->name = strmake("I%s", delegate->name);
iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL);
}
type_t *type_delegate_declare(char *name, struct namespace *namespace)
{
type_t *type = get_type(TYPE_DELEGATE, name, NULL, 0);
if (type_get_type_detect_alias(type) != TYPE_DELEGATE)
error_loc("delegate %s previously not declared a delegate at %s:%d\n",
type->name, type->loc_info.input_name, type->loc_info.line_number);
return type;
}
type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts)
{
type_t *iface;
if (delegate->defined)
error_loc("delegate %s already defined at %s:%d\n",
delegate->name, delegate->loc_info.input_name, delegate->loc_info.line_number);
delegate->attrs = check_interface_attrs(delegate->name, attrs);
iface = make_type(TYPE_INTERFACE);
iface->attrs = delegate->attrs;
iface->details.iface = xmalloc(sizeof(*iface->details.iface));
iface->details.iface->disp_props = NULL;
iface->details.iface->disp_methods = NULL;
iface->details.iface->stmts = stmts;
iface->details.iface->inherit = find_type("IUnknown", NULL, 0);
if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n");
iface->details.iface->disp_inherit = NULL;
iface->details.iface->async_iface = NULL;
iface->details.iface->requires = NULL;
iface->defined = TRUE;
compute_method_indexes(iface);
delegate->details.delegate.iface = iface;
delegate->defined = TRUE;
compute_delegate_iface_names(delegate);
return delegate;
}
type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params)
{
type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0);
@ -821,6 +869,7 @@ static type_t *replace_type_parameters_in_type(type_t *type, typeref_list_t *ori
case TYPE_BITFIELD:
case TYPE_INTERFACE:
case TYPE_RUNTIMECLASS:
case TYPE_DELEGATE:
return type;
case TYPE_PARAMETER:
if (!orig || !repl) return NULL;

View File

@ -64,6 +64,8 @@ type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, typeref_list_t
type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, typeref_list_t *ifaces);
type_t *type_apicontract_declare(char *name, struct namespace *namespace);
type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs);
type_t *type_delegate_declare(char *name, struct namespace *namespace);
type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts);
type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params);
type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires);
type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params);
@ -254,6 +256,7 @@ static inline int type_is_complete(const type_t *type)
case TYPE_ARRAY:
case TYPE_BITFIELD:
case TYPE_RUNTIMECLASS:
case TYPE_DELEGATE:
return TRUE;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@ -376,6 +379,13 @@ static inline type_t *type_runtimeclass_get_default_iface(const type_t *type)
return NULL;
}
static inline type_t *type_delegate_get_iface(const type_t *type)
{
type = type_get_real_type(type);
assert(type_get_type(type) == TYPE_DELEGATE);
return type->details.delegate.iface;
}
static inline const decl_spec_t *type_pointer_get_ref(const type_t *type)
{
type = type_get_real_type(type);

View File

@ -441,6 +441,11 @@ struct parameterized_details
typeref_list_t *params;
};
struct delegate_details
{
type_t *iface;
};
#define HASHMAX 64
struct namespace {
@ -471,6 +476,7 @@ enum type_type
TYPE_RUNTIMECLASS,
TYPE_PARAMETERIZED_TYPE,
TYPE_PARAMETER,
TYPE_DELEGATE,
};
struct _type_t {
@ -493,6 +499,7 @@ struct _type_t {
struct alias_details alias;
struct runtimeclass_details runtimeclass;
struct parameterized_details parameterized;
struct delegate_details delegate;
} details;
const char *c_name;
unsigned int typestring_offset;