[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