Rob Shearman : widl: Check that fields in structures and unions referenced by non-local functions can be marshalled and that their attributes are consistent .
Alexandre Julliard
julliard at winehq.org
Mon Apr 21 07:46:17 CDT 2008
Module: wine
Branch: master
Commit: 15612e60fd20138baa0fe20c24ff3f2c447ad40f
URL: http://source.winehq.org/git/wine.git/?a=commit;h=15612e60fd20138baa0fe20c24ff3f2c447ad40f
Author: Rob Shearman <rob at codeweavers.com>
Date: Sun Apr 20 22:15:16 2008 +0100
widl: Check that fields in structures and unions referenced by non-local functions can be marshalled and that their attributes are consistent.
---
tools/widl/parser.y | 95 +++++++++++++++++++++++++++++++++++++++++-------
tools/widl/widltypes.h | 1 +
2 files changed, 82 insertions(+), 14 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index d4ba87a..4d04546 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1352,6 +1352,7 @@ static type_t *make_type(unsigned char type, type_t *ref)
t->written = FALSE;
t->user_types_registered = FALSE;
t->tfswrite = FALSE;
+ t->checked = FALSE;
t->typelib_idx = -1;
return t;
}
@@ -2359,6 +2360,83 @@ static const attr_list_t *check_coclass_attrs(const char *name, const attr_list_
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 */
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;
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 */
for (;;)
{
- if (!is_wire_marshal && is_attr(type->attrs, ATTR_WIREMARSHAL))
- {
- is_wire_marshal = 1;
+ if (is_attr(type->attrs, ATTR_WIREMARSHAL))
break;
- }
- if (!is_context_handle && is_attr(type->attrs, ATTR_CONTEXTHANDLE))
- {
- is_context_handle = 1;
+ if (is_attr(type->attrs, ATTR_CONTEXTHANDLE))
break;
- }
if (type->kind == TKIND_ALIAS)
type = type->orig;
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)
- 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);
+ check_field_common("function", funcname, arg);
}
}
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 89d593a..dfae4dd 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -239,6 +239,7 @@ struct _type_t {
unsigned int written : 1;
unsigned int user_types_registered : 1;
unsigned int tfswrite : 1; /* if the type needs to be written to the TFS */
+ unsigned int checked : 1;
int sign : 2;
};
More information about the wine-cvs
mailing list