Module: wine Branch: master Commit: 5f39b415265eb72e1dd3b3da5996cf77fa2f652d URL: http://source.winehq.org/git/wine.git/?a=commit;h=5f39b415265eb72e1dd3b3da59...
Author: Rob Shearman rob@codeweavers.com Date: Mon Apr 14 10:59:12 2008 +0100
widl: Check that attributes applied to interfaces, functions and arguments are applicable and issue an error if not.
---
tools/widl/parser.y | 139 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 133 insertions(+), 6 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 46418a3..49f7633 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -130,6 +130,8 @@ static char *gen_name(void); static void process_typedefs(var_list_t *names); static void check_arg(var_t *arg); static void check_all_user_types(ifref_list_t *ifaces); +static const attr_list_t *check_iface_attrs(const char *name, const attr_list_t *attrs); +static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs);
#define tsENUM 1 #define tsSTRUCT 2 @@ -662,13 +664,10 @@ s_field: m_attributes type pident array { $$ = $3->var; funcdef: m_attributes type pident { var_t *v = $3->var; var_list_t *args = $3->args; - v->attrs = $1; + v->attrs = check_function_attrs(v->name, $1); set_type(v, $2, $3, NULL, FALSE); free($3); $$ = make_func(v, args); - if (is_attr(v->attrs, ATTR_IN)) { - error_loc("inapplicable attribute [in] for function '%s'\n",$$->def->name); - } } ;
@@ -816,7 +815,7 @@ interfacehdr: attributes interface { $$.interface = $2; pointer_default = get_attrv($1, ATTR_POINTERDEFAULT); is_object_interface = is_object($1); if ($2->defined) error_loc("multiple definition error\n"); - $2->attrs = $1; + $2->attrs = check_iface_attrs($2->name, $1); $2->defined = TRUE; if (!parse_only && do_header) write_forward($2); } @@ -2114,12 +2113,140 @@ static void process_typedefs(pident_list_t *pidents) } }
+struct allowed_attr +{ + unsigned int dce_compatible : 1; + unsigned int acf : 1; + unsigned int on_interface : 1; + unsigned int on_function : 1; + unsigned int on_arg : 1; + unsigned int on_type : 1; + unsigned int on_field : 1; + unsigned int on_library : 1; + unsigned int on_dispinterface : 1; + unsigned int on_module : 1; + unsigned int on_coclass : 1; + const char *display_name; +}; + +struct allowed_attr allowed_attr[] = +{ + /* attr { D ACF I Fn ARG T Fi L DI M C <display name> } */ + /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "aggregatable" }, + /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "appobject" }, + /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, "async" }, + /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, + /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "bindable" }, + /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "call_as" }, + /* ATTR_CALLCONV */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" }, + /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "context_handle" }, + /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, + /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, "default" }, + /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, + /* ATTR_DEFAULTVALUE_EXPR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "defaultvalue" }, + /* ATTR_DEFAULTVALUE_STRING */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "defaultvalue" }, + /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "defaultvtable" }, + /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, + /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "dllname" }, + /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, + /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, + /* ATTR_ENTRY_ORDINAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "entry" }, + /* ATTR_ENTRY_STRING */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "entry" }, + /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, + /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "handle" }, + /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, "helpcontext" }, + /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpfile" }, + /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, "helpstring" }, + /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, "helpstringcontext" }, + /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpstringdll" }, + /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, "hidden" }, + /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, "id" }, + /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, + /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "iid_is" }, + /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, + /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, + /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "in" }, + /* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, + /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "length_is" }, + /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, "local" }, + /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, + /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "noncreatable" }, + /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, + /* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, + /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "odl" }, + /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, + /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "optional" }, + /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "out" }, + /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, + /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, "ref, unique or ptr" }, + /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "propget" }, + /* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "propput" }, + /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "propputref" }, + /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "public" }, + /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, "range" }, + /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "readonly" }, + /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, + /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, "restricted" }, + /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "retval" }, + /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "size_is" }, + /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, "source" }, + /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, + /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, "string" }, + /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "switch_is" }, + /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "switch_type" }, + /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "transmit_as" }, + /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, "uuid" }, + /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "v1_enum" }, + /* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "vararg" }, + /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, "version" }, + /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "wire_marshal" }, +}; + +static const attr_list_t *check_iface_attrs(const char *name, const attr_list_t *attrs) +{ + const attr_t *attr; + if (!attrs) return attrs; + LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) + { + if (!allowed_attr[attr->type].on_interface) + error_loc("inapplicable attribute %s for interface %s\n", + allowed_attr[attr->type].display_name, name); + } + return attrs; +} + +static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs) +{ + const attr_t *attr; + if (!attrs) return attrs; + LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) + { + if (!allowed_attr[attr->type].on_function) + error_loc("inapplicable attribute %s for function %s\n", + allowed_attr[attr->type].display_name, name); + } + return attrs; +} + static void check_arg(var_t *arg) { - type_t *t = arg->type; + const type_t *t = arg->type; + const attr_t *attr;
if (t->type == 0 && ! is_var_ptr(arg)) error_loc("argument '%s' has void type\n", arg->name); + + if (arg->attrs) + { + LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry) + { + if (!allowed_attr[attr->type].on_arg) + error_loc("inapplicable attribute %s for argument %s\n", + allowed_attr[attr->type].display_name, arg->name); + } + } }
static void check_all_user_types(ifref_list_t *ifrefs)