Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v3: I got caught by the change to the parameterized_arg rule that was actually prepending types instead of appending types them, as the helper name suggests, reversing the list order.
So I decided to clean all this type_list_t single linked list mess first, to use the usual double linked list structure and helpers. As there was already a ifref_list_t / ifref_t that is mostly a type list, I just renamed it and used it everywhere type_list_t was used.
Then this also:
* Fix memmove off-by-one error in format_parameterized_type_c_name.
* Fix incorrect usage of u.type_list for STMT_TYPE and STMT_TYPEREF,
* Use STMT_TYPE with a partially specialized parameterized type for the delayed definitions, instead of trying to force use of type_list.
* Removes development code leftovers.
* Add loc_info_t to replace_type_parameters_in_statement(_list).
* Print proper error message in unsupported cases.
* Delay the delegate patches to a later batch.
Thanks Jacek for the review!
tools/widl/parser.y | 4 ++-- tools/widl/typetree.c | 8 ++++---- tools/widl/typetree.h | 2 +- tools/widl/widltypes.h | 2 +- tools/widl/write_msft.c | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 6ab4f83a0ad..54006529ba9 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1821,10 +1821,10 @@ static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface) return list; }
-static ifref_t *make_ifref(type_t *iface) +static ifref_t *make_ifref(type_t *type) { ifref_t *l = xmalloc(sizeof(ifref_t)); - l->iface = iface; + l->type = type; l->attrs = NULL; return l; } diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 203fffcdee6..2f49a92511a 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -565,19 +565,19 @@ type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref /* 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; + if (!(ifref->type->defined)) continue; + if (!(requires = type_iface_get_requires(ifref->type))) 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 = type_is_equal(tmp->type, required->type))) 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); + ifref->type->name, required->type->name, runtimeclass->name); } }
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 96b681e0379..186f42307f4 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -363,7 +363,7 @@ static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) if (!ifaces) return NULL; LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry) if (is_attr(entry->attrs, ATTR_DEFAULT)) - return entry->iface; + return entry->type;
return NULL; } diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 7596577493d..f31d40cad91 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -538,7 +538,7 @@ struct _declarator_t { };
struct _ifref_t { - type_t *iface; + type_t *type; attr_list_t *attrs;
/* parser-internal */ diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 5728f041f6f..63635cec011 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -2352,10 +2352,10 @@ static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls)
i = 0; if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) { - if(iref->iface->typelib_idx == -1) - add_interface_typeinfo(typelib, iref->iface); + if(iref->type->typelib_idx == -1) + add_interface_typeinfo(typelib, iref->type); ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref)); - ref->reftype = typelib->typelib_typeinfo_offsets[iref->iface->typelib_idx]; + ref->reftype = typelib->typelib_typeinfo_offsets[iref->type->typelib_idx]; ref->flags = 0; ref->oCustData = -1; ref->onext = -1;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/parser.y | 34 +++++++++++++++++----------------- tools/widl/typetree.c | 14 +++++++------- tools/widl/typetree.h | 8 ++++---- tools/widl/widltypes.h | 5 ++--- tools/widl/write_msft.c | 6 +++--- 5 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 54006529ba9..dd8012ca5f4 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -57,8 +57,8 @@ static attr_t *make_custom_attr(UUID *id, expr_t *pval); static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_t *decl, int top); static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls); -static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface); -static ifref_t *make_ifref(type_t *iface); +static ifref_list_t *append_typeref(ifref_list_t *list, typeref_t *ref); +static typeref_t *make_typeref(type_t *type); static var_list_t *append_var_list(var_list_t *list, var_list_t *vars); static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *p); static declarator_t *make_declarator(var_t *var); @@ -137,7 +137,7 @@ static typelib_t *current_typelib; statement_list_t *stmt_list; warning_t *warning; warning_list_t *warning_list; - ifref_t *ifref; + typeref_t *typeref; ifref_list_t *ifref_list; char *str; UUID *uuid; @@ -293,7 +293,7 @@ static typelib_t *current_typelib; %type <type> type unqualified_type qualified_type %type <type> type_parameter %type <type_list> type_parameters -%type <ifref> class_interface +%type <typeref> 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 @@ -934,12 +934,12 @@ namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; } ;
class_interfaces: { $$ = NULL; } - | class_interfaces class_interface { $$ = append_ifref( $1, $2 ); } + | class_interfaces class_interface { $$ = append_typeref( $1, $2 ); } ;
class_interface: - m_attributes interfaceref ';' { $$ = make_ifref($2); $$->attrs = $1; } - | m_attributes dispinterfaceref ';' { $$ = make_ifref($2); $$->attrs = $1; } + m_attributes interfaceref ';' { $$ = make_typeref($2); $$->attrs = $1; } + | m_attributes dispinterfaceref ';' { $$ = make_typeref($2); $$->attrs = $1; } ;
dispinterface: tDISPINTERFACE typename { $$ = type_dispinterface_declare($2); } @@ -982,8 +982,8 @@ interface: ;
required_types: - qualified_type { $$ = append_ifref(NULL, make_ifref($1)); } - | required_types ',' qualified_type { $$ = append_ifref($1, make_ifref($3)); } + qualified_type { $$ = append_typeref(NULL, make_typeref($1)); } + | required_types ',' qualified_type { $$ = append_typeref($1, make_typeref($3)); }
requires: { $$ = NULL; } | tREQUIRES required_types { $$ = $2; } @@ -1809,24 +1809,24 @@ static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, dec return var_list; }
-static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface) +static ifref_list_t *append_typeref(ifref_list_t *list, typeref_t *ref) { - if (!iface) return list; + if (!ref) return list; if (!list) { list = xmalloc( sizeof(*list) ); list_init( list ); } - list_add_tail( list, &iface->entry ); + list_add_tail( list, &ref->entry ); return list; }
-static ifref_t *make_ifref(type_t *type) +static typeref_t *make_typeref(type_t *type) { - ifref_t *l = xmalloc(sizeof(ifref_t)); - l->type = type; - l->attrs = NULL; - return l; + typeref_t *ref = xmalloc(sizeof(typeref_t)); + ref->type = type; + ref->attrs = NULL; + return ref; }
static type_list_t *append_type(type_list_t *list, type_t *type) diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 2f49a92511a..d2a43a36c01 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -548,7 +548,7 @@ 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; + typeref_t *ref, *required, *tmp; ifref_list_t *requires;
if (runtimeclass->defined) @@ -560,24 +560,24 @@ type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref 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) + LIST_FOR_EACH_ENTRY(ref, ifaces, typeref_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->type->defined)) continue; - if (!(requires = type_iface_get_requires(ifref->type))) continue; - LIST_FOR_EACH_ENTRY(required, requires, ifref_t, entry) + if (!(ref->type->defined)) continue; + if (!(requires = type_iface_get_requires(ref->type))) continue; + LIST_FOR_EACH_ENTRY(required, requires, typeref_t, entry) { int found = 0;
- LIST_FOR_EACH_ENTRY(tmp, ifaces, ifref_t, entry) + LIST_FOR_EACH_ENTRY(tmp, ifaces, typeref_t, entry) if ((found = type_is_equal(tmp->type, required->type))) break;
if (!found) error_loc("interface '%s' also requires interface '%s', " "but runtimeclass '%s' does not implement it.\n", - ifref->type->name, required->type->name, runtimeclass->name); + ref->type->name, required->type->name, runtimeclass->name); } }
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 186f42307f4..7c2e9d40026 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -358,12 +358,12 @@ static inline ifref_list_t *type_runtimeclass_get_ifaces(const type_t *type) static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) { ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type); - ifref_t *entry; + typeref_t *ref;
if (!ifaces) return NULL; - LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry) - if (is_attr(entry->attrs, ATTR_DEFAULT)) - return entry->type; + LIST_FOR_EACH_ENTRY(ref, ifaces, typeref_t, entry) + if (is_attr(ref->attrs, ATTR_DEFAULT)) + return ref->type;
return NULL; } diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index f31d40cad91..8e83fc059fb 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -43,7 +43,7 @@ typedef struct _type_t type_t; typedef struct _var_t var_t; typedef struct _decl_spec_t decl_spec_t; typedef struct _declarator_t declarator_t; -typedef struct _ifref_t ifref_t; +typedef struct _typeref_t typeref_t; typedef struct _typelib_entry_t typelib_entry_t; typedef struct _importlib_t importlib_t; typedef struct _importinfo_t importinfo_t; @@ -537,7 +537,7 @@ struct _declarator_t { struct list entry; };
-struct _ifref_t { +struct _typeref_t { type_t *type; attr_list_t *attrs;
@@ -601,7 +601,6 @@ struct _statement_t { enum statement_type type; union { - ifref_t iface; type_t *type; const char *str; var_t *var; diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 63635cec011..fb532f7a227 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -2331,7 +2331,7 @@ static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef) static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls) { msft_typeinfo_t *msft_typeinfo; - ifref_t *iref; + typeref_t *iref; int num_ifaces = 0, offset, i; MSFT_RefRecord *ref, *first = NULL, *first_source = NULL; int have_default = 0, have_default_source = 0; @@ -2345,13 +2345,13 @@ static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls) msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs);
ifaces = type_coclass_get_ifaces(cls); - if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) num_ifaces++; + if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, typeref_t, entry ) num_ifaces++;
offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES, num_ifaces * sizeof(*ref), 0);
i = 0; - if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) { + if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, typeref_t, entry ) { if(iref->type->typelib_idx == -1) add_interface_typeinfo(typelib, iref->type); ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref));
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/parser.y | 10 +++++----- tools/widl/typetree.c | 10 +++++----- tools/widl/typetree.h | 16 ++++++++-------- tools/widl/widltypes.h | 8 ++++---- tools/widl/write_msft.c | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index dd8012ca5f4..07fe23230db 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -57,7 +57,7 @@ static attr_t *make_custom_attr(UUID *id, expr_t *pval); static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_t *decl, int top); static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls); -static ifref_list_t *append_typeref(ifref_list_t *list, typeref_t *ref); +static typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref); static typeref_t *make_typeref(type_t *type); static var_list_t *append_var_list(var_list_t *list, var_list_t *vars); static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *p); @@ -138,7 +138,7 @@ static typelib_t *current_typelib; warning_t *warning; warning_list_t *warning_list; typeref_t *typeref; - ifref_list_t *ifref_list; + typeref_list_t *typeref_list; char *str; UUID *uuid; unsigned int num; @@ -294,8 +294,8 @@ static typelib_t *current_typelib; %type <type> type_parameter %type <type_list> type_parameters %type <typeref> class_interface -%type <ifref_list> class_interfaces -%type <ifref_list> requires required_types +%type <typeref_list> class_interfaces +%type <typeref_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 @@ -1809,7 +1809,7 @@ static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, dec return var_list; }
-static ifref_list_t *append_typeref(ifref_list_t *list, typeref_t *ref) +static typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref) { if (!ref) return list; if (!list) diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index d2a43a36c01..bafd8d9879f 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -425,7 +425,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, ifref_list_t *requires) +type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires) { if (iface->defined) error_loc("interface %s already defined at %s:%d\n", @@ -526,7 +526,7 @@ type_t *type_coclass_declare(char *name) return type; }
-type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, ifref_list_t *ifaces) +type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, typeref_list_t *ifaces) { if (coclass->defined) error_loc("coclass %s already defined at %s:%d\n", @@ -546,10 +546,10 @@ type_t *type_runtimeclass_declare(char *name, struct namespace *namespace) return type; }
-type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref_list_t *ifaces) +type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, typeref_list_t *ifaces) { typeref_t *ref, *required, *tmp; - ifref_list_t *requires; + typeref_list_t *requires;
if (runtimeclass->defined) error_loc("runtimeclass %s already defined at %s:%d\n", @@ -614,7 +614,7 @@ type_t *type_parameterized_interface_declare(char *name, struct namespace *names return type; }
-type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires) +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 *iface; if (type->defined) diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 7c2e9d40026..aa08c299c20 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -53,17 +53,17 @@ 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, ifref_list_t *requires); +type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_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); type_t *type_module_define(type_t* module, attr_list_t *attrs, statement_list_t *stmts); -type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, ifref_list_t *ifaces); -type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref_list_t *ifaces); +type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, typeref_list_t *ifaces); +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_parameterized_interface_declare(char *name, struct namespace *namespace, type_list_t *params); -type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires); +type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires); int type_is_equal(const type_t *type1, const type_t *type2); const char *type_get_name(const type_t *type, enum name_type name_type); char *gen_name(void); @@ -183,7 +183,7 @@ 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) +static inline typeref_list_t *type_iface_get_requires(const type_t *type) { type = type_get_real_type(type); assert(type_get_type(type) == TYPE_INTERFACE); @@ -341,14 +341,14 @@ static inline type_t *type_alias_get_aliasee_type(const type_t *type) return type->details.alias.aliasee.type; }
-static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) +static inline typeref_list_t *type_coclass_get_ifaces(const type_t *type) { type = type_get_real_type(type); assert(type_get_type(type) == TYPE_COCLASS); return type->details.coclass.ifaces; }
-static inline ifref_list_t *type_runtimeclass_get_ifaces(const type_t *type) +static inline typeref_list_t *type_runtimeclass_get_ifaces(const type_t *type) { type = type_get_real_type(type); assert(type_get_type(type) == TYPE_RUNTIMECLASS); @@ -357,7 +357,7 @@ static inline ifref_list_t *type_runtimeclass_get_ifaces(const type_t *type)
static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) { - ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type); + typeref_list_t *ifaces = type_runtimeclass_get_ifaces(type); typeref_t *ref;
if (!ifaces) return NULL; diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 8e83fc059fb..e2b8608fabb 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -60,7 +60,7 @@ typedef struct list str_list_t; typedef struct list expr_list_t; typedef struct list var_list_t; typedef struct list declarator_list_t; -typedef struct list ifref_list_t; +typedef struct list typeref_list_t; typedef struct list user_type_list_t; typedef struct list context_handle_list_t; typedef struct list generic_handle_list_t; @@ -386,7 +386,7 @@ struct iface_details struct _type_t *inherit; struct _type_t *disp_inherit; struct _type_t *async_iface; - ifref_list_t *requires; + typeref_list_t *requires; };
struct module_details @@ -406,7 +406,7 @@ struct array_details
struct coclass_details { - ifref_list_t *ifaces; + typeref_list_t *ifaces; };
struct basic_details @@ -433,7 +433,7 @@ struct alias_details
struct runtimeclass_details { - ifref_list_t *ifaces; + typeref_list_t *ifaces; };
struct parameterized_details diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index fb532f7a227..49659123ddd 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -2336,7 +2336,7 @@ static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls) MSFT_RefRecord *ref, *first = NULL, *first_source = NULL; int have_default = 0, have_default_source = 0; const attr_t *attr; - ifref_list_t *ifaces; + typeref_list_t *ifaces;
if (-1 < cls->typelib_idx) return;
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/client.c | 14 +++++++------- tools/widl/header.c | 16 ++++++++-------- tools/widl/parser.y | 26 ++++---------------------- tools/widl/typegen.c | 12 ++++++------ tools/widl/typetree.c | 2 +- tools/widl/typetree.h | 2 +- tools/widl/widltypes.h | 10 ++-------- tools/widl/write_msft.c | 10 +++++----- 8 files changed, 34 insertions(+), 58 deletions(-)
diff --git a/tools/widl/client.c b/tools/widl/client.c index 185ab8dffc2..6ecae4187d3 100644 --- a/tools/widl/client.c +++ b/tools/widl/client.c @@ -373,9 +373,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) } case STMT_TYPEDEF: { - const type_list_t *type_entry; - for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next) - write_serialize_functions(client, type_entry->type, iface); + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) + write_serialize_functions(client, ref->type, iface); break; } default: @@ -539,11 +539,11 @@ static void write_client_ifaces(const statement_list_t *stmts, int expr_eval_rou } if (stmt2->type == STMT_TYPEDEF) { - const type_list_t *type_entry; - for (type_entry = stmt2->u.type_list; type_entry; type_entry = type_entry->next) + typeref_t *ref; + if (stmt2->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt2->u.type_list, typeref_t, entry) { - if (is_attr(type_entry->type->attrs, ATTR_ENCODE) - || is_attr(type_entry->type->attrs, ATTR_DECODE)) + if (is_attr(ref->type->attrs, ATTR_ENCODE) + || is_attr(ref->type->attrs, ATTR_DECODE)) { needs_stub = 1; break; diff --git a/tools/widl/header.c b/tools/widl/header.c index 8423756e060..f4010220206 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -776,7 +776,7 @@ static int for_each_serializable(const statement_list_t *stmts, FILE *header, { statement_t *stmt, *iface_stmt; statement_list_t *iface_stmts; - const type_list_t *type_entry; + typeref_t *ref;
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) { @@ -787,12 +787,12 @@ static int for_each_serializable(const statement_list_t *stmts, FILE *header, if (iface_stmts) LIST_FOR_EACH_ENTRY( iface_stmt, iface_stmts, statement_t, entry ) { if (iface_stmt->type != STMT_TYPEDEF) continue; - for (type_entry = iface_stmt->u.type_list; type_entry; type_entry = type_entry->next) + if (iface_stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, iface_stmt->u.type_list, typeref_t, entry) { - if (!is_attr(type_entry->type->attrs, ATTR_ENCODE) - && !is_attr(type_entry->type->attrs, ATTR_DECODE)) + if (!is_attr(ref->type->attrs, ATTR_ENCODE) + && !is_attr(ref->type->attrs, ATTR_DECODE)) continue; - if (!proc(header, type_entry->type)) + if (!proc(header, ref->type)) return 0; } } @@ -1887,9 +1887,9 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons break; case STMT_TYPEDEF: { - const type_list_t *type_entry = stmt->u.type_list; - for (; type_entry; type_entry = type_entry->next) - write_typedef(header, type_entry->type, stmt->declonly); + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) + write_typedef(header, ref->type, stmt->declonly); break; } case STMT_LIBRARY: diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 07fe23230db..5002383690e 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -45,7 +45,6 @@ struct _import_t };
static str_list_t *append_str(str_list_t *list, char *str); -static type_list_t *append_type(type_list_t *list, type_t *type); static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list); static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, @@ -128,7 +127,6 @@ static typelib_t *current_typelib; expr_t *expr; expr_list_t *expr_list; type_t *type; - type_list_t *type_list; var_t *var; var_list_t *var_list; declarator_t *declarator; @@ -292,7 +290,7 @@ static typelib_t *current_typelib; %type <type> enumdef structdef uniondef typedecl %type <type> type unqualified_type qualified_type %type <type> type_parameter -%type <type_list> type_parameters +%type <typeref_list> type_parameters %type <typeref> class_interface %type <typeref_list> class_interfaces %type <typeref_list> requires required_types @@ -971,8 +969,8 @@ type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namesp ;
type_parameters: - type_parameter { $$ = append_type(NULL, $1); } - | type_parameters ',' type_parameter { $$ = append_type($1, $3); } + type_parameter { $$ = append_typeref(NULL, make_typeref($1)); } + | type_parameters ',' type_parameter { $$ = append_typeref($1, make_typeref($3)); } ;
interface: @@ -1829,16 +1827,6 @@ static typeref_t *make_typeref(type_t *type) return ref; }
-static type_list_t *append_type(type_list_t *list, type_t *type) -{ - type_list_t *entry; - if (!type) return list; - entry = xmalloc( sizeof(*entry) ); - entry->type = type; - entry->next = list; - return entry; -} - var_list_t *append_var(var_list_t *list, var_t *var) { if (!var) return list; @@ -3209,24 +3197,18 @@ static statement_t *make_statement_typedef(declarator_list_t *decls, int declonl { declarator_t *decl, *next; statement_t *stmt; - type_list_t **type_list;
if (!decls) return NULL;
stmt = make_statement(STMT_TYPEDEF); stmt->u.type_list = NULL; - type_list = &stmt->u.type_list; stmt->declonly = declonly;
LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry ) { var_t *var = decl->var; type_t *type = find_type_or_error(current_namespace, var->name); - *type_list = xmalloc(sizeof(type_list_t)); - (*type_list)->type = type; - (*type_list)->next = NULL; - - type_list = &(*type_list)->next; + stmt->u.type_list = append_typeref(stmt->u.type_list, make_typeref(type)); free(decl); free(var); } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 1b5fe16b6ec..6ae55ac1934 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -3747,13 +3747,13 @@ static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned in } case STMT_TYPEDEF: { - const type_list_t *type_entry; - for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next) + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) { - if (is_attr(type_entry->type->attrs, ATTR_ENCODE) - || is_attr(type_entry->type->attrs, ATTR_DECODE)) - type_entry->type->typestring_offset = write_type_tfs( file, - type_entry->type->attrs, type_entry->type, type_entry->type->name, + if (is_attr(ref->type->attrs, ATTR_ENCODE) + || is_attr(ref->type->attrs, ATTR_DECODE)) + ref->type->typestring_offset = write_type_tfs( file, + ref->type->attrs, ref->type, ref->type->name, TYPE_CONTEXT_CONTAINER, offset); } break; diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index bafd8d9879f..3071307b353 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -603,7 +603,7 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) return apicontract; }
-type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, type_list_t *params) +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); if (type_get_type_detect_alias(type) != TYPE_PARAMETERIZED_TYPE) diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index aa08c299c20..a2185ae35ea 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -62,7 +62,7 @@ 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_parameterized_interface_declare(char *name, struct namespace *namespace, type_list_t *params); +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); int type_is_equal(const type_t *type1, const type_t *type2); const char *type_get_name(const type_t *type, enum name_type name_type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index e2b8608fabb..e2f77fbadec 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -51,7 +51,6 @@ typedef struct _typelib_t typelib_t; typedef struct _user_type_t user_type_t; typedef struct _user_type_t context_handle_t; typedef struct _user_type_t generic_handle_t; -typedef struct _type_list_t type_list_t; typedef struct _statement_t statement_t; typedef struct _warning_t warning_t;
@@ -439,7 +438,7 @@ struct runtimeclass_details struct parameterized_details { type_t *type; - type_list_t *params; + typeref_list_t *params; };
#define HASHMAX 64 @@ -591,11 +590,6 @@ struct _user_type_t { const char *name; };
-struct _type_list_t { - type_t *type; - struct _type_list_t *next; -}; - struct _statement_t { struct list entry; enum statement_type type; @@ -605,7 +599,7 @@ struct _statement_t { const char *str; var_t *var; typelib_t *lib; - type_list_t *type_list; + typeref_list_t *type_list; } u; unsigned int declonly : 1; /* for STMT_TYPE and STMT_TYPEDEF */ }; diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 49659123ddd..c39f38249c8 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -2479,14 +2479,14 @@ static void add_entry(msft_typelib_t *typelib, const statement_t *stmt) break; case STMT_TYPEDEF: { - const type_list_t *type_entry = stmt->u.type_list; - for (; type_entry; type_entry = type_entry->next) { + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) { /* if the type is public then add the typedef, otherwise attempt * to add the aliased type */ - if (is_attr(type_entry->type->attrs, ATTR_PUBLIC)) - add_typedef_typeinfo(typelib, type_entry->type); + if (is_attr(ref->type->attrs, ATTR_PUBLIC)) + add_typedef_typeinfo(typelib, ref->type); else - add_type_typeinfo(typelib, type_alias_get_aliasee_type(type_entry->type)); + add_type_typeinfo(typelib, type_alias_get_aliasee_type(ref->type)); } break; }
Signed-off-by: Jacek Caban jacek@codeweavers.com
This allows parameterized types to reference each other with a different set of parameters. This is required for instance for IIterable<T>, that needs to reference IIterator<T>.
The partial specialization is recorded by adding a new parameterized type, referencing the original one as its template. The parameterized type chain will be resolved all at once when the type is declared.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.idl | 9 ++++++++ tools/widl/parser.y | 41 ++++++++++++++++++++++++++++++++++ tools/widl/typetree.c | 41 +++++++++++++++++++++++++++++++--- tools/widl/typetree.h | 3 +++ tools/widl/widltypes.h | 1 + 5 files changed, 92 insertions(+), 3 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index ab7c4753c3b..5f7a49c38e4 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -127,6 +127,15 @@ namespace Windows { HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value); }
+ [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(faa585ea-6214-4217-afda-7f46de5869b3) + ] + interface IIterable<T> : IInspectable + { + HRESULT First([out, retval] Windows.Foundation.Collections.IIterator<T> **value); + } + [ contract(Windows.Foundation.FoundationContract, 1.0), uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 5002383690e..cfe061abd23 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -291,6 +291,9 @@ static typelib_t *current_typelib; %type <type> type unqualified_type qualified_type %type <type> type_parameter %type <typeref_list> type_parameters +%type <type> parameterized_type +%type <type> parameterized_type_arg +%type <typeref_list> parameterized_type_args %type <typeref> class_interface %type <typeref_list> class_interfaces %type <typeref_list> requires required_types @@ -907,6 +910,24 @@ qualified_type: | namespace_pfx typename { $$ = find_type_or_error($1, $2); } ;
+parameterized_type: qualified_type '<' parameterized_type_args '>' + { $$ = find_parameterized_type($1, $3); } + ; + +parameterized_type_arg: + base_type { $$ = $1; } + | qualified_type { $$ = $1; } + | qualified_type '*' { $$ = type_new_pointer($1); } + | parameterized_type { $$ = $1; } + | parameterized_type '*' { $$ = type_new_pointer($1); } + ; + +parameterized_type_args: + parameterized_type_arg { $$ = append_typeref(NULL, make_typeref($1)); } + | parameterized_type_args ',' parameterized_type_arg + { $$ = append_typeref($1, make_typeref($3)); } + ; + coclass: tCOCLASS typename { $$ = type_coclass_declare($2); } ;
@@ -963,6 +984,7 @@ dispinterfacedef:
inherit: { $$ = NULL; } | ':' qualified_type { $$ = $2; } + | ':' parameterized_type { $$ = $2; } ;
type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); } @@ -981,7 +1003,9 @@ interface:
required_types: qualified_type { $$ = append_typeref(NULL, make_typeref($1)); } + | parameterized_type { $$ = append_typeref(NULL, make_typeref($1)); } | required_types ',' qualified_type { $$ = append_typeref($1, make_typeref($3)); } + | required_types ',' parameterized_type { $$ = append_typeref($1, make_typeref($3)); }
requires: { $$ = NULL; } | tREQUIRES required_types { $$ = $2; } @@ -1205,6 +1229,7 @@ unqualified_type: type: unqualified_type | namespace_pfx typename { $$ = find_type_or_error($1, $2); } + | parameterized_type { $$ = $1; } ;
typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list @@ -3250,3 +3275,19 @@ void init_loc_info(loc_info_t *i) i->line_number = line_number; i->near_text = parser_text; } + +type_t *find_parameterized_type(type_t *type, typeref_list_t *params) +{ + char *name = format_parameterized_type_name(type, params); + + if (parameters_namespace) + { + assert(type->type_type == TYPE_PARAMETERIZED_TYPE); + type = type_parameterized_type_specialize_partial(type, params); + } + /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */ + else error_loc("parameterized type '%s' not declared\n", name); + + free(name); + return type; +} diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 3071307b353..a31bd383169 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -100,13 +100,40 @@ static size_t append_namespace(char **buf, size_t *len, size_t pos, struct names return n; }
+static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *prefix, + const char *separator, const char *suffix, const char *abi_prefix) +{ + size_t n = 0; + n += strappend(buf, len, pos + n, "%s", prefix); + n += append_namespace(buf, len, pos + n, namespace, separator, abi_prefix); + n += strappend(buf, len, pos + n, "%s", suffix); + return n; +} + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) +{ + size_t len = 0; + char *buf = NULL; + append_namespaces(&buf, &len, 0, namespace, prefix, separator, suffix, abi_prefix); + return buf; +} + +char *format_parameterized_type_name(type_t *type, typeref_list_t *params) { size_t len = 0, pos = 0; char *buf = NULL; - pos += strappend(&buf, &len, pos, "%s", prefix); - pos += append_namespace(&buf, &len, pos, namespace, separator, abi_prefix); - pos += strappend(&buf, &len, pos, "%s", suffix); + typeref_t *ref; + + 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, "*"); + if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ","); + } + pos += strappend(&buf, &len, pos, ">"); + return buf; }
@@ -642,6 +669,14 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty return type; }
+type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params) +{ + type_t *new_type = duptype(type, 0); + new_type->details.parameterized.type = type; + new_type->details.parameterized.params = params; + return new_type; +} + int type_is_equal(const type_t *type1, const type_t *type2) { if (type1 == type2) diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index a2185ae35ea..6408fc0e409 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -36,6 +36,8 @@ attr_list_t *check_interface_attrs(const char *name, attr_list_t *attrs); attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs); attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs);
+type_t *find_parameterized_type(type_t *type, typeref_list_t *params); + type_t *type_new_function(var_list_t *args); type_t *type_new_pointer(type_t *ref); type_t *type_new_alias(const decl_spec_t *t, const char *name); @@ -64,6 +66,7 @@ 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_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); int type_is_equal(const type_t *type1, const type_t *type2); const char *type_get_name(const type_t *type, enum name_type name_type); char *gen_name(void); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index e2f77fbadec..777aabc78ff 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -643,6 +643,7 @@ void init_loc_info(loc_info_t *);
char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix); +char *format_parameterized_type_name(type_t *type, typeref_list_t *params);
static inline enum type_type type_get_type_detect_alias(const type_t *type) {
Signed-off-by: Jacek Caban jacek@codeweavers.com
This allows parameterized interfaces to be instanciated in declare blocks, in the same way MIDL does, generating a new interface to the header from the parameterized type template, replacing its parameters with the given types.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.media.speechsynthesis.idl | 24 +++ tools/widl/header.c | 7 +- tools/widl/parser.l | 1 + tools/widl/parser.y | 69 +++++- tools/widl/typetree.c | 243 ++++++++++++++++++++++ tools/widl/typetree.h | 5 + 6 files changed, 340 insertions(+), 9 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 87497678f30..af4466681dc 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -35,11 +35,24 @@ namespace Windows { interface ISpeechSynthesizer; interface ISpeechSynthesizer2; interface IVoiceInformation; + runtimeclass SpeechSynthesizer; runtimeclass VoiceInformation; } } }
+namespace Windows { + namespace Media { + namespace SpeechSynthesis { + declare { + interface Windows.Foundation.Collections.IIterator<Windows.Media.SpeechSynthesis.VoiceInformation*>; + interface Windows.Foundation.Collections.IIterable<Windows.Media.SpeechSynthesis.VoiceInformation*>; + interface Windows.Foundation.Collections.IVectorView<Windows.Media.SpeechSynthesis.VoiceInformation*>; + } + } + } +} + namespace Windows { namespace Media { namespace SpeechSynthesis { @@ -64,6 +77,17 @@ namespace Windows { [propget] HRESULT Gender([out] [retval] VoiceGender* value); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SpeechSynthesis.SpeechSynthesizer), + uuid(7d526ecc-7533-4c3f-85be-888c2baeebdc) + ] + interface IInstalledVoicesStatic : IInspectable + { + [propget] HRESULT AllVoices([out, retval] Windows.Foundation.Collections.IVectorView<VoiceInformation*>** value); + [propget] HRESULT DefaultVoice([out, retval] VoiceInformation** value); + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile) diff --git a/tools/widl/header.c b/tools/widl/header.c index f4010220206..f0f2b39073b 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1479,7 +1479,8 @@ static void write_forward(FILE *header, type_t *iface) fprintf(header, "typedef interface %s %s;\n", iface->c_name, iface->c_name); fprintf(header, "#ifdef __cplusplus\n"); write_namespace_start(header, iface->namespace); - write_line(header, 0, "interface %s;", iface->name); + 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); fprintf(header, "#endif /* __cplusplus */\n"); fprintf(header, "#endif\n\n" ); @@ -1548,11 +1549,13 @@ static void write_com_interface_end(FILE *header, type_t *iface) write_namespace_start(header, iface->namespace); } if (uuid) { + if (strchr(iface->name, '<')) write_line(header, 0, "template<>"); write_line(header, 0, "MIDL_INTERFACE("%s")", uuid_string(uuid)); indent(header, 0); }else { indent(header, 0); - fprintf(header, "interface "); + if (strchr(iface->name, '<')) fprintf(header, "template<> struct "); + else fprintf(header, "interface "); } if (type_iface_get_inherit(iface)) { diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 946dba84cd6..d319954edd3 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -276,6 +276,7 @@ static const struct keyword keywords[] = { {"coclass", tCOCLASS, 0}, {"const", tCONST, 0}, {"cpp_quote", tCPPQUOTE, 0}, + {"declare", tDECLARE, 1}, {"default", tDEFAULT, 0}, {"dispinterface", tDISPINTERFACE, 0}, {"double", tDOUBLE, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index cfe061abd23..ea80cde6af7 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -56,8 +56,6 @@ static attr_t *make_custom_attr(UUID *id, expr_t *pval); static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_t *decl, int top); static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls); -static typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref); -static typeref_t *make_typeref(type_t *type); static var_list_t *append_var_list(var_list_t *list, var_list_t *vars); static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *p); static declarator_t *make_declarator(var_t *var); @@ -79,6 +77,7 @@ static void pop_namespace(const char *name); static void push_parameters_namespace(const char *name); static void pop_parameters_namespace(const char *name);
+static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts); static void check_arg_attrs(const var_t *arg); static void check_statements(const statement_list_t *stmts, int is_inside_library); static void check_all_user_types(const statement_list_t *stmts); @@ -106,6 +105,7 @@ static statement_t *make_statement_importlib(const char *str); 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_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 *); @@ -116,6 +116,7 @@ static struct namespace global_namespace = {
static struct namespace *current_namespace = &global_namespace; static struct namespace *parameters_namespace = NULL; +static statement_list_t *parameterized_type_stmts = NULL;
static typelib_t *current_typelib;
@@ -177,6 +178,7 @@ static typelib_t *current_typelib; %token tCONTRACTVERSION %token tCONTROL tCPPQUOTE %token tCUSTOM +%token tDECLARE %token tDECODE tDEFAULT tDEFAULTBIND %token tDEFAULTCOLLELEM %token tDEFAULTVALUE @@ -318,6 +320,8 @@ static typelib_t *current_typelib; %type <typelib> library_start librarydef %type <statement> statement typedef pragma_warning %type <stmt_list> gbl_statements imp_statements int_statements +%type <stmt_list> decl_block decl_statements +%type <stmt_list> imp_decl_block imp_decl_statements %type <warning_list> warnings %type <num> allocate_option_list allocate_option %type <namespace> namespace_pfx @@ -341,7 +345,8 @@ static typelib_t *current_typelib;
%%
-input: gbl_statements m_acf { check_statements($1, FALSE); +input: gbl_statements m_acf { $1 = append_parameterized_type_stmts($1); + check_statements($1, FALSE); check_all_user_types($1); write_header($1); write_id_data($1); @@ -357,6 +362,22 @@ input: gbl_statements m_acf { check_statements($1, FALSE);
m_acf: /* empty */ | aACF acf_statements
+decl_statements: { $$ = NULL; } + | decl_statements tINTERFACE qualified_type '<' parameterized_type_args '>' ';' + { parameterized_type_stmts = append_statement(parameterized_type_stmts, make_statement_parameterized_type($3, $5)); + $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); + } + ; + +decl_block: tDECLARE '{' decl_statements '}' { $$ = $3; } + +imp_decl_statements: { $$ = NULL; } + | imp_decl_statements tINTERFACE qualified_type '<' parameterized_type_args '>' ';' + { $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); } + ; + +imp_decl_block: tDECLARE '{' imp_decl_statements '}' { $$ = $3; } + gbl_statements: { $$ = NULL; } | gbl_statements namespacedef '{' { push_namespace($2); } gbl_statements '}' { pop_namespace($2); $$ = append_statements($1, $5); } @@ -378,6 +399,7 @@ gbl_statements: { $$ = NULL; } | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } | gbl_statements statement { $$ = append_statement($1, $2); } + | gbl_statements decl_block { $$ = append_statements($1, $2); } ;
imp_statements: { $$ = NULL; } @@ -400,6 +422,7 @@ imp_statements: { $$ = NULL; } | imp_statements statement { $$ = append_statement($1, $2); } | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); } | imp_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } + | imp_statements imp_decl_block { $$ = append_statements($1, $2); } ;
int_statements: { $$ = NULL; } @@ -1832,7 +1855,7 @@ static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, dec return var_list; }
-static typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref) +typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref) { if (!ref) return list; if (!list) @@ -1844,7 +1867,7 @@ static typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref) return list; }
-static typeref_t *make_typeref(type_t *type) +typeref_t *make_typeref(type_t *type) { typeref_t *ref = xmalloc(sizeof(typeref_t)); ref->type = type; @@ -3066,6 +3089,29 @@ static void check_async_uuid(type_t *iface) iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface; }
+static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts) +{ + statement_t *stmt, *next; + + if (stmts && parameterized_type_stmts) LIST_FOR_EACH_ENTRY_SAFE(stmt, next, parameterized_type_stmts, statement_t, entry) + { + switch(stmt->type) + { + case STMT_TYPE: + stmt->u.type = type_parameterized_type_specialize_define(stmt->u.type); + stmt->declonly = FALSE; + list_remove(&stmt->entry); + stmts = append_statement(stmts, stmt); + break; + default: + assert(0); /* should not be there */ + break; + } + } + + return stmts; +} + static void check_statements(const statement_list_t *stmts, int is_inside_library) { const statement_t *stmt; @@ -3241,6 +3287,13 @@ static statement_t *make_statement_typedef(declarator_list_t *decls, int declonl return stmt; }
+static statement_t *make_statement_parameterized_type(type_t *type, typeref_list_t *params) +{ + statement_t *stmt = make_statement(STMT_TYPE); + stmt->u.type = type_parameterized_type_specialize_partial(type, params); + return stmt; +} + static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) { if (!l2) return l1; @@ -3285,8 +3338,10 @@ type_t *find_parameterized_type(type_t *type, typeref_list_t *params) assert(type->type_type == TYPE_PARAMETERIZED_TYPE); type = type_parameterized_type_specialize_partial(type, params); } - /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */ - else error_loc("parameterized type '%s' not declared\n", name); + else if ((type = find_type(name, type->namespace, 0))) + assert(type->type_type != TYPE_PARAMETERIZED_TYPE); + else + error_loc("parameterized type '%s' not declared\n", name);
free(name); return type; diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index a31bd383169..3f90fcbe014 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -137,6 +137,40 @@ char *format_parameterized_type_name(type_t *type, typeref_list_t *params) return buf; }
+static char const *parameterized_type_shorthands[][2] = { + {"Windows_CFoundation_CCollections_C", "__F"}, + {"Windows_CFoundation_C", "__F"}, +}; + +static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *params) +{ + size_t len = 0, pos = 0; + char *buf = NULL, *tmp; + int i, count = params ? list_count(params) : 0; + typeref_t *ref; + + pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL); + pos += strappend(&buf, &len, pos, "_%d", 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)) {} + pos += append_namespaces(&buf, &len, pos, type->namespace, "_", "__C", type->name, NULL); + } + + for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i) + { + if ((tmp = strstr(buf, parameterized_type_shorthands[i][0])) && + (tmp - buf) == strlen(use_abi_namespace ? "__x_ABI_C" : "__x_C")) + { + tmp += strlen(parameterized_type_shorthands[i][0]); + strcpy(buf, parameterized_type_shorthands[i][1]); + memmove(buf + 3, tmp, len - (tmp - buf)); + } + } + + return buf; +} + type_t *type_new_function(var_list_t *args) { var_t *arg; @@ -677,6 +711,215 @@ type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t return new_type; }
+static type_t *replace_type_parameters_in_type(type_t *type, typeref_list_t *orig, typeref_list_t *repl); + +static typeref_list_t *replace_type_parameters_in_type_list(typeref_list_t *list, typeref_list_t *orig, typeref_list_t *repl) +{ + typeref_list_t *new_list = NULL; + typeref_t *ref; + + if (!list) return list; + + LIST_FOR_EACH_ENTRY(ref, list, typeref_t, entry) + { + type_t *new_type = replace_type_parameters_in_type(ref->type, orig, repl); + new_list = append_typeref(new_list, make_typeref(new_type)); + } + + return new_list; +} + +static var_t *replace_type_parameters_in_var(var_t *var, typeref_list_t *orig, typeref_list_t *repl) +{ + var_t *new_var = xmalloc(sizeof(*new_var)); + *new_var = *var; + list_init(&new_var->entry); + new_var->declspec.type = replace_type_parameters_in_type(var->declspec.type, orig, repl); + return new_var; +} + +static var_list_t *replace_type_parameters_in_var_list(var_list_t *var_list, typeref_list_t *orig, typeref_list_t *repl) +{ + var_list_t *new_var_list; + var_t *var, *new_var; + + if (!var_list) return var_list; + + new_var_list = xmalloc(sizeof(*new_var_list)); + list_init(new_var_list); + + LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry) + { + new_var = replace_type_parameters_in_var(var, orig, repl); + list_add_tail(new_var_list, &new_var->entry); + } + + return new_var_list; +} + +static statement_t *replace_type_parameters_in_statement(statement_t *stmt, typeref_list_t *orig, typeref_list_t *repl, loc_info_t *loc) +{ + statement_t *new_stmt = xmalloc(sizeof(*new_stmt)); + *new_stmt = *stmt; + list_init(&new_stmt->entry); + + switch (stmt->type) + { + case STMT_DECLARATION: + new_stmt->u.var = replace_type_parameters_in_var(stmt->u.var, orig, repl); + break; + case STMT_TYPE: + case STMT_TYPEREF: + new_stmt->u.type = replace_type_parameters_in_type(stmt->u.type, orig, repl); + break; + case STMT_TYPEDEF: + new_stmt->u.type_list = replace_type_parameters_in_type_list(stmt->u.type_list, orig, repl); + break; + case STMT_MODULE: + case STMT_LIBRARY: + case STMT_IMPORT: + case STMT_IMPORTLIB: + case STMT_PRAGMA: + case STMT_CPPQUOTE: + error_loc_info(loc, "unimplemented parameterized type replacement for statement type %d.\n", stmt->type); + break; + } + + return new_stmt; +} + +static statement_list_t *replace_type_parameters_in_statement_list(statement_list_t *stmt_list, typeref_list_t *orig, typeref_list_t *repl, loc_info_t *loc) +{ + statement_list_t *new_stmt_list; + statement_t *stmt, *new_stmt; + + if (!stmt_list) return stmt_list; + + new_stmt_list = xmalloc(sizeof(*new_stmt_list)); + list_init(new_stmt_list); + + LIST_FOR_EACH_ENTRY(stmt, stmt_list, statement_t, entry) + { + new_stmt = replace_type_parameters_in_statement(stmt, orig, repl, loc); + list_add_tail(new_stmt_list, &new_stmt->entry); + } + + return new_stmt_list; +} + +static type_t *replace_type_parameters_in_type(type_t *type, typeref_list_t *orig, typeref_list_t *repl) +{ + struct list *o, *r; + type_t *t; + + if (!type) return type; + switch (type->type_type) + { + case TYPE_VOID: + case TYPE_BASIC: + case TYPE_ENUM: + case TYPE_BITFIELD: + case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: + return type; + case TYPE_PARAMETER: + if (!orig || !repl) return NULL; + for (o = list_head(orig), r = list_head(repl); o && r; + o = list_next(orig, o), r = list_next(repl, r)) + if (type == LIST_ENTRY(o, typeref_t, entry)->type) + return LIST_ENTRY(r, typeref_t, entry)->type; + return type; + case TYPE_POINTER: + t = replace_type_parameters_in_type(type->details.pointer.ref.type, orig, repl); + if (t == type->details.pointer.ref.type) return type; + type = duptype(type, 0); + type->details.pointer.ref.type = t; + return type; + case TYPE_ALIAS: + t = replace_type_parameters_in_type(type->details.alias.aliasee.type, orig, repl); + if (t == type->details.alias.aliasee.type) return type; + type = duptype(type, 0); + type->details.alias.aliasee.type = t; + return type; + case TYPE_ARRAY: + t = replace_type_parameters_in_type(type->details.array.elem.type, orig, repl); + if (t == t->details.array.elem.type) return type; + type = duptype(type, 0); + t->details.array.elem.type = t; + return type; + case TYPE_FUNCTION: + t = duptype(type, 0); + t->details.function = xmalloc(sizeof(*t->details.function)); + t->details.function->args = replace_type_parameters_in_var_list(type->details.function->args, orig, repl); + t->details.function->retval = replace_type_parameters_in_var(type->details.function->retval, orig, repl); + return t; + case TYPE_PARAMETERIZED_TYPE: + t = type->details.parameterized.type; + if (t->type_type != TYPE_PARAMETERIZED_TYPE) return find_parameterized_type(type, repl); + repl = replace_type_parameters_in_type_list(type->details.parameterized.params, orig, repl); + return replace_type_parameters_in_type(t, t->details.parameterized.params, repl); + case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: + case TYPE_UNION: + case TYPE_MODULE: + case TYPE_COCLASS: + case TYPE_APICONTRACT: + error_loc_info(&type->loc_info, "unimplemented parameterized type replacement for type %s of type %d.\n", type->name, type->type_type); + break; + } + + return type; +} + +static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, typeref_list_t *orig, typeref_list_t *repl) +{ + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_methods = NULL; + iface->details.iface->disp_props = NULL; + iface->details.iface->stmts = replace_type_parameters_in_statement_list(tmpl->details.iface->stmts, orig, repl, &tmpl->loc_info); + iface->details.iface->inherit = replace_type_parameters_in_type(tmpl->details.iface->inherit, orig, repl); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; +} + +type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params) +{ + type_t *tmpl = type->details.parameterized.type; + type_t *new_type = duptype(tmpl, 0); + + new_type->namespace = type->namespace; + 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); + + return new_type; +} + +type_t *type_parameterized_type_specialize_define(type_t *type) +{ + type_t *tmpl = type->details.parameterized.type; + typeref_list_t *orig = tmpl->details.parameterized.params; + typeref_list_t *repl = type->details.parameterized.params; + type_t *iface = find_parameterized_type(tmpl, repl); + + if (type_get_type_detect_alias(type) != TYPE_PARAMETERIZED_TYPE || + type_get_type_detect_alias(tmpl) != TYPE_PARAMETERIZED_TYPE) + error_loc("cannot define non-parameterized type %s, declared at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + + if (type_get_type_detect_alias(tmpl->details.parameterized.type) == TYPE_INTERFACE && + type_get_type_detect_alias(iface) == TYPE_INTERFACE) + type_parameterized_interface_specialize(tmpl->details.parameterized.type, iface, orig, repl); + else + error_loc("pinterface %s previously not declared a pinterface at %s:%d\n", + iface->name, iface->loc_info.input_name, iface->loc_info.line_number); + + iface->defined = TRUE; + compute_method_indexes(iface); + return iface; +} + int type_is_equal(const type_t *type1, const type_t *type2) { if (type1 == type2) diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 6408fc0e409..4f2d39a0434 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -67,11 +67,16 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs); 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); +type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params); +type_t *type_parameterized_type_specialize_define(type_t *type); int type_is_equal(const type_t *type1, const type_t *type2); const char *type_get_name(const type_t *type, enum name_type name_type); char *gen_name(void); extern int is_attr(const attr_list_t *list, enum attr_type t);
+typeref_t *make_typeref(type_t *type); +typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref); + /* FIXME: shouldn't need to export this */ type_t *duptype(type_t *t, int dupname);
On 17.02.2021 19:33, Rémi Bernon wrote:
@@ -116,6 +116,7 @@ static struct namespace global_namespace = {
static struct namespace *current_namespace = &global_namespace; static struct namespace *parameters_namespace = NULL; +static statement_list_t *parameterized_type_stmts = NULL;
Sorry for not catching this earlier, but what's the reason for having this? Is for delaying specialization? It seems to me that you could just specialize the type as soon as it appears in 'declare' statement and avoid additional global list maintenance.
Thanks,
Jacek
On 2/17/21 8:40 PM, Jacek Caban wrote:
On 17.02.2021 19:33, Rémi Bernon wrote:
@@ -116,6 +116,7 @@ static struct namespace global_namespace = { static struct namespace *current_namespace = &global_namespace; static struct namespace *parameters_namespace = NULL; +static statement_list_t *parameterized_type_stmts = NULL;
Sorry for not catching this earlier, but what's the reason for having this? Is for delaying specialization? It seems to me that you could just specialize the type as soon as it appears in 'declare' statement and avoid additional global list maintenance.
Thanks,
Jacek
Yes, this is because we need to delay the instantiation.
I don't remember precisely, but I believe it's because the parameterized types generate their UUIDs from a signature computed recursively from their type parameters.
The signature includes the types UUIDs among other things, but so it can only be computed after the declaration of the types that are passed as parameters, and not in the declare block which can work with the forward declarations.
FWIW MIDL also generates the parameterized types specialized interfaces at the bottom of the headers, I guess maybe for the same reasons.
On 17.02.2021 22:06, Rémi Bernon wrote:
On 2/17/21 8:40 PM, Jacek Caban wrote:
On 17.02.2021 19:33, Rémi Bernon wrote:
@@ -116,6 +116,7 @@ static struct namespace global_namespace = { static struct namespace *current_namespace = &global_namespace; static struct namespace *parameters_namespace = NULL; +static statement_list_t *parameterized_type_stmts = NULL;
Sorry for not catching this earlier, but what's the reason for having this? Is for delaying specialization? It seems to me that you could just specialize the type as soon as it appears in 'declare' statement and avoid additional global list maintenance.
Thanks,
Jacek
Yes, this is because we need to delay the instantiation.
I don't remember precisely, but I believe it's because the parameterized types generate their UUIDs from a signature computed recursively from their type parameters.
The signature includes the types UUIDs among other things, but so it can only be computed after the declaration of the types that are passed as parameters, and not in the declare block which can work with the forward declarations.
FWIW MIDL also generates the parameterized types specialized interfaces at the bottom of the headers, I guess maybe for the same reasons.
Sounds good to me.
Jacek
Signed-off-by: Jacek Caban jacek@codeweavers.com