widl: Check that fields in structures and unions referenced by non-local functions can be marshalled and that their attributes are consistent.

This commit is contained in:
Rob Shearman 2008-04-20 22:15:16 +01:00 committed by Alexandre Julliard
parent 6e27e7840f
commit 15612e60fd
2 changed files with 82 additions and 14 deletions

View File

@ -1352,6 +1352,7 @@ static type_t *make_type(unsigned char type, type_t *ref)
t->written = FALSE; t->written = FALSE;
t->user_types_registered = FALSE; t->user_types_registered = FALSE;
t->tfswrite = FALSE; t->tfswrite = FALSE;
t->checked = FALSE;
t->typelib_idx = -1; t->typelib_idx = -1;
return t; return t;
} }
@ -2359,6 +2360,83 @@ static const attr_list_t *check_coclass_attrs(const char *name, const attr_list_
return attrs; return attrs;
} }
static void check_remoting_fields(type_t *type);
/* checks that properties common to fields and arguments are consistent */
static void check_field_common(const char *container_type,
const char *container_name, const var_t *arg)
{
type_t *type = arg->type;
int is_wire_marshal = 0;
int is_context_handle = 0;
if (is_attr(arg->attrs, ATTR_LENGTHIS) &&
(is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->type, ATTR_STRING)))
error_loc_info(&arg->loc_info,
"string and length_is specified for argument %s are mutually exclusive attributes\n",
arg->name);
/* get fundamental type for the argument */
for (;;)
{
if (is_attr(type->attrs, ATTR_WIREMARSHAL))
{
is_wire_marshal = 1;
break;
}
if (is_attr(type->attrs, ATTR_CONTEXTHANDLE))
{
is_context_handle = 1;
break;
}
if (type->kind == TKIND_ALIAS)
type = type->orig;
else if (is_ptr(type) || is_array(type))
type = type->ref;
else
break;
}
if (type->type == 0 && !is_attr(arg->attrs, ATTR_IIDIS) && !is_wire_marshal && !is_context_handle)
error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot derive from void *\n", arg->name, container_type, container_name);
else if (type->type == RPC_FC_FUNCTION)
error_loc_info(&arg->loc_info, "parameter \'%s\' of %s \'%s\' cannot be a function pointer\n", arg->name, container_type, container_name);
else if (!is_wire_marshal && (is_struct(type->type) || is_union(type->type)))
check_remoting_fields(type);
}
static void check_remoting_fields(type_t *type)
{
const char *container_type = NULL;
const var_t *field;
const var_list_t *fields = NULL;
if (type->checked)
return;
type->checked = TRUE;
if (is_struct(type->type))
{
fields = type->fields_or_args;
container_type = "structure";
}
else if (is_union(type->type))
{
if (type->type == RPC_FC_ENCAPSULATED_UNION)
{
const var_t *uv = LIST_ENTRY(list_tail(type->fields_or_args), const var_t, entry);
fields = uv->type->fields_or_args;
}
else
fields = type->fields_or_args;
container_type = "union";
}
if (fields) LIST_FOR_EACH_ENTRY( field, type->fields_or_args, const var_t, entry )
if (field->type) check_field_common(container_type, type->name, field);
}
/* checks that arguments for a function make sense for marshalling and unmarshalling */ /* checks that arguments for a function make sense for marshalling and unmarshalling */
static void check_remoting_args(const func_t *func) static void check_remoting_args(const func_t *func)
{ {
@ -2369,22 +2447,14 @@ static void check_remoting_args(const func_t *func)
{ {
int ptr_level = 0; int ptr_level = 0;
const type_t *type = arg->type; const type_t *type = arg->type;
int is_wire_marshal = 0;
int is_context_handle = 0;
/* get pointer level and fundamental type for the argument */ /* get pointer level and fundamental type for the argument */
for (;;) for (;;)
{ {
if (!is_wire_marshal && is_attr(type->attrs, ATTR_WIREMARSHAL)) if (is_attr(type->attrs, ATTR_WIREMARSHAL))
{
is_wire_marshal = 1;
break; break;
} if (is_attr(type->attrs, ATTR_CONTEXTHANDLE))
if (!is_context_handle && is_attr(type->attrs, ATTR_CONTEXTHANDLE))
{
is_context_handle = 1;
break; break;
}
if (type->kind == TKIND_ALIAS) if (type->kind == TKIND_ALIAS)
type = type->orig; type = type->orig;
else if (is_ptr(type)) else if (is_ptr(type))
@ -2408,10 +2478,7 @@ static void check_remoting_args(const func_t *func)
} }
} }
if (type->type == 0 && !is_attr(arg->attrs, ATTR_IIDIS) && !is_wire_marshal && !is_context_handle) check_field_common("function", funcname, arg);
error_loc_info(&arg->loc_info, "parameter \'%s\' of function \'%s\' cannot derive from void *\n", arg->name, funcname);
else if (type->type == RPC_FC_FUNCTION)
error_loc_info(&arg->loc_info, "parameter \'%s\' of function \'%s\' cannot be a function pointer\n", arg->name, funcname);
} }
} }

View File

@ -239,6 +239,7 @@ struct _type_t {
unsigned int written : 1; unsigned int written : 1;
unsigned int user_types_registered : 1; unsigned int user_types_registered : 1;
unsigned int tfswrite : 1; /* if the type needs to be written to the TFS */ unsigned int tfswrite : 1; /* if the type needs to be written to the TFS */
unsigned int checked : 1;
int sign : 2; int sign : 2;
}; };