[PATCH 1/4] widl: Track whether the type has been defined yet in the statement_t and var_t structures.

Zebediah Figura z.figura12 at gmail.com
Mon Aug 19 21:17:36 CDT 2019


Based on a patch by Richard Pospesel.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47149
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 tools/widl/header.c    | 37 +++++++++++++++++++------------------
 tools/widl/parser.y    | 10 +++++++---
 tools/widl/widltypes.h |  3 +++
 3 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index c20fe69917..61fadcf72f 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -43,7 +43,7 @@ user_type_list_t user_type_list = LIST_INIT(user_type_list);
 context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
 generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
 
-static void write_type_def_or_decl(FILE *f, const decl_spec_t *t, int field, const char *name);
+static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name);
 
 static void indent(FILE *h, int delta)
 {
@@ -252,7 +252,7 @@ static void write_fields(FILE *h, var_list_t *fields)
         default:
             ;
         }
-        write_type_def_or_decl(h, &v->declspec, TRUE, name);
+        write_type_v(h, &v->declspec, TRUE, v->declonly, name);
         fprintf(h, ";\n");
     }
 }
@@ -328,7 +328,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
   else {
     switch (type_get_type_detect_alias(t)) {
       case TYPE_ENUM:
-        if (!declonly && t->defined && !t->written) {
+        if (!declonly && !t->written) {
+          assert(t->defined);
           if (name) fprintf(h, "enum %s {\n", name);
           else fprintf(h, "enum {\n");
           t->written = TRUE;
@@ -341,7 +342,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
         break;
       case TYPE_STRUCT:
       case TYPE_ENCAPSULATED_UNION:
-        if (!declonly && t->defined && !t->written) {
+        if (!declonly && !t->written) {
+          assert(t->defined);
           if (name) fprintf(h, "struct %s {\n", name);
           else fprintf(h, "struct {\n");
           t->written = TRUE;
@@ -356,7 +358,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
         else fprintf(h, "struct %s", name ? name : "");
         break;
       case TYPE_UNION:
-        if (!declonly && t->defined && !t->written) {
+        if (!declonly && !t->written) {
+          assert(t->defined);
           if (t->name) fprintf(h, "union %s {\n", t->name);
           else fprintf(h, "union {\n");
           t->written = TRUE;
@@ -547,12 +550,7 @@ static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declo
         write_type_right(h, t, is_field);
 }
 
-static void write_type_def_or_decl(FILE *f, const decl_spec_t *t, int field, const char *name)
-{
-  write_type_v(f, t, field, FALSE, name);
-}
-
-static void write_type_definition(FILE *f, type_t *t)
+static void write_type_definition(FILE *f, type_t *t, int declonly)
 {
     int in_namespace = t->namespace && !is_global_namespace(t->namespace);
     int save_written = t->written;
@@ -564,14 +562,14 @@ static void write_type_definition(FILE *f, type_t *t)
         write_namespace_start(f, t->namespace);
     }
     indent(f, 0);
-    write_type_left(f, &ds, NAME_DEFAULT, FALSE, TRUE);
+    write_type_left(f, &ds, NAME_DEFAULT, declonly, TRUE);
     fprintf(f, ";\n");
     if(in_namespace) {
         t->written = save_written;
         write_namespace_end(f, t->namespace);
         fprintf(f, "extern \"C\" {\n");
         fprintf(f, "#else\n");
-        write_type_left(f, &ds, NAME_C, FALSE, TRUE);
+        write_type_left(f, &ds, NAME_C, declonly, TRUE);
         fprintf(f, ";\n");
         fprintf(f, "#endif\n\n");
     }
@@ -805,10 +803,10 @@ static void write_generic_handle_routines(FILE *header)
   }
 }
 
-static void write_typedef(FILE *header, type_t *type)
+static void write_typedef(FILE *header, type_t *type, int declonly)
 {
   fprintf(header, "typedef ");
-  write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name);
+  write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name);
   fprintf(header, ";\n");
 }
 
@@ -852,7 +850,7 @@ static void write_declaration(FILE *header, const var_t *v)
         fprintf(header, "extern ");
         break;
     }
-    write_type_def_or_decl(header, &v->declspec, FALSE, v->name);
+    write_type_v(header, &v->declspec, FALSE, v->declonly, v->name);
     fprintf(header, ";\n\n");
   }
 }
@@ -1092,6 +1090,9 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
         }
         else fprintf(h, ",");
     }
+    /* In theory we should be writing the definition using write_type_v(..., arg->declonly),
+     * but that causes redefinition in e.g. proxy files. In fact MIDL disallows
+     * defining UDTs inside of an argument list. */
     write_type_decl(h, &arg->declspec, arg->name);
     if (method == 2) {
         const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE);
@@ -1733,7 +1734,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
           write_coclass(header, stmt->u.type);
         else
         {
-          write_type_definition(header, stmt->u.type);
+          write_type_definition(header, stmt->u.type, stmt->declonly);
         }
         break;
       case STMT_TYPEREF:
@@ -1754,7 +1755,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
       {
         const type_list_t *type_entry = stmt->u.type_list;
         for (; type_entry; type_entry = type_entry->next)
-	  write_typedef(header, type_entry->type);
+          write_typedef(header, type_entry->type, stmt->declonly);
         break;
       }
       case STMT_LIBRARY:
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index afbe2b1799..bdbd44040c 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -116,7 +116,7 @@ static statement_t *make_statement_pragma(const char *str);
 static statement_t *make_statement_cppquote(const char *str);
 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);
+static statement_t *make_statement_typedef(var_list_t *names, int declonly);
 static statement_t *make_statement_import(const char *str);
 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 *);
@@ -1115,7 +1115,7 @@ type:	  tVOID					{ $$ = type_new_void(); }
 typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list
 						{ $1 = append_attribs($1, $3);
 						  reg_typedefs($4, $5, check_typedef_attrs($1));
-						  $$ = make_statement_typedef($5);
+						  $$ = make_statement_typedef($5, !$4->type->defined);
 						}
 	;
 
@@ -1546,6 +1546,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator
   v->declspec.type = decl->type;
   v->declspec.qualifier = decl->qualifier;
   v->attrs = attrs;
+  v->declonly = !type->defined;
 
   if (is_attr(type->attrs, ATTR_CALLCONV) && !is_func(type))
     error_loc("calling convention applied to non-function type\n");
@@ -1750,6 +1751,7 @@ var_t *make_var(char *name)
   v->attrs = NULL;
   v->eval = NULL;
   init_loc_info(&v->loc_info);
+  v->declonly = FALSE;
   return v;
 }
 
@@ -2912,6 +2914,7 @@ static statement_t *make_statement_type_decl(type_t *type)
 {
     statement_t *stmt = make_statement(STMT_TYPE);
     stmt->u.type = type;
+    stmt->declonly = !type->defined;
     return stmt;
 }
 
@@ -2982,7 +2985,7 @@ static statement_t *make_statement_module(type_t *type)
     return stmt;
 }
 
-static statement_t *make_statement_typedef(declarator_list_t *decls)
+static statement_t *make_statement_typedef(declarator_list_t *decls, int declonly)
 {
     declarator_t *decl, *next;
     statement_t *stmt;
@@ -2993,6 +2996,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls)
     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 )
     {
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 3886360bd4..7a7bd8991e 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -478,6 +478,8 @@ struct _var_t {
 
   struct _loc_info_t loc_info;
 
+  unsigned int declonly : 1;
+
   /* parser-internal */
   struct list entry;
 };
@@ -560,6 +562,7 @@ struct _statement_t {
         typelib_t *lib;
         type_list_t *type_list;
     } u;
+    unsigned int declonly : 1; /* for STMT_TYPE and STMT_TYPEDEF */
 };
 
 struct _warning_t {
-- 
2.22.0




More information about the wine-devel mailing list