[2/2] widl: Fix incomplete struct/union typedef bug

Dan Hipschman dsh at linux.ucla.edu
Thu Jun 7 19:43:58 CDT 2007


This fixes another problem that shows up compiling oaidl.idl.  The problem
is that if you alias an incomplete structure or union type, as with:

	typedef struct foo foo_t;

where struct foo hasn't been defined yet, the type foo_t won't get updated
when the structure is defined.

---
 tools/widl/parser.y    |   51 +++++++++++++++++++++++++++++++++++++++++++++++-
 tools/widl/typegen.c   |    4 +-
 tools/widl/widltypes.h |    2 +
 3 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 00d3b4d..b5c1865 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -65,6 +65,17 @@
 # endif
 #endif
 
+typedef struct list typelist_t;
+struct typenode {
+  type_t *type;
+  struct list entry;
+};
+
+typelist_t incomplete_types = LIST_INIT(incomplete_types);
+
+static void add_incomplete(type_t *t);
+static void fix_incomplete(void);
+
 static str_list_t *append_str(str_list_t *list, char *str);
 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
 static attr_t *make_attr(enum attr_type type);
@@ -263,7 +274,11 @@ static void check_arg(var_t *arg);
 
 %%
 
-input:   gbl_statements                        { write_proxies($1); write_client($1); write_server($1); }
+input:   gbl_statements				{ fix_incomplete();
+						  write_proxies($1);
+						  write_client($1);
+						  write_server($1);
+						}
 	;
 
 gbl_statements:					{ $$ = NULL; }
@@ -1475,6 +1490,38 @@ static type_t *reg_type(type_t *type, const char *name, int t)
   return type;
 }
 
+static int is_incomplete(const type_t *t)
+{
+  return !t->defined && (is_struct(t->type) || is_union(t->type));
+}
+
+static void add_incomplete(type_t *t)
+{
+  struct typenode *tn = xmalloc(sizeof *tn);
+  tn->type = t;
+  list_add_tail(&incomplete_types, &tn->entry);
+}
+
+static void fix_type(type_t *t)
+{
+  if (t->kind == TKIND_ALIAS && is_incomplete(t)) {
+    type_t *ot = t->orig;
+    fix_type(ot);
+    t->fields = ot->fields;
+    t->defined = ot->defined;
+  }
+}
+
+static void fix_incomplete(void)
+{
+  struct typenode *tn, *next;
+
+  LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) {
+    fix_type(tn->type);
+    free(tn);
+  }
+}
+
 static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *attrs)
 {
   type_t *ptr = type;
@@ -1544,6 +1591,8 @@ static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *a
         yyerror("'%s': [string] attribute applied to non-pointer type",
                 cur->name);
 
+      if (is_incomplete(cur))
+        add_incomplete(cur);
       reg_type(cur, cur->name, 0);
     }
   }
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 7c0921e..8f4c926 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -109,7 +109,7 @@ const char *string_of_type(unsigned char type)
     }
 }
 
-static int is_struct(unsigned char type)
+int is_struct(unsigned char type)
 {
     switch (type)
     {
@@ -125,7 +125,7 @@ static int is_struct(unsigned char type)
     }
 }
 
-static int is_union(unsigned char type)
+int is_union(unsigned char type)
 {
     switch (type)
     {
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index fb8e5fb..0c8acad 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -305,5 +305,7 @@ int is_ptr(const type_t *t);
 int is_array(const type_t *t);
 int is_var_ptr(const var_t *v);
 int cant_be_null(const var_t *v);
+int is_struct(unsigned char tc);
+int is_union(unsigned char tc);
 
 #endif



More information about the wine-patches mailing list