[2/3] widl: Implement type redefinition checks.

Dan Hipschman dsh at linux.ucla.edu
Tue Jul 1 15:08:51 CDT 2008


This allows widl to catch type redefinitions and report an error, like MIDL.
However, this does a better job than MIDL since it also reports the location
of the originial definition, like GCC.

---
 tools/widl/parser.y    |   41 ++++++++++++++++++++++++++++++++++-------
 tools/widl/typelib.c   |    1 +
 tools/widl/widltypes.h |    3 +++
 3 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index bb54b43..fb526cc 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -156,6 +156,8 @@ static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs);
 static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs);
 const char *get_attr_display_name(enum attr_type type);
 static void add_explicit_handle_if_necessary(func_t *func);
+static type_t *find_type_helper(const char *name, int t);
+static void check_def(const type_t *t);
 
 static statement_t *make_statement(enum statement_type type);
 static statement_t *make_statement_type_decl(type_t *type);
@@ -845,12 +847,15 @@ int_std:  tINT					{ $$ = make_builtin($<str>1); }
 
 coclass:  tCOCLASS aIDENTIFIER			{ $$ = make_class($2); }
 	| tCOCLASS aKNOWNTYPE			{ $$ = find_type($2, 0);
-						  if ($$->defined) error_loc("multiple definition error\n");
-						  if ($$->kind != TKIND_COCLASS) error_loc("%s was not declared a coclass\n", $2);
+						  if ($$->kind != TKIND_COCLASS)
+						    error_loc("%s was not declared a coclass at %s:%d\n",
+							      $2, $$->loc_info.input_name,
+							      $$->loc_info.line_number);
 						}
 	;
 
 coclasshdr: attributes coclass			{ $$ = $2;
+						  check_def($$);
 						  $$->attrs = check_coclass_attrs($2->name, $1);
 						  if (!parse_only && do_header)
 						    write_coclass($$);
@@ -882,7 +887,7 @@ dispinterfacehdr: attributes dispinterface	{ attr_t *attrs;
 						  is_in_interface = TRUE;
 						  is_object_interface = TRUE;
 						  $$ = $2;
-						  if ($$->defined) error_loc("multiple definition error\n");
+						  check_def($$);
 						  attrs = make_attr(ATTR_DISPINTERFACE);
 						  $$->attrs = append_attr( check_dispiface_attrs($2->name, $1), attrs );
 						  $$->ref = find_type("IDispatch", 0);
@@ -934,7 +939,7 @@ interfacehdr: attributes interface		{ $$.interface = $2;
 						    pointer_default = get_attrv($1, ATTR_POINTERDEFAULT);
 						  is_object_interface = is_object($1);
 						  is_in_interface = TRUE;
-						  if ($2->defined) error_loc("multiple definition error\n");
+						  check_def($2);
 						  $2->attrs = check_iface_attrs($2->name, $1);
 						  $2->defined = TRUE;
 						  if (!parse_only && do_header) write_forward($2);
@@ -1060,6 +1065,7 @@ pointer_type:
 
 structdef: tSTRUCT t_ident '{' fields '}'	{ $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
                                                   /* overwrite RPC_FC_STRUCT with a more exact type */
+						  check_def($$);
 						  $$->type = get_struct_type( $4 );
 						  $$->kind = TKIND_RECORD;
 						  $$->fields_or_args = $4;
@@ -1089,6 +1095,7 @@ typedef: tTYPEDEF m_attributes decl_spec declarator_list
 
 uniondef: tUNION t_ident '{' ne_union_fields '}'
 						{ $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
+						  check_def($$);
 						  $$->kind = TKIND_UNION;
 						  $$->fields_or_args = $4;
 						  $$->defined = TRUE;
@@ -1097,6 +1104,7 @@ uniondef: tUNION t_ident '{' ne_union_fields '}'
 	  tSWITCH '(' s_field ')'
 	  m_ident '{' cases '}'			{ var_t *u = $7;
 						  $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
+						  check_def($$);
 						  $$->kind = TKIND_UNION;
 						  if (!u) u = make_var( xstrdup("tagged_union") );
 						  u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
@@ -1390,6 +1398,7 @@ type_t *make_type(unsigned char type, type_t *ref)
   t->tfswrite = FALSE;
   t->checked = FALSE;
   t->typelib_idx = -1;
+  init_loc_info(&t->loc_info);
   return t;
 }
 
@@ -1701,9 +1710,7 @@ static var_t *make_var(char *name)
   v->attrs = NULL;
   v->eval = NULL;
   v->stgclass = STG_NONE;
-  v->loc_info.input_name = input_name ? input_name : "stdin";
-  v->loc_info.line_number = line_number;
-  v->loc_info.near_text = parser_text;
+  init_loc_info(&v->loc_info);
   return v;
 }
 
@@ -1894,6 +1901,12 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
     if (name->name) {
       type_t *cur;
 
+      cur = find_type_helper(name->name, 0);
+      if (cur)
+          error_loc("%s: redefinition error; original definition was at %s:%d\n",
+                    cur->name, cur->loc_info.input_name,
+                    cur->loc_info.line_number);
+
       /* set the attributes to allow set_type to do some checks on them */
       name->attrs = attrs;
       set_type(name, decl_spec, decl, 0);
@@ -2891,3 +2904,17 @@ static func_list_t *append_func_from_statement(func_list_t *list, statement_t *s
     }
     return list;
 }
+
+void init_loc_info(loc_info_t *i)
+{
+    i->input_name = input_name ? input_name : "stdin";
+    i->line_number = line_number;
+    i->near_text = parser_text;
+}
+
+static void check_def(const type_t *t)
+{
+    if (t->defined)
+        error_loc("%s: redefinition error; original definition was at %s:%d\n",
+                  t->name, t->loc_info.input_name, t->loc_info.line_number);
+}
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index 4102fad..b30b323 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -70,6 +70,7 @@ type_t *alias(type_t *t, const char *name)
   a->kind = TKIND_ALIAS;
   a->attrs = NULL;
   a->declarray = FALSE;
+  init_loc_info(&a->loc_info);
 
   return a;
 }
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index c3a3948..d00a732 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -274,6 +274,7 @@ struct _type_t {
   unsigned int typestring_offset;
   unsigned int ptrdesc;           /* used for complex structs */
   int typelib_idx;
+  loc_info_t loc_info;
   unsigned int declarray : 1;     /* if declared as an array */
   unsigned int ignore : 1;
   unsigned int defined : 1;
@@ -410,6 +411,8 @@ var_t *find_const(const char *name, int f);
 type_t *find_type(const char *name, int t);
 type_t *make_type(unsigned char type, type_t *ref);
 
+void init_loc_info(loc_info_t *);
+
 static inline type_t *get_func_return_type(const func_t *func)
 {
   return func->def->type->ref;



More information about the wine-patches mailing list