From: Hans Leidekker hans@codeweavers.com
--- tools/widl/parser.y | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 1e83cd2802f..7a79f4cb9b8 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -2610,6 +2610,51 @@ static void check_eventremove_args(const var_t *func) } }
+static int is_size_parameter(const var_t *param, const var_list_t *arg_list) +{ + const var_t *arg; + + LIST_FOR_EACH_ENTRY(arg, arg_list, var_t, entry) + { + const type_t *type = arg->declspec.type; + const expr_t *size_is; + + if (is_ptr(type)) type = type_pointer_get_ref_type(type); + if (type->type_type != TYPE_ARRAY || !(size_is = type_array_get_conformance(type))) continue; + + if (size_is->type == EXPR_PPTR) size_is = size_is->ref; + if (!strcmp(param->name, size_is->u.sval)) return 1; + } + return 0; +} + +static void check_propget_args(const var_t *func) +{ + const var_t *arg; + const var_list_t *arg_list = type_function_get_args(func->declspec.type); + unsigned int count = 0; + + if (!is_attr(func->attrs, ATTR_PROPGET)) return; + + LIST_FOR_EACH_ENTRY_REV(arg, arg_list, const var_t, entry) + { + const type_t *type = arg->declspec.type; + int is_size = is_size_parameter(arg, arg_list); + + count++; + if (count == 1 && (!is_ptr(type) || !is_attr(arg->attrs, ATTR_RETVAL))) + error_at( &arg->where, "last parameter '%s' of function '%s' must be an [out, retval] pointer\n", + arg->name, func->name ); + + if (count == 2 && !is_size) + error_at( &arg->where, "parameter '%s' of function '%s' must be a size_is parameter\n", + arg->name, func->name ); + + if ((is_size && count > 2) || (!is_size && count > 1)) + error_at( &arg->where, "propget function '%s' has too many parameters\n", func->name ); + } +} + /* checks that arguments for a function make sense for marshalling and unmarshalling */ static void check_remoting_args(const var_t *func) { @@ -2621,6 +2666,7 @@ static void check_remoting_args(const var_t *func)
if (winrt_mode) { + check_propget_args(func); check_eventadd_args(func); check_eventremove_args(func); }