[PATCH 5/6] widl: Implement initial support for generics.

Rémi Bernon rbernon at codeweavers.com
Wed Aug 26 17:57:09 CDT 2020


This 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 <rbernon at codeweavers.com>
---
 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 ff4fb4bc210..856cec9da05 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;
@@ -519,6 +522,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 d0883f7b8ab..1ca1ecb23c7 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -274,7 +274,7 @@ static typelib_t *current_typelib;
 %type <str> namespacedef
 %type <type> base_type int_std
 %type <type> enumdef structdef uniondef typedecl
-%type <type> type qualified_seq qualified_type
+%type <type> type qualified_seq qualified_type generics_type generics_decl
 %type <ifref> coclass_int
 %type <ifref_list> coclass_ints
 %type <var> 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); }
@@ -2431,6 +2449,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 1634f9bd50b..47704ce7d34 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -432,6 +432,7 @@ enum type_type
     TYPE_POINTER,
     TYPE_ARRAY,
     TYPE_BITFIELD,
+    TYPE_GENERIC,
 };
 
 struct _type_t {
-- 
2.28.0




More information about the wine-devel mailing list