widl: Support WinRT requires keyword.

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-09 10:37:21 +01:00 committed by Alexandre Julliard
parent 1442ddf942
commit daba929a52
5 changed files with 56 additions and 5 deletions

View File

@ -298,6 +298,7 @@ static const struct keyword keywords[] = {
{"pascal", tPASCAL, 0},
{"properties", tPROPERTIES, 0},
{"register", tREGISTER, 0},
{"requires", tREQUIRES, 1},
{"runtimeclass", tRUNTIMECLASS, 1},
{"short", tSHORT, 0},
{"signed", tSIGNED, 0},

View File

@ -240,6 +240,7 @@ static typelib_t *current_typelib;
%token tREADONLY tREF
%token tREGISTER tREPRESENTAS
%token tREQUESTEDIT
%token tREQUIRES
%token tRESTRICTED
%token tRETVAL
%token tRUNTIMECLASS
@ -293,6 +294,7 @@ static typelib_t *current_typelib;
%type <type> type unqualified_type qualified_type
%type <ifref> class_interface
%type <ifref_list> class_interfaces
%type <ifref_list> requires required_types
%type <var> arg ne_union_field union_field s_field case enum enum_member declaration
%type <var> funcdef
%type <var_list> m_args arg_list args dispint_meths
@ -967,8 +969,16 @@ inherit: { $$ = NULL; }
interface: tINTERFACE typename { $$ = type_interface_declare($2, current_namespace); }
;
interfacedef: attributes interface inherit
'{' int_statements '}' semicolon_opt { $$ = type_interface_define($2, $1, $3, $5);
required_types:
qualified_type { $$ = append_ifref(NULL, make_ifref($1)); }
| required_types ',' qualified_type { $$ = append_ifref($1, make_ifref($3)); }
requires: { $$ = NULL; }
| tREQUIRES required_types { $$ = $2; }
;
interfacedef: attributes interface inherit requires
'{' int_statements '}' semicolon_opt { $$ = type_interface_define($2, $1, $3, $6, $4);
check_async_uuid($$);
}
| dispinterfacedef semicolon_opt { $$ = $1; }
@ -2981,7 +2991,7 @@ static void check_async_uuid(type_t *iface)
stmts = append_statement(stmts, make_statement_declaration(finish_func));
}
type_interface_define(async_iface, map_attrs(iface->attrs, async_iface_attrs), inherit, stmts);
type_interface_define(async_iface, map_attrs(iface->attrs, async_iface_attrs), inherit, stmts, NULL);
iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface;
}

View File

@ -441,7 +441,7 @@ type_t *type_interface_declare(char *name, struct namespace *namespace)
return type;
}
type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts)
type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires)
{
if (iface->defined)
error_loc("interface %s already defined at %s:%d\n",
@ -457,6 +457,7 @@ type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit
iface->details.iface->inherit = inherit;
iface->details.iface->disp_inherit = NULL;
iface->details.iface->async_iface = NULL;
iface->details.iface->requires = requires;
iface->defined = TRUE;
compute_method_indexes(iface);
return iface;
@ -485,6 +486,7 @@ type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t
if (!iface->details.iface->inherit) error_loc("IDispatch 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);
return iface;
@ -504,6 +506,7 @@ type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *att
if (!dispiface->details.iface->inherit) error_loc("IDispatch is undefined\n");
dispiface->details.iface->disp_inherit = iface;
dispiface->details.iface->async_iface = NULL;
dispiface->details.iface->requires = NULL;
dispiface->defined = TRUE;
compute_method_indexes(dispiface);
return dispiface;
@ -561,6 +564,9 @@ type_t *type_runtimeclass_declare(char *name, struct namespace *namespace)
type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref_list_t *ifaces)
{
ifref_t *ifref, *required, *tmp;
ifref_list_t *requires;
if (runtimeclass->defined)
error_loc("runtimeclass %s already defined at %s:%d\n",
runtimeclass->name, runtimeclass->loc_info.input_name, runtimeclass->loc_info.line_number);
@ -569,6 +575,28 @@ type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref
runtimeclass->defined = TRUE;
if (!type_runtimeclass_get_default_iface(runtimeclass))
error_loc("missing default interface on runtimeclass %s\n", runtimeclass->name);
LIST_FOR_EACH_ENTRY(ifref, ifaces, ifref_t, entry)
{
/* FIXME: this should probably not be allowed, here or in coclass, */
/* but for now there's too many places in Wine IDL where it is to */
/* even print a warning. */
if (!(ifref->iface->defined)) continue;
if (!(requires = type_iface_get_requires(ifref->iface))) continue;
LIST_FOR_EACH_ENTRY(required, requires, ifref_t, entry)
{
int found = 0;
LIST_FOR_EACH_ENTRY(tmp, ifaces, ifref_t, entry)
if ((found = type_is_equal(tmp->iface, required->iface))) break;
if (!found)
error_loc("interface '%s' also requires interface '%s', "
"but runtimeclass '%s' does not implement it.\n",
ifref->iface->name, required->iface->name, runtimeclass->name);
}
}
return runtimeclass;
}
@ -593,8 +621,12 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs)
int type_is_equal(const type_t *type1, const type_t *type2)
{
if (type1 == type2)
return TRUE;
if (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2))
return FALSE;
if (type1->namespace != type2->namespace)
return FALSE;
if (type1->name && type2->name)
return !strcmp(type1->name, type2->name);

View File

@ -53,7 +53,7 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio
type_t *type_new_bitfield(type_t *field_type, const expr_t *bits);
type_t *type_runtimeclass_declare(char *name, struct namespace *namespace);
type_t *type_interface_declare(char *name, struct namespace *namespace);
type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts);
type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires);
type_t *type_dispinterface_declare(char *name);
type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, var_list_t *props, var_list_t *methods);
type_t *type_dispinterface_define_from_iface(type_t *dispiface, attr_list_t *attrs, type_t *iface);
@ -181,6 +181,13 @@ static inline type_t *type_iface_get_inherit(const type_t *type)
return type->details.iface->inherit;
}
static inline ifref_list_t *type_iface_get_requires(const type_t *type)
{
type = type_get_real_type(type);
assert(type_get_type(type) == TYPE_INTERFACE);
return type->details.iface->requires;
}
static inline type_t *type_iface_get_async_iface(const type_t *type)
{
type = type_get_real_type(type);

View File

@ -386,6 +386,7 @@ struct iface_details
struct _type_t *inherit;
struct _type_t *disp_inherit;
struct _type_t *async_iface;
ifref_list_t *requires;
};
struct module_details