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.
This commit is contained in:
Dan Hipschman 2008-07-01 13:08:51 -07:00 committed by Alexandre Julliard
parent 6db7ce7a6d
commit 6725c5d756
3 changed files with 38 additions and 7 deletions

View File

@ -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);
@ -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);
}

View File

@ -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;
}

View File

@ -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;