From 6725c5d756dc6cd1dc19e7de0e0c45005a2024a2 Mon Sep 17 00:00:00 2001 From: Dan Hipschman Date: Tue, 1 Jul 2008 13:08:51 -0700 Subject: [PATCH] widl: Implement type redefinition checks. 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 6616193a776..fc27b2d00d3 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($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); @@ -2896,3 +2909,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 4102fad6313..b30b323ed16 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 c3a39483929..d00a73255ca 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;