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