widl: Import Wine version 7dcdd7a6549793e8

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
diff --git a/mingw-w64-tools/widl/VERSION b/mingw-w64-tools/widl/VERSION
index 7a0caa1..953a3bc 100644
--- a/mingw-w64-tools/widl/VERSION
+++ b/mingw-w64-tools/widl/VERSION
@@ -1 +1 @@
-WIDL version 10.12
+WIDL version 10.13
diff --git a/mingw-w64-tools/widl/configure b/mingw-w64-tools/widl/configure
index 0e191c7..f92ea5a 100755
--- a/mingw-w64-tools/widl/configure
+++ b/mingw-w64-tools/widl/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for widl 10.12.
+# Generated by GNU Autoconf 2.72 for widl 10.13.
 #
 # Report bugs to <mingw-w64-public@lists.sourceforge.net>.
 #
@@ -603,8 +603,8 @@
 # Identity of this package.
 PACKAGE_NAME='widl'
 PACKAGE_TARNAME='widl'
-PACKAGE_VERSION='10.12'
-PACKAGE_STRING='widl 10.12'
+PACKAGE_VERSION='10.13'
+PACKAGE_STRING='widl 10.13'
 PACKAGE_BUGREPORT='mingw-w64-public@lists.sourceforge.net'
 PACKAGE_URL=''
 
@@ -1311,7 +1311,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures widl 10.12 to adapt to many kinds of systems.
+'configure' configures widl 10.13 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1383,7 +1383,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of widl 10.12:";;
+     short | recursive ) echo "Configuration of widl 10.13:";;
    esac
   cat <<\_ACEOF
 
@@ -1485,7 +1485,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-widl configure 10.12
+widl configure 10.13
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -1910,7 +1910,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by widl $as_me 10.12, which was
+It was created by widl $as_me 10.13, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3327,7 +3327,7 @@
 
 # Define the identity of the package.
  PACKAGE='widl'
- VERSION='10.12'
+ VERSION='10.13'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -5797,7 +5797,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by widl $as_me 10.12, which was
+This file was extended by widl $as_me 10.13, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -5865,7 +5865,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-widl config.status 10.12
+widl config.status 10.13
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 
diff --git a/mingw-w64-tools/widl/include/bcrypt.h b/mingw-w64-tools/widl/include/bcrypt.h
index b7d6c16..3333d2a 100644
--- a/mingw-w64-tools/widl/include/bcrypt.h
+++ b/mingw-w64-tools/widl/include/bcrypt.h
@@ -91,6 +91,7 @@
 #define BCRYPT_DSA_ALGORITHM        L"DSA"
 #define BCRYPT_ECDH_P256_ALGORITHM  L"ECDH_P256"
 #define BCRYPT_ECDH_P384_ALGORITHM  L"ECDH_P384"
+#define BCRYPT_ECDH_P521_ALGORITHM  L"ECDH_P521"
 #define BCRYPT_ECDSA_P256_ALGORITHM L"ECDSA_P256"
 #define BCRYPT_ECDSA_P384_ALGORITHM L"ECDSA_P384"
 #define BCRYPT_ECDSA_P521_ALGORITHM L"ECDSA_P521"
@@ -175,6 +176,7 @@
 static const WCHAR BCRYPT_DSA_ALGORITHM[] = {'D','S','A',0};
 static const WCHAR BCRYPT_ECDH_P256_ALGORITHM[] = {'E','C','D','H','_','P','2','5','6',0};
 static const WCHAR BCRYPT_ECDH_P384_ALGORITHM[] = {'E','C','D','H','_','P','3','8','4',0};
+static const WCHAR BCRYPT_ECDH_P521_ALGORITHM[] = {'E','C','D','H','_','P','5','2','1',0};
 static const WCHAR BCRYPT_ECDSA_P256_ALGORITHM[] = {'E','C','D','S','A','_','P','2','5','6',0};
 static const WCHAR BCRYPT_ECDSA_P384_ALGORITHM[] = {'E','C','D','S','A','_','P','3','8','4',0};
 static const WCHAR BCRYPT_ECDSA_P521_ALGORITHM[] = {'E','C','D','S','A','_','P','5','2','1',0};
diff --git a/mingw-w64-tools/widl/include/processthreadsapi.h b/mingw-w64-tools/widl/include/processthreadsapi.h
index 44cb251..c205824 100644
--- a/mingw-w64-tools/widl/include/processthreadsapi.h
+++ b/mingw-w64-tools/widl/include/processthreadsapi.h
@@ -49,6 +49,21 @@
 WINBASEAPI HRESULT WINAPI SetThreadDescription(HANDLE,PCWSTR);
 WINBASEAPI BOOL WINAPI SetThreadInformation(HANDLE,THREAD_INFORMATION_CLASS,LPVOID,DWORD);
 
+typedef enum _QUEUE_USER_APC_FLAGS
+{
+    QUEUE_USER_APC_FLAGS_NONE,
+    QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC = 0x00000001,
+    QUEUE_USER_APC_CALLBACK_DATA_CONTEXT = 0x00010000,
+} QUEUE_USER_APC_FLAGS;
+
+typedef struct _APC_CALLBACK_DATA
+{
+    ULONG_PTR Parameter;
+    CONTEXT *ContextRecord;
+    ULONG_PTR Reserved0;
+    ULONG_PTR Reserved1;
+} APC_CALLBACK_DATA, *PAPC_CALLBACK_DATA;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/mingw-w64-tools/widl/include/winbase.h b/mingw-w64-tools/widl/include/winbase.h
index 29a3ea8..c96f58a 100644
--- a/mingw-w64-tools/widl/include/winbase.h
+++ b/mingw-w64-tools/widl/include/winbase.h
@@ -2293,6 +2293,7 @@
 WINBASEAPI BOOL        WINAPI QueryPerformanceFrequency(LARGE_INTEGER*);
 WINBASEAPI BOOL        WINAPI QueryUmsThreadInformation(PUMS_CONTEXT,UMS_THREAD_INFO_CLASS,PVOID,ULONG,PULONG);
 WINBASEAPI DWORD       WINAPI QueueUserAPC(PAPCFUNC,HANDLE,ULONG_PTR);
+WINBASEAPI DWORD       WINAPI QueueUserAPC2(PAPCFUNC,HANDLE,ULONG_PTR,QUEUE_USER_APC_FLAGS);
 WINBASEAPI BOOL        WINAPI QueueUserWorkItem(LPTHREAD_START_ROUTINE,PVOID,ULONG);
 WINBASEAPI void        WINAPI RaiseException(DWORD,DWORD,DWORD,const ULONG_PTR *);
 WINBASEAPI HANDLE      WINAPI ReOpenFile(HANDLE,DWORD,DWORD,DWORD);
@@ -2479,6 +2480,7 @@
 WINBASEAPI BOOL        WINAPI VirtualLock(LPVOID,SIZE_T);
 WINBASEAPI BOOL        WINAPI VirtualProtect(LPVOID,SIZE_T,DWORD,LPDWORD);
 WINBASEAPI BOOL        WINAPI VirtualProtectEx(HANDLE,LPVOID,SIZE_T,DWORD,LPDWORD);
+WINBASEAPI BOOL        WINAPI VirtualProtectFromApp(LPVOID,SIZE_T,ULONG,PULONG);
 WINBASEAPI SIZE_T      WINAPI VirtualQuery(LPCVOID,PMEMORY_BASIC_INFORMATION,SIZE_T);
 WINBASEAPI SIZE_T      WINAPI VirtualQueryEx(HANDLE,LPCVOID,PMEMORY_BASIC_INFORMATION,SIZE_T);
 WINBASEAPI BOOL        WINAPI VirtualUnlock(LPVOID,SIZE_T);
diff --git a/mingw-w64-tools/widl/include/winnt.h b/mingw-w64-tools/widl/include/winnt.h
index f0ab49e..a76d58d 100644
--- a/mingw-w64-tools/widl/include/winnt.h
+++ b/mingw-w64-tools/widl/include/winnt.h
@@ -6163,6 +6163,14 @@
     GUID *ObjectType;
 } OBJECT_TYPE_LIST, *POBJECT_TYPE_LIST;
 
+typedef enum _AUDIT_EVENT_TYPE
+{
+    AuditEventObjectAccess,
+    AuditEventDirectoryServiceAccess
+} AUDIT_EVENT_TYPE, *PAUDIT_EVENT_TYPE;
+
+#define AUDIT_ALLOW_NO_PRIVILEGE 0x1
+
 typedef struct _RTL_CRITICAL_SECTION_DEBUG
 {
   WORD   Type;
diff --git a/mingw-w64-tools/widl/src/attribute.c b/mingw-w64-tools/widl/src/attribute.c
index bcd804e..0268cde 100644
--- a/mingw-w64-tools/widl/src/attribute.c
+++ b/mingw-w64-tools/widl/src/attribute.c
@@ -103,6 +103,17 @@
     }
 }
 
+void get_version( const attr_list_t *list, unsigned short *major, unsigned short *minor )
+{
+    version_t *version = get_attrp( list, ATTR_VERSION );
+    if (version)
+    {
+        *major = version->major;
+        *minor = version->minor;
+    }
+    else *major = *minor = 0;
+}
+
 struct allowed_attr
 {
     unsigned int dce_compatible : 1;
@@ -134,6 +145,7 @@
     /* ATTR_AGGREGATABLE */        { 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" },
     /* ATTR_ALLOCATE */            { 0, 1, 0,  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "allocate" },
     /* ATTR_ANNOTATION */          { 0, 0, 0,  0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" },
+    /* ATTR_APICONTACT */          { 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "apicontract" },
     /* ATTR_APPOBJECT */           { 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" },
     /* ATTR_ASYNC */               { 0, 1, 0,  0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
     /* ATTR_ASYNCUUID */           { 1, 0, 0,  1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" },
@@ -477,13 +489,18 @@
 attr_list_t *check_runtimeclass_attrs( const char *name, attr_list_t *attrs )
 {
     const attr_t *attr;
+    bool found_version = false;
     if (!attrs) return NULL;
     LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry )
     {
         if (!allowed_attr[attr->type].on_runtimeclass)
             error_at( &attr->where, "inapplicable attribute %s for runtimeclass %s\n",
                       allowed_attr[attr->type].display_name, name );
+        if (attr->type == ATTR_CONTRACT || attr->type == ATTR_VERSION)
+            found_version = true;
     }
+    if (!found_version)
+        error_at( NULL, "runtimeclass %s requires contract or version attribute\n", name );
     return attrs;
 }
 
diff --git a/mingw-w64-tools/widl/src/client.c b/mingw-w64-tools/widl/src/client.c
index 795e3ba..e5d93cd 100644
--- a/mingw-w64-tools/widl/src/client.c
+++ b/mingw-w64-tools/widl/src/client.c
@@ -439,9 +439,11 @@
 
 static void write_clientinterfacedecl(type_t *iface)
 {
-    unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
     const struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID);
     const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT);
+    unsigned short major, minor;
+
+    get_version( iface->attrs, &major, &minor );
 
     if (endpoints) write_endpoints( client, iface->name, endpoints );
 
@@ -452,7 +454,7 @@
     print_client("{{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n",
                  uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
                  uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
-                 uuid->Data4[7], MAJORVERSION(ver), MINORVERSION(ver));
+                 uuid->Data4[7], major, minor);
     print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
     print_client("0,\n");
     if (endpoints)
@@ -475,7 +477,7 @@
                      iface->name, iface->name);
     else
         print_client("RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
-                     prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name);
+                     prefix_client, iface->name, major, minor, iface->name);
     fprintf(client, "\n");
 }
 
diff --git a/mingw-w64-tools/widl/src/header.c b/mingw-w64-tools/widl/src/header.c
index 81a789a..775851c 100644
--- a/mingw-w64-tools/widl/src/header.c
+++ b/mingw-w64-tools/widl/src/header.c
@@ -40,8 +40,6 @@
 context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
 generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
 
-static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, bool define, const char *name, enum name_type name_type);
-
 static void write_apicontract( FILE *header, type_t *type );
 static void write_apicontract_guard_start(FILE *header, const expr_t *expr);
 static void write_apicontract_guard_end(FILE *header, const expr_t *expr);
@@ -66,25 +64,6 @@
     fprintf(f, "\n");
 }
 
-static char *format_parameterized_type_args(const type_t *type, const char *prefix, const char *suffix)
-{
-    typeref_list_t *params;
-    typeref_t *ref;
-    size_t len = 0, pos = 0;
-    char *buf = NULL;
-
-    params = type->details.parameterized.params;
-    if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
-    {
-        assert(ref->type->type_type != TYPE_POINTER);
-        pos += strappend(&buf, &len, pos, "%s%s%s", prefix, ref->type->name, suffix);
-        if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", ");
-    }
-
-    if (!buf) return xstrdup("");
-    return buf;
-}
-
 static void write_guid(FILE *f, const char *guid_prefix, const char *name, const struct uuid *uuid)
 {
   if (!uuid) return;
@@ -159,6 +138,26 @@
     return v->name;
 }
 
+static void write_type_definition_left( FILE *h, const decl_spec_t *ds, enum name_type name_type, bool write_callconv );
+static void write_type_definition( FILE *h, const decl_spec_t *ds, bool is_field, const char *name, enum name_type name_type )
+{
+    type_t *t = ds->type;
+
+    if (!h) return;
+    if (t) write_type_definition_left( h, ds, name_type, true );
+    if (name) fprintf( h, "%s%s", !t || needs_space_after( t ) ? " " : "", name );
+    if (t) write_type_right( h, t, is_field );
+}
+
+static void write_type_v( FILE *h, const decl_spec_t *ds, bool is_field, const char *name, enum name_type name_type )
+{
+    struct strbuf str = {0};
+
+    if (!h) return;
+    append_declspec( &str, ds, name_type, is_object_interface ? "STDMETHODCALLTYPE" : "", is_field, name );
+    fwrite( str.buf, 1, str.pos, h );
+}
+
 static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type)
 {
     unsigned nameless_struct_cnt = 0, nameless_struct_i = 0, nameless_union_cnt = 0, nameless_union_i = 0;
@@ -219,7 +218,8 @@
         default:
             ;
         }
-        write_type_v(h, &v->declspec, TRUE, v->is_defined, name, name_type);
+        if (v->is_defined) write_type_definition( h, &v->declspec, true, name, name_type );
+        else write_type_v( h, &v->declspec, true, name, name_type );
         fprintf(h, ";\n");
         if (contract) write_apicontract_guard_end(h, contract);
     }
@@ -250,125 +250,88 @@
   }
 }
 
-int needs_space_after(type_t *t)
-{
-  return (type_is_alias(t) ||
-          (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name)));
-}
-
-static int decl_needs_parens(const type_t *t)
-{
-    if (type_is_alias(t))
-        return FALSE;
-    if (is_array(t) && !type_array_is_decl_as_ptr(t))
-        return TRUE;
-    return is_func(t);
-}
-
 static void write_pointer_left(FILE *h, type_t *ref)
 {
-    if (needs_space_after(ref))
-        fprintf(h, " ");
-    if (decl_needs_parens(ref))
-        fprintf(h, "(");
-    if (type_get_type_detect_alias(ref) == TYPE_FUNCTION)
-    {
-        const char *callconv = get_attrp(ref->attrs, ATTR_CALLCONV);
-        if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE";
-        if (callconv) fprintf(h, "%s ", callconv);
-    }
-    fprintf(h, "*");
+    struct strbuf str = {0};
+    append_pointer_left( &str, ref, is_object_interface ? "STDMETHODCALLTYPE" : "" );
+    fwrite( str.buf, 1, str.pos, h );
 }
 
-void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv)
+static void write_record_type_definition( FILE *header, type_t *type, const char *specifier, enum name_type name_type )
 {
-  type_t *t = ds->type;
-  const char *decl_name, *name;
-  char *args;
+    const char *decl_name;
 
-  if (!h) return;
+    assert( type->defined );
+    type->written = TRUE;
 
-  decl_name = type_get_decl_name(t, name_type);
-  name = type_get_name(t, name_type);
+    if (!(decl_name = type_get_decl_name( type, name_type ))) decl_name = "";
+    fprintf( header, "%s %s%s{\n", specifier, decl_name, *decl_name ? " " : "" );
+    indentation++;
 
-  if (ds->func_specifier & FUNCTION_SPECIFIER_INLINE)
-    fprintf(h, "inline ");
+    switch (type_get_type_detect_alias( type ))
+    {
+    case TYPE_ENUM:
+        write_enums( header, type_enum_get_values( type ), is_global_namespace( type->namespace ) ? NULL : type->name );
+        break;
+    case TYPE_STRUCT:
+        write_fields( header, type_struct_get_fields( type ), name_type );
+        break;
+    case TYPE_ENCAPSULATED_UNION:
+        write_fields( header, type_encapsulated_union_get_fields( type ), name_type );
+        break;
+    case TYPE_UNION:
+        write_fields( header, type_union_get_cases( type ), name_type );
+        break;
+    default:
+        /* shouldn't be here */
+        assert( 0 );
+        break;
+    }
 
-  if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (type_is_alias(t) || !is_ptr(t)))
-    fprintf(h, "const ");
+    indent( header, -1 );
+    fprintf( header, "}" );
+}
 
-  if (type_is_alias(t)) fprintf(h, "%s", name);
-  else {
-    switch (type_get_type_detect_alias(t)) {
-      case TYPE_ENUM:
-        if (!define) fprintf(h, "enum %s", decl_name ? decl_name : "");
-        else if (!t->written) {
-          assert(t->defined);
-          if (decl_name) fprintf(h, "enum %s {\n", decl_name);
-          else fprintf(h, "enum {\n");
-          t->written = TRUE;
-          indentation++;
-          write_enums(h, type_enum_get_values(t), is_global_namespace(t->namespace) ? NULL : t->name);
-          indent(h, -1);
-          fprintf(h, "}");
-        }
-        else if (winrt_mode && name_type == NAME_DEFAULT && name) fprintf(h, "%s", name);
-        else fprintf(h, "enum %s", name ? name : "");
+static void write_type_definition_left( FILE *h, const decl_spec_t *decl_spec, enum name_type name_type, bool write_callconv )
+{
+    bool is_const = !!(decl_spec->qualifier & TYPE_QUALIFIER_CONST);
+    type_t *type = decl_spec->type;
+    const char *name;
+    struct strbuf str = {0};
+
+    if (!h) return;
+
+    if (decl_spec->func_specifier & FUNCTION_SPECIFIER_INLINE) fprintf( h, "inline " );
+    if (is_const && (type_is_alias( type ) || !is_ptr( type ))) fprintf( h, "const " );
+
+    if ((name = type_get_name( type, name_type, false ))) fprintf( h, "%s", name );
+    else switch (type_get_type_detect_alias( type ))
+    {
+    case TYPE_ENUM:
+    case TYPE_STRUCT:
+    case TYPE_ENCAPSULATED_UNION:
+    case TYPE_UNION:
+    {
+        const char *specifier = type_get_record_specifier( type );
+        if (!type->written) write_record_type_definition( h, type, specifier, name_type );
+        else if ((name = type_get_name( type, name_type, true )) && winrt_mode && name_type == NAME_DEFAULT) fprintf( h, "%s", name );
+        else fprintf( h, "%s %s", specifier, name ? name : "" );
         break;
-      case TYPE_STRUCT:
-      case TYPE_ENCAPSULATED_UNION:
-        if (!define) fprintf(h, "struct %s", decl_name ? decl_name : "");
-        else if (!t->written) {
-          assert(t->defined);
-          if (decl_name) fprintf(h, "struct %s {\n", decl_name);
-          else fprintf(h, "struct {\n");
-          t->written = TRUE;
-          indentation++;
-          if (type_get_type(t) != TYPE_STRUCT)
-            write_fields(h, type_encapsulated_union_get_fields(t), name_type);
-          else
-            write_fields(h, type_struct_get_fields(t), name_type);
-          indent(h, -1);
-          fprintf(h, "}");
-        }
-        else if (winrt_mode && name_type == NAME_DEFAULT && name) fprintf(h, "%s", name);
-        else fprintf(h, "struct %s", name ? name : "");
+    }
+
+    case TYPE_POINTER:
+        write_type_definition_left( h, type_pointer_get_ref( type ), name_type, false );
+        write_pointer_left( h, type_pointer_get_ref_type( type ) );
+        if (is_const) fprintf( h, "const " );
         break;
-      case TYPE_UNION:
-        if (!define) fprintf(h, "union %s", decl_name ? decl_name : "");
-        else if (!t->written) {
-          assert(t->defined);
-          if (decl_name) fprintf(h, "union %s {\n", decl_name);
-          else fprintf(h, "union {\n");
-          t->written = TRUE;
-          indentation++;
-          write_fields(h, type_union_get_cases(t), name_type);
-          indent(h, -1);
-          fprintf(h, "}");
-        }
-        else if (winrt_mode && name_type == NAME_DEFAULT && name) fprintf(h, "%s", name);
-        else fprintf(h, "union %s", name ? name : "");
+
+    case TYPE_ARRAY:
+        write_type_definition_left( h, type_array_get_element( type ), name_type, !type_array_is_decl_as_ptr( type ) );
+        if (type_array_is_decl_as_ptr( type )) write_pointer_left( h, type_array_get_element_type( type ) );
         break;
-      case TYPE_POINTER:
-      {
-        write_type_left(h, type_pointer_get_ref(t), name_type, define, FALSE);
-        write_pointer_left(h, type_pointer_get_ref_type(t));
-        if (ds->qualifier & TYPE_QUALIFIER_CONST) fprintf(h, "const ");
-        break;
-      }
-      case TYPE_ARRAY:
-        if (t->name && type_array_is_decl_as_ptr(t))
-          fprintf(h, "%s", t->name);
-        else
-        {
-          write_type_left(h, type_array_get_element(t), name_type, define, !type_array_is_decl_as_ptr(t));
-          if (type_array_is_decl_as_ptr(t))
-            write_pointer_left(h, type_array_get_element_type(t));
-        }
-        break;
-      case TYPE_FUNCTION:
-      {
-        write_type_left(h, type_function_get_ret(t), name_type, define, TRUE);
+
+    case TYPE_FUNCTION:
+        write_type_definition_left( h, type_function_get_ret( type ), name_type, true );
 
         /* A pointer to a function has to write the calling convention inside
          * the parentheses. There's no way to handle that here, so we have to
@@ -376,188 +339,59 @@
          * convention or not. */
         if (write_callconv)
         {
-            const char *callconv = get_attrp(t->attrs, ATTR_CALLCONV);
+            const char *callconv = get_attrp( type->attrs, ATTR_CALLCONV );
             if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE";
-            if (callconv) fprintf(h, " %s ", callconv);
+            if (callconv) fprintf( h, " %s ", callconv );
         }
         break;
-      }
-      case TYPE_BASIC:
-        if (type_basic_get_type(t) != TYPE_BASIC_INT32 &&
-            type_basic_get_type(t) != TYPE_BASIC_INT64 &&
-            type_basic_get_type(t) != TYPE_BASIC_LONG &&
-            type_basic_get_type(t) != TYPE_BASIC_HYPER)
-        {
-          if (type_basic_get_sign(t) < 0) fprintf(h, "signed ");
-          else if (type_basic_get_sign(t) > 0) fprintf(h, "unsigned ");
-        }
-        switch (type_basic_get_type(t))
-        {
-        case TYPE_BASIC_INT8: fprintf(h, "small"); break;
-        case TYPE_BASIC_INT16: fprintf(h, "short"); break;
-        case TYPE_BASIC_INT: fprintf(h, "int"); break;
-        case TYPE_BASIC_INT3264: fprintf(h, "__int3264"); break;
-        case TYPE_BASIC_BYTE: fprintf(h, "byte"); break;
-        case TYPE_BASIC_CHAR: fprintf(h, "char"); break;
-        case TYPE_BASIC_WCHAR: fprintf(h, "wchar_t"); break;
-        case TYPE_BASIC_FLOAT: fprintf(h, "float"); break;
-        case TYPE_BASIC_DOUBLE: fprintf(h, "double"); break;
-        case TYPE_BASIC_ERROR_STATUS_T: fprintf(h, "error_status_t"); break;
-        case TYPE_BASIC_HANDLE: fprintf(h, "handle_t"); break;
-        case TYPE_BASIC_INT32:
-          if (type_basic_get_sign(t) > 0)
-            fprintf(h, "UINT32");
-          else
-            fprintf(h, "INT32");
-          break;
-        case TYPE_BASIC_LONG:
-          if (type_basic_get_sign(t) > 0)
-            fprintf(h, "ULONG");
-          else
-            fprintf(h, "LONG");
-          break;
-        case TYPE_BASIC_INT64:
-          if (type_basic_get_sign(t) > 0)
-            fprintf(h, "UINT64");
-          else
-            fprintf(h, "INT64");
-          break;
-        case TYPE_BASIC_HYPER:
-          if (type_basic_get_sign(t) > 0)
-            fprintf(h, "MIDL_uhyper");
-          else
-            fprintf(h, "hyper");
-          break;
-        }
+
+    case TYPE_BASIC:
+        append_basic_type( &str, type );
+        fwrite( str.buf, 1, str.pos, h );
         break;
-      case TYPE_INTERFACE:
-      case TYPE_MODULE:
-      case TYPE_COCLASS:
-        fprintf(h, "%s", type_get_name(t, name_type));
+    case TYPE_BITFIELD:
+        type = type_bitfield_get_field( type );
+        if (!type_is_alias( type )) append_basic_type( &str, type );
+        else strappend( &str, "%s", type_get_name( type, name_type, false ) );
+        fwrite( str.buf, 1, str.pos, h );
         break;
-      case TYPE_RUNTIMECLASS:
-        fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t, TRUE), name_type));
-        break;
-      case TYPE_DELEGATE:
-        fprintf(h, "%s", type_get_name(type_delegate_get_iface(t), name_type));
-        break;
-      case TYPE_VOID:
-        fprintf(h, "void");
-        break;
-      case TYPE_BITFIELD:
-      {
-        const decl_spec_t ds = {.type = type_bitfield_get_field(t)};
-        write_type_left(h, &ds, name_type, define, TRUE);
-        break;
-      }
-      case TYPE_ALIAS:
+
+    case TYPE_INTERFACE:
+    case TYPE_MODULE:
+    case TYPE_COCLASS:
+    case TYPE_RUNTIMECLASS:
+    case TYPE_DELEGATE:
+    case TYPE_VOID:
+    case TYPE_ALIAS:
+    case TYPE_PARAMETERIZED_TYPE:
+    case TYPE_PARAMETER:
         /* handled elsewhere */
-        assert(0);
+        assert( 0 );
         break;
-      case TYPE_PARAMETERIZED_TYPE:
-      {
-        type_t *iface = type_parameterized_type_get_real_type(t);
-        if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface);
-        args = format_parameterized_type_args(t, "", "_logical");
-        fprintf(h, "%s<%s>", iface->name, args);
-        free(args);
-        break;
-      }
-      case TYPE_PARAMETER:
-        fprintf(h, "%s_abi", t->name);
-        break;
-      case TYPE_APICONTRACT:
+    case TYPE_APICONTRACT:
         /* shouldn't be here */
-        assert(0);
+        assert( 0 );
         break;
     }
-  }
 }
 
-void write_type_right(FILE *h, type_t *t, int is_field)
+void write_type_left( FILE *h, const decl_spec_t *ds, enum name_type name_type )
 {
-  if (!h) return;
-  if (type_is_alias(t)) return;
-
-  switch (type_get_type(t))
-  {
-  case TYPE_ARRAY:
-  {
-    type_t *elem = type_array_get_element_type(t);
-    if (type_array_is_decl_as_ptr(t))
-    {
-      if (decl_needs_parens(elem))
-        fprintf(h, ")");
-    }
-    else
-    {
-      if (is_conformant_array(t))
-        fprintf(h, "[%s]", is_field ? "1" : "");
-      else
-        fprintf(h, "[%u]", type_array_get_dim(t));
-    }
-    write_type_right(h, elem, FALSE);
-    break;
-  }
-  case TYPE_FUNCTION:
-  {
-    const var_list_t *args = type_function_get_args(t);
-    fputc('(', h);
-    if (args) write_args(h, args, NULL, 0, FALSE, NAME_DEFAULT);
-    else
-      fprintf(h, "void");
-    fputc(')', h);
-    write_type_right(h, type_function_get_rettype(t), FALSE);
-    break;
-  }
-  case TYPE_POINTER:
-  {
-    type_t *ref = type_pointer_get_ref_type(t);
-    if (decl_needs_parens(ref))
-      fprintf(h, ")");
-    write_type_right(h, ref, FALSE);
-    break;
-  }
-  case TYPE_BITFIELD:
-    fprintf(h, " : %u", type_bitfield_get_bits(t)->cval);
-    break;
-  case TYPE_VOID:
-  case TYPE_BASIC:
-  case TYPE_ENUM:
-  case TYPE_STRUCT:
-  case TYPE_ENCAPSULATED_UNION:
-  case TYPE_UNION:
-  case TYPE_ALIAS:
-  case TYPE_MODULE:
-  case TYPE_COCLASS:
-  case TYPE_INTERFACE:
-  case TYPE_RUNTIMECLASS:
-  case TYPE_DELEGATE:
-  case TYPE_PARAMETERIZED_TYPE:
-  case TYPE_PARAMETER:
-    break;
-  case TYPE_APICONTRACT:
-    /* not supposed to be here */
-    assert(0);
-    break;
-  }
-}
-
-static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, bool define, const char *name, enum name_type name_type)
-{
-    type_t *t = ds->type;
-
+    struct strbuf str = {0};
     if (!h) return;
-
-    if (t) write_type_left(h, ds, name_type, define, TRUE);
-
-    if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
-
-    if (t)
-        write_type_right(h, t, is_field);
+    append_type_left( &str, ds, name_type, is_object_interface ? "STDMETHODCALLTYPE" : "" );
+    fwrite( str.buf, 1, str.pos, h );
 }
 
-static void write_type_definition(FILE *f, type_t *t, bool define)
+void write_type_right( FILE *h, type_t *type, bool is_field )
+{
+    struct strbuf str = {0};
+    if (!h) return;
+    append_type_right( &str, type, is_object_interface ? "STDMETHODCALLTYPE" : "", is_field );
+    fwrite( str.buf, 1, str.pos, h );
+}
+
+static void write_type( FILE *f, type_t *t, bool define )
 {
     int in_namespace = t->namespace && !is_global_namespace(t->namespace);
     decl_spec_t ds = {.type = t};
@@ -577,14 +411,16 @@
         write_namespace_start(f, t->namespace);
     }
     indent(f, 0);
-    write_type_left(f, &ds, NAME_DEFAULT, define, TRUE);
+    if (define) write_type_definition_left( f, &ds, NAME_DEFAULT, true );
+    else write_type_left( f, &ds, NAME_DEFAULT );
     fprintf(f, ";\n");
     if(in_namespace) {
         t->written = false;
         write_namespace_end(f, t->namespace);
         fprintf(f, "extern \"C\" {\n");
         fprintf(f, "#else\n");
-        write_type_left(f, &ds, NAME_C, define, TRUE);
+        if (define) write_type_definition_left( f, &ds, NAME_C, true );
+        else write_type_left( f, &ds, NAME_C );
         fprintf(f, ";\n");
         if (winrt_mode) write_widl_using_macros(f, t);
         fprintf(f, "#endif\n\n");
@@ -596,12 +432,12 @@
 
 void write_type_decl(FILE *f, const decl_spec_t *t, const char *name)
 {
-    write_type_v(f, t, FALSE, false, name, NAME_DEFAULT);
+    write_type_v( f, t, false, name, NAME_DEFAULT );
 }
 
 void write_type_decl_left(FILE *f, const decl_spec_t *ds)
 {
-  write_type_left(f, ds, NAME_DEFAULT, false, TRUE);
+    write_type_left( f, ds, NAME_DEFAULT );
 }
 
 static int user_type_registered(const char *name)
@@ -825,13 +661,13 @@
 static void write_typedef(FILE *header, type_t *type, bool define)
 {
     type_t *t = type_alias_get_aliasee_type(type), *root = type_pointer_get_root_type(t);
-    if (winrt_mode && !define && type_get_type( t ) == TYPE_ENUM)
-        write_type_definition( header, t, TRUE );
+    if (winrt_mode && !define && type_get_type( t ) == TYPE_ENUM) write_type( header, t, true );
     if (winrt_mode && root->namespace && !is_global_namespace(root->namespace))
     {
         fprintf(header, "#ifndef __cplusplus\n");
         fprintf(header, "typedef ");
-        write_type_v(header, type_alias_get_aliasee(type), FALSE, define, type->c_name, NAME_C);
+        if (define) write_type_definition( header, type_alias_get_aliasee( type ), false, type->c_name, NAME_C );
+        else write_type_v( header, type_alias_get_aliasee( type ), false, type->c_name, NAME_C );
         fprintf(header, ";\n");
         if (type_get_type_detect_alias(t) != TYPE_ENUM)
         {
@@ -839,7 +675,7 @@
             if (t->namespace && !is_global_namespace(t->namespace)) write_namespace_start(header, t->namespace);
             indent(header, 0);
             fprintf(header, "typedef ");
-            write_type_v(header, type_alias_get_aliasee(type), FALSE, false, type->name, NAME_DEFAULT);
+            write_type_v( header, type_alias_get_aliasee( type ), false, type->name, NAME_DEFAULT );
             fprintf(header, ";\n");
             if (t->namespace && !is_global_namespace(t->namespace)) write_namespace_end(header, t->namespace);
         }
@@ -848,7 +684,8 @@
     else
     {
         fprintf(header, "typedef ");
-        write_type_v(header, type_alias_get_aliasee(type), FALSE, define, type->name, NAME_DEFAULT);
+        if (define) write_type_definition( header, type_alias_get_aliasee( type ), false, type->name, NAME_DEFAULT );
+        else write_type_v( header, type_alias_get_aliasee( type ), false, type->name, NAME_DEFAULT );
         fprintf(header, ";\n");
     }
 }
@@ -893,7 +730,8 @@
         fprintf(header, "extern ");
         break;
     }
-    write_type_v(header, &v->declspec, FALSE, v->is_defined, v->name, NAME_DEFAULT);
+    if (v->is_defined) write_type_definition( header, &v->declspec, false, v->name, NAME_DEFAULT );
+    else write_type_v( header, &v->declspec, false, v->name, NAME_DEFAULT );
     fprintf(header, ";\n\n");
   }
 }
@@ -1137,7 +975,7 @@
     /* In theory we should be writing the definition using write_type_v(..., arg->define),
      * but that causes redefinition in e.g. proxy files. In fact MIDL disallows
      * defining UDTs inside of an argument list. */
-    write_type_v(h, &arg->declspec, FALSE, false, arg->name, name_type);
+    write_type_v( h, &arg->declspec, false, arg->name, name_type );
     if (method == 2) {
         const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE);
         if (expr) {
@@ -1760,12 +1598,14 @@
 
 static void write_rpc_interface_start(FILE *header, const type_t *iface)
 {
-  unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
   const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
   expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
+  unsigned short major, minor;
+
+  get_version( iface->attrs, &major, &minor );
 
   fprintf(header, "/*****************************************************************************\n");
-  fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
+  fprintf(header, " * %s interface (v%d.%d)\n", iface->name, major, minor);
   fprintf(header, " */\n");
   if (contract) write_apicontract_guard_start(header, contract);
   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
@@ -1784,9 +1624,9 @@
   else
   {
       fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
-              prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
+              prefix_client, iface->name, major, minor);
       fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
-              prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
+              prefix_server, iface->name, major, minor);
   }
 }
 
@@ -1833,15 +1673,17 @@
   fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
 }
 
-static void write_apicontract(FILE *header, type_t *apicontract)
+static void write_apicontract( FILE *header, type_t *apicontract )
 {
+    const version_t *version;
     char *name;
     if (apicontract->written) return;
     name = format_apicontract_macro( apicontract );
-    fprintf(header, "#if !defined(%s_VERSION)\n", name);
-    fprintf(header, "#define %s_VERSION %#x\n", name, get_attrv(apicontract->attrs, ATTR_CONTRACTVERSION));
-    fprintf(header, "#endif // defined(%s_VERSION)\n\n", name);
-    free(name);
+    version = get_attrp( apicontract->attrs, ATTR_CONTRACTVERSION );
+    fprintf( header, "#if !defined(%s_VERSION)\n", name );
+    fprintf( header, "#define %s_VERSION %#x\n", name, (version->major << 16 | version->minor) );
+    fprintf( header, "#endif // defined(%s_VERSION)\n\n", name );
+    free( name );
     apicontract->written = true;
 }
 
@@ -2034,8 +1876,8 @@
           write_apicontract(header, stmt->u.type);
         else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS)
           write_runtimeclass(header, stmt->u.type);
-        else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE)
-          write_type_definition(header, stmt->u.type, stmt->is_defined);
+        else if (type_get_type( stmt->u.type ) != TYPE_PARAMETERIZED_TYPE)
+            write_type( header, stmt->u.type, stmt->is_defined );
         else
         {
           is_object_interface++;
diff --git a/mingw-w64-tools/widl/src/header.h b/mingw-w64-tools/widl/src/header.h
index 4506689..ddae3a4 100644
--- a/mingw-w64-tools/widl/src/header.h
+++ b/mingw-w64-tools/widl/src/header.h
@@ -24,13 +24,12 @@
 #include "typetree.h"
 
 extern const char* get_name(const var_t *v);
-extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv);
-extern void write_type_right(FILE *h, type_t *t, int is_field);
+extern void write_type_left( FILE *h, const decl_spec_t *ds, enum name_type name_type );
+extern void write_type_right( FILE *h, type_t *t, bool is_field );
 extern void write_type_decl(FILE *f, const decl_spec_t *t, const char *name);
 extern void write_type_decl_left(FILE *f, const decl_spec_t *ds);
 extern unsigned int get_context_handle_offset( const type_t *type );
 extern unsigned int get_generic_handle_offset( const type_t *type );
-extern int needs_space_after(type_t *t);
 extern int is_object(const type_t *iface);
 extern int is_local(const attr_list_t *list);
 extern int count_methods(const type_t *iface);
diff --git a/mingw-w64-tools/widl/src/metadata.c b/mingw-w64-tools/widl/src/metadata.c
index bd953c5..ec2d213 100644
--- a/mingw-w64-tools/widl/src/metadata.c
+++ b/mingw-w64-tools/widl/src/metadata.c
@@ -479,14 +479,16 @@
     buf->offset += size;
 }
 
-static void serialize_byte( BYTE value )
+static void serialize_byte( UINT value )
 {
-    add_bytes( &tables_disk, (const BYTE *)&value, sizeof(value) );
+    assert( !(value >> 24) );
+    add_bytes( &tables_disk, (const BYTE *)&value, sizeof(BYTE) );
 }
 
-static void serialize_ushort( USHORT value )
+static void serialize_ushort( UINT value )
 {
-    add_bytes( &tables_disk, (const BYTE *)&value, sizeof(value) );
+    assert( !(value >> 16) );
+    add_bytes( &tables_disk, (const BYTE *)&value, sizeof(USHORT) );
 }
 
 static void serialize_uint( UINT value )
@@ -623,11 +625,11 @@
 
 struct module_row
 {
-    USHORT generation;
-    UINT   name;
-    UINT   mvid;
-    UINT   encid;
-    UINT   encbaseid;
+    UINT generation;
+    UINT name;
+    UINT mvid;
+    UINT encid;
+    UINT encbaseid;
 };
 
 static UINT add_module_row( UINT name, UINT mvid )
@@ -713,9 +715,9 @@
 
 struct field_row
 {
-    USHORT flags;
-    UINT   name;
-    UINT   signature;
+    UINT flags;
+    UINT name;
+    UINT signature;
 };
 
 static UINT add_field_row( UINT flags, UINT name, UINT signature )
@@ -740,12 +742,12 @@
 
 struct methoddef_row
 {
-    UINT   rva;
-    USHORT implflags;
-    USHORT flags;
-    UINT   name;
-    UINT   signature;
-    UINT   paramlist;
+    UINT rva;
+    UINT implflags;
+    UINT flags;
+    UINT name;
+    UINT signature;
+    UINT paramlist;
 };
 
 static UINT add_methoddef_row( UINT implflags, UINT flags, UINT name, UINT signature, UINT paramlist )
@@ -775,9 +777,9 @@
 
 struct param_row
 {
-    USHORT flags;
-    USHORT sequence;
-    UINT   name;
+    UINT flags;
+    UINT sequence;
+    UINT name;
 };
 
 static UINT add_param_row( USHORT flags, USHORT sequence, UINT name )
@@ -868,8 +870,8 @@
 
 struct constant_row
 {
-    BYTE type;
-    BYTE padding;
+    UINT type;
+    UINT padding;
     UINT parent;
     UINT value;
 };
@@ -947,15 +949,15 @@
 
 struct assembly_row
 {
-    UINT   hashalgid;
-    USHORT majorversion;
-    USHORT minorversion;
-    USHORT buildnumber;
-    USHORT revisionnumber;
-    UINT   flags;
-    UINT   publickey;
-    UINT   name;
-    UINT   culture;
+    UINT hashalgid;
+    UINT majorversion;
+    UINT minorversion;
+    UINT buildnumber;
+    UINT revisionnumber;
+    UINT flags;
+    UINT publickey;
+    UINT name;
+    UINT culture;
 };
 
 static UINT add_assembly_row( UINT name )
@@ -981,15 +983,15 @@
 
 struct assemblyref_row
 {
-    USHORT majorversion;
-    USHORT minorversion;
-    USHORT buildnumber;
-    USHORT revisionnumber;
-    UINT   flags;
-    UINT   publickey;
-    UINT   name;
-    UINT   culture;
-    UINT   hashvalue;
+    UINT majorversion;
+    UINT minorversion;
+    UINT buildnumber;
+    UINT revisionnumber;
+    UINT flags;
+    UINT publickey;
+    UINT name;
+    UINT culture;
+    UINT hashvalue;
 };
 
 static UINT add_assemblyref_row( UINT flags, UINT publickey, UINT name )
@@ -1045,9 +1047,9 @@
 
 struct property_row
 {
-    USHORT flags;
-    UINT   name;
-    UINT   type;
+    UINT flags;
+    UINT name;
+    UINT type;
 };
 
 static UINT add_property_row( USHORT flags, UINT name, UINT type )
@@ -1097,9 +1099,9 @@
 
 struct event_row
 {
-    USHORT flags;
-    UINT   name;
-    UINT   type;
+    UINT flags;
+    UINT name;
+    UINT type;
 };
 
 static UINT add_event_row( USHORT flags, UINT name, UINT type )
@@ -1124,9 +1126,9 @@
 
 struct methodsemantics_row
 {
-    USHORT semantics;
-    UINT   method;
-    UINT   association;
+    UINT semantics;
+    UINT method;
+    UINT association;
 };
 
 static UINT add_methodsemantics_row( USHORT flags, UINT name, UINT type )
@@ -1644,6 +1646,15 @@
     return len;
 }
 
+static BOOL is_retval( const var_t *arg )
+{
+    const type_t *type = arg->declspec.type;
+
+    /* array return values are encoded as out parameters even if the retval attribute is present */
+    if (!is_attr( arg->attrs, ATTR_RETVAL ) || type_get_type( type ) == TYPE_ARRAY) return FALSE;
+    return TRUE;
+}
+
 static UINT make_method_sig( const var_t *method, BYTE *buf, BOOL is_static )
 {
     const var_t *arg;
@@ -1661,7 +1672,7 @@
     {
         const type_t *type;
 
-        if (!is_attr( arg->attrs, ATTR_RETVAL )) continue;
+        if (!is_retval( arg )) continue;
         type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */
         len = make_type_sig( type, buf + 2 ) + 2;
     }
@@ -1669,7 +1680,7 @@
     /* add remaining parameters */
     LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
     {
-        if (is_attr( arg->attrs, ATTR_RETVAL ) ) continue;
+        if (is_size_param( arg, arg_list ) || is_retval( arg ) ) continue;
         len += make_type_sig( arg->declspec.type, buf + len );
         buf[1]++;
     }
@@ -1690,7 +1701,7 @@
     {
         const type_t *type;
 
-        if (!is_attr( arg->attrs, ATTR_RETVAL )) continue;
+        if (!is_retval( arg )) continue;
         type = type_pointer_get_ref_type( arg->declspec.type ); /* retval must be a pointer */
         len = make_type_sig( type, buf + 2 ) + 2;
     }
@@ -1709,7 +1720,7 @@
 
     if (method) LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
     {
-        if (is_attr( arg->attrs, ATTR_RETVAL )) continue;
+        if (is_retval( arg )) continue;
         len += make_type_sig( arg->declspec.type, buf + len );
         buf[1]++;
     }
@@ -1756,12 +1767,12 @@
     return len;
 }
 
-static UINT make_contract_value( const type_t *type, BYTE *buf )
+static UINT make_contract_value( const attr_t *attr, BYTE *buf )
 {
-    const expr_t *attr = get_attrp( type->attrs, ATTR_CONTRACT );
-    const type_t *contract = attr->u.var->declspec.type;
+    const expr_t *expr = attr->u.pval;
+    const type_t *contract = expr->u.var->declspec.type;
     char *name = format_namespace( contract->namespace, "", ".", contract->name, NULL );
-    UINT version = attr->ref->u.integer.value, len = strlen( name );
+    UINT version = expr->ref->u.integer.value, len = strlen( name );
 
     buf[0] = 1;
     buf[1] = 0;
@@ -1777,24 +1788,38 @@
     return len;
 }
 
-static UINT make_version_value( const type_t *type, BYTE *buf )
+static UINT make_version_value( const attr_t *attr, BYTE *buf )
 {
-    UINT version = get_attrv( type->attrs, ATTR_VERSION );
+    const version_t *version;
+    UINT value;
+
+    if (attr && (version = attr->u.pval)) value = (version->major << 16) | version->minor;
+    else value = 1;
 
     buf[0] = 1;
     buf[1] = 0;
-    buf[2] = is_attr( type->attrs, ATTR_VERSION ) ? 0 : 1;
-    buf[3] = 0;
-    memcpy( buf + 4, &version, sizeof(version) );
+    memcpy( buf + 2, &value, sizeof(value) );
+    buf[6] = buf[7] = 0;
     return 8;
 }
 
-static void add_contract_attr_step1( type_t *type )
+static attr_t *get_attr( const attr_list_t *list, enum attr_type attr_type )
+{
+    attr_t *attr;
+    if (list) LIST_FOR_EACH_ENTRY( attr, list, attr_t, entry )
+    {
+        if (attr->type == attr_type ) return attr;
+    }
+    return NULL;
+}
+
+static void add_contract_attr_step1( const type_t *type )
 {
     UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
     BYTE sig[32];
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_CONTRACT )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_CONTRACT ))) return;
 
     add_assemblyref_row( 0x200, 0, add_string("windowscontracts") );
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
@@ -1807,72 +1832,77 @@
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
     sig_size = make_member_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
-    type->md.member[MD_ATTR_CONTRACT] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
 }
 
-static void add_contract_attr_step2( type_t *type )
+static void add_contract_attr_step2( const type_t *type )
 {
     UINT parent, attr_type, value_size;
     BYTE value[MAX_NAME + sizeof(UINT) + 5];
+    const attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_CONTRACT )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_CONTRACT ))) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_CONTRACT] );
-    value_size = make_contract_value( type, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_contract_value( attr, value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 }
 
-static void add_version_attr_step1( type_t *type )
+static void add_version_attr_step1( const type_t *type )
 {
     static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 };
     UINT assemblyref, scope, typeref, class;
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_VERSION ) && is_attr( type->attrs, ATTR_CONTRACT )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_VERSION )) && is_attr( type->attrs, ATTR_CONTRACT )) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
 
     typeref = add_typeref_row( scope, add_string("VersionAttribute"), add_string("Windows.Foundation.Metadata") );
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_VERSION] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
 }
 
-static void add_version_attr_step2( type_t *type )
+static void add_version_attr_step2( const type_t *type )
 {
     UINT parent, attr_type, value_size;
     BYTE value[8];
+    const attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_VERSION ) && is_attr( type->attrs, ATTR_CONTRACT )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_VERSION )) && is_attr( type->attrs, ATTR_CONTRACT )) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_VERSION] );
-    value_size = make_version_value( type, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_version_value( attr, value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 }
 
-static void add_flags_attr_step1( type_t *type )
+static void add_flags_attr_step1( const type_t *type )
 {
     static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
     UINT scope, typeref, class;
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_FLAGS )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_FLAGS ))) return;
 
     scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
     typeref = add_typeref_row( scope, add_string("FlagsAttribute"), add_string("System") );
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_FLAGS] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
 }
 
-static void add_flags_attr_step2( type_t *type )
+static void add_flags_attr_step2( const type_t *type )
 {
     static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
     UINT parent, attr_type;
+    const attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_FLAGS )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_FLAGS ))) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_FLAGS] );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
     add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
 }
 
@@ -1969,42 +1999,46 @@
     add_contract_attr_step2( type );
 }
 
-static void add_uuid_attr_step1( type_t *type )
+static void add_uuid_attr_step1( const type_t *type )
 {
     static const BYTE sig[] =
         { SIG_TYPE_HASTHIS, 11, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_U2, ELEMENT_TYPE_U2,
           ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1,
           ELEMENT_TYPE_U1, ELEMENT_TYPE_U1 };
     UINT assemblyref, scope, typeref, class;
+    attr_t *attr;
+
+    if (!(attr = get_attr( type->attrs, ATTR_UUID ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
     typeref = add_typeref_row( scope, add_string("GuidAttribute"), add_string("Windows.Foundation.Metadata") );
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_UUID] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
 }
 
-static void add_uuid_attr_step2( type_t *type )
+static void add_uuid_attr_step2( const type_t *type )
 {
-    static const BYTE default_uuid[] =
-        { 0xe7, 0x1f, 0xb5, 0x67, 0x6e, 0x38, 0x31, 0x5a, 0x8a, 0x1c, 0x89, 0x83, 0xc9, 0x49, 0x5c, 0x33 };
-    const struct uuid *uuid = get_attrp( type->attrs, ATTR_UUID );
+    const struct uuid *uuid;
     BYTE value[sizeof(*uuid) + 4] = { 0x01 };
     UINT parent, attr_type;
+    const attr_t *attr;
 
-    if (uuid) memcpy( value + 2, uuid, sizeof(*uuid) );
-    else memcpy( value + 2, default_uuid, sizeof(default_uuid) );
+    if (!(attr = get_attr( type->attrs, ATTR_UUID ))) return;
+
+    uuid = attr->u.pval;
+    memcpy( value + 2, uuid, sizeof(*uuid) );
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_UUID] );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
     add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
 }
 
-static UINT make_exclusiveto_value( const type_t *type, BYTE *buf )
+static UINT make_exclusiveto_value( const attr_t *attr, BYTE *buf )
 {
-    const type_t *attr = get_attrp( type->attrs, ATTR_EXCLUSIVETO );
-    char *name = format_namespace( attr->namespace, "", ".", attr->name, NULL );
+    const type_t *type = attr->u.pval;
+    char *name = format_namespace( type->namespace, "", ".", type->name, NULL );
     UINT len = strlen( name );
 
     buf[0] = 1;
@@ -2019,12 +2053,13 @@
     return len;
 }
 
-static void add_exclusiveto_attr_step1( type_t *type )
+static void add_exclusiveto_attr_step1( const type_t *type )
 {
     UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
     BYTE sig[32];
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_EXCLUSIVETO ))) return;
 
     scope = resolution_scope( TABLE_ASSEMBLYREF, MSCORLIB_ROW );
     typeref_type = add_typeref_row( scope, add_string("Type"), add_string("System") );
@@ -2035,30 +2070,31 @@
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
     sig_size = make_member_sig2( ELEMENT_TYPE_CLASS, typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
-    type->md.member[MD_ATTR_EXCLUSIVETO] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
 }
 
-static void add_exclusiveto_attr_step2( type_t *type )
+static void add_exclusiveto_attr_step2( const type_t *type )
 {
     UINT parent, attr_type, value_size;
     BYTE value[MAX_NAME + 5];
+    const attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_EXCLUSIVETO )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_EXCLUSIVETO ))) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_EXCLUSIVETO] );
-    value_size = make_exclusiveto_value( type, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_exclusiveto_value( attr, value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 }
 
-static UINT make_overload_value( const var_t *method, BYTE *buf )
+static UINT make_overload_value( const char *name, BYTE *buf )
 {
-    UINT len = strlen( method->name );
+    UINT len = strlen( name );
 
     buf[0] = 1;
     buf[1] = 0;
     buf[2] = len;
-    memcpy( buf + 3, method->name, len );
+    memcpy( buf + 3, name, len );
     len += 3;
     buf[len++] = 0;
     buf[len++] = 0;
@@ -2070,16 +2106,16 @@
 {
     static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING };
     UINT assemblyref, scope, typeref, class;
-    type_t *type = method->declspec.type;
+    attr_t *attr;
 
-    if (!is_attr( method->attrs, ATTR_OVERLOAD )) return;
+    if (!(attr = get_attr( method->attrs, ATTR_OVERLOAD ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
     typeref = add_typeref_row( scope, add_string("OverloadAttribute"), add_string("Windows.Foundation.Metadata") );
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_OVERLOAD] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
 }
 
 static void add_overload_attr_step2( const var_t *method )
@@ -2087,12 +2123,13 @@
     const type_t *type = method->declspec.type;
     UINT parent, attr_type, value_size;
     BYTE value[MAX_NAME + 5];
+    const attr_t *attr;
 
-    if (!is_attr( method->attrs, ATTR_OVERLOAD )) return;
+    if (!(attr = get_attr( method->attrs, ATTR_OVERLOAD ))) return;
 
     parent = has_customattribute( TABLE_METHODDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_OVERLOAD] );
-    value_size = make_overload_value( method, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_overload_value( method->name, value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 }
 
@@ -2100,16 +2137,16 @@
 {
     static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
     UINT assemblyref, scope, typeref, class;
-    type_t *type = method->declspec.type;
+    attr_t *attr;
 
-    if (!is_attr( method->attrs, ATTR_DEFAULT_OVERLOAD ) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
+    if (!(attr = get_attr( method->attrs, ATTR_DEFAULT_OVERLOAD )) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
     typeref = add_typeref_row( scope, add_string("DefaultOverloadAttribute"), add_string("Windows.Foundation.Metadata") );
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_DEFAULT_OVERLOAD] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
 }
 
 static void add_default_overload_attr_step2( const var_t *method )
@@ -2117,23 +2154,24 @@
     static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
     const type_t *type = method->declspec.type;
     UINT parent, attr_type;
+    const attr_t *attr;
 
-    if (!is_attr( method->attrs, ATTR_DEFAULT_OVERLOAD ) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
+    if (!(attr = get_attr( method->attrs, ATTR_DEFAULT_OVERLOAD )) || !is_attr( method->attrs, ATTR_OVERLOAD )) return;
 
     parent = has_customattribute( TABLE_METHODDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_DEFAULT_OVERLOAD] );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
     add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
 }
 
-static UINT make_deprecated_value( const var_t *method, BYTE **ret_buf )
+static UINT make_deprecated_value( const attr_t *attr, BYTE **ret_buf )
 {
     static const BYTE zero[] = { 0x00, 0x00, 0x00, 0x00 }, one[] = { 0x01, 0x00, 0x00, 0x00 };
-    const expr_t *attr = get_attrp( method->attrs, ATTR_DEPRECATED );
-    const type_t *type = attr->ext2->u.var->declspec.type;
-    const char *text = attr->ref->u.sval;
-    const char *kind = attr->u.ext->u.sval;
+    const expr_t *expr = attr->u.pval;
+    const type_t *type = expr->ext2->u.var->declspec.type;
+    const char *text = expr->ref->u.sval;
+    const char *kind = expr->u.ext->u.sval;
     BYTE encoded[4];
-    UINT len, len_text = strlen( text ), len_encoded = encode_int( len_text, encoded );
+    UINT len, version, len_text = strlen( text ), len_encoded = encode_int( len_text, encoded );
     BYTE *buf = xmalloc( 2 + len_encoded + len_text + 6 + MAX_NAME + 5 );
     char *contract;
 
@@ -2146,11 +2184,11 @@
     if (!strcmp( kind, "remove" )) memcpy( buf + len, one, sizeof(one) );
     else memcpy( buf + len, zero, sizeof(zero) );
     len += 4;
-    buf[len++] = 0;
-    buf[len++] = 0;
 
-    buf[len++] = 1;
-    buf[len++] = 0;
+    version = expr->ext2->ref->u.integer.value;
+    memcpy( buf + len, &version, sizeof(version) );
+    len += sizeof(version);
+
     contract = format_namespace( type->namespace, "", ".", type->name, NULL );
     len_text = strlen( contract );
     buf[len++] = len_text;
@@ -2167,10 +2205,10 @@
 static void add_deprecated_attr_step1( const var_t *method )
 {
     UINT assemblyref, scope, typeref_type, typeref, class, sig_size;
-    type_t *type = method->declspec.type;
     BYTE sig[32];
+    attr_t *attr;
 
-    if (!is_attr( method->attrs, ATTR_DEPRECATED )) return;
+    if (!(attr = get_attr( method->attrs, ATTR_DEPRECATED ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
@@ -2179,7 +2217,7 @@
 
     sig_size = make_deprecated_sig( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_DEPRECATED] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
 }
 
 static void add_deprecated_attr_step2( const var_t *method )
@@ -2187,12 +2225,13 @@
     const type_t *type = method->declspec.type;
     UINT parent, attr_type, value_size;
     BYTE *value;
+    const attr_t *attr;
 
-    if (!is_attr( method->attrs, ATTR_DEPRECATED )) return;
+    if (!(attr = get_attr( method->attrs, ATTR_DEPRECATED ))) return;
 
     parent = has_customattribute( TABLE_METHODDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_DEPRECATED] );
-    value_size = make_deprecated_value( method, &value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_deprecated_value( attr, &value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
     free( value );
 }
@@ -2207,6 +2246,7 @@
     {
         type_t *type = arg->declspec.type;
 
+        if (is_size_param( arg, arg_list )) continue;
         if (type_get_type( type ) == TYPE_POINTER) type = type_pointer_get_ref_type( type );
         if (type->name && !strcmp( type->name, "EventRegistrationToken" ))
         {
@@ -2271,7 +2311,7 @@
 
     LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
     {
-        if (is_attr( arg->attrs, ATTR_RETVAL ))
+        if (is_retval( arg ))
         {
             first = add_param_row( 0, 0, add_string(arg->name) );
             break;
@@ -2280,7 +2320,7 @@
 
     LIST_FOR_EACH_ENTRY( arg, arg_list, var_t, entry )
     {
-        if (is_attr( arg->attrs, ATTR_RETVAL )) continue;
+        if (is_size_param( arg, arg_list) || is_retval( arg )) continue;
         row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
         if (!first) first = row;
     }
@@ -2578,66 +2618,62 @@
     add_exclusiveto_attr_step2( type );
 }
 
-static UINT make_contractversion_value( const type_t *type, BYTE *buf )
-{
-    UINT version = get_attrv( type->attrs, ATTR_CONTRACTVERSION ), len = 2 + sizeof(version);
-
-    buf[0] = 1;
-    buf[1] = 0;
-    memcpy( buf + 2, &version, sizeof(version) );
-    buf[len++] = 0;
-    buf[len++] = 0;
-    return len;
-}
-
-static void add_contractversion_attr_step1( type_t *type )
+static void add_contractversion_attr_step1( const type_t *type )
 {
     static const BYTE sig[] = { SIG_TYPE_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4 };
     UINT assemblyref, scope, typeref, class;
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_CONTRACTVERSION )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_CONTRACTVERSION ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
     typeref = add_typeref_row( scope, add_string("ContractVersionAttribute"), add_string("Windows.Foundation.Metadata") );
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_CONTRACTVERSION] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
 }
 
-static void add_contractversion_attr_step2( type_t *type )
+static void add_contractversion_attr_step2( const type_t *type )
 {
     UINT parent, attr_type, value_size;
     BYTE value[8];
+    const attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_CONTRACTVERSION )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_CONTRACTVERSION ))) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_CONTRACTVERSION] );
-    value_size = make_contractversion_value( type, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_version_value( attr, value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 }
 
-static void add_apicontract_attr_step1( type_t *type )
+static void add_apicontract_attr_step1( const type_t *type )
 {
     static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
     UINT assemblyref, scope, typeref, class;
+    attr_t *attr;
+
+    if (!(attr = get_attr( type->attrs, ATTR_APICONTRACT ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
     typeref = add_typeref_row( scope, add_string("ApiContractAttribute"), add_string("Windows.Foundation.Metadata") );
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
-    type->md.member[MD_ATTR_APICONTRACT] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sizeof(sig)) );
 }
 
-static void add_apicontract_attr_step2( type_t *type )
+static void add_apicontract_attr_step2( const type_t *type )
 {
     static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
     UINT parent, attr_type;
+    const attr_t *attr;
+
+    if (!(attr = get_attr( type->attrs, ATTR_APICONTRACT ))) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_APICONTRACT] );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
     add_customattribute_row( parent, attr_type, add_blob(value, sizeof(value)) );
 }
 
@@ -2678,7 +2714,7 @@
     type->md.ref = add_typeref_row( resolution_scope(TABLE_MODULE, MODULE_ROW), name, namespace );
 }
 
-static void add_default_attr( const type_t *type, UINT interfaceimpl_ref )
+static void add_default_attr( UINT interfaceimpl_ref )
 {
     static const BYTE sig[] = { SIG_TYPE_HASTHIS, 0, ELEMENT_TYPE_VOID };
     static const BYTE value[] = { 0x01, 0x00, 0x00, 0x00 };
@@ -2718,10 +2754,11 @@
 {
     UINT parent, attr_type, value_size;
     BYTE value[MAX_NAME + sizeof(UINT) + 5];
+    const attr_t *attr = get_attr( iface->attrs, ATTR_CONTRACT );
 
     parent = has_customattribute( TABLE_METHODDEF, method->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, iface->md.member[MD_ATTR_CONTRACT] );
-    value_size = make_contract_value( class, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_contract_value( get_attr(class->attrs, ATTR_CONTRACT), value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 
     if (method->md.class_property)
@@ -2766,12 +2803,13 @@
     return len_iface + len_contract + 10;
 }
 
-static void add_static_attr_step1( type_t *type )
+static void add_static_attr_step1( const type_t *type )
 {
     UINT assemblyref, scope, typeref, typeref_type, class, sig_size;
     BYTE sig[32];
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_STATIC )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_STATIC ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
@@ -2782,10 +2820,10 @@
 
     class = memberref_parent( TABLE_TYPEREF, typeref );
     sig_size = make_member_sig3( typedef_or_ref(TABLE_TYPEREF, typeref_type), sig );
-    type->md.member[MD_ATTR_STATIC] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
 }
 
-static void add_static_attr_step2( type_t *type )
+static void add_static_attr_step2( const type_t *type )
 {
     const attr_t *attr;
 
@@ -2797,7 +2835,7 @@
         if (attr->type != ATTR_STATIC) continue;
 
         parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-        attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_STATIC] );
+        attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
         value_size = make_static_value( attr->u.pval, value );
         add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
     }
@@ -2855,7 +2893,7 @@
     return len_iface + sizeof(version) + len_contract + len_extra;
 }
 
-static void add_activatable_attr_step1( type_t *type )
+static void add_activatable_attr_step1( const type_t *type )
 {
     static const BYTE sig_default[] = { SIG_TYPE_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U4, ELEMENT_TYPE_STRING };
     attr_t *attr;
@@ -2889,7 +2927,7 @@
     }
 }
 
-static void add_activatable_attr_step2( type_t *type )
+static void add_activatable_attr_step2( const type_t *type )
 {
     const attr_t *attr;
 
@@ -2907,9 +2945,9 @@
     }
 }
 
-static UINT make_threading_value( const type_t *type, BYTE *buf )
+static UINT make_threading_value( const attr_t *attr, BYTE *buf )
 {
-    UINT value, model = get_attrv( type->attrs, ATTR_THREADING );
+    UINT value, model = attr->u.ival;
 
     switch (model)
     {
@@ -2934,12 +2972,13 @@
     return 8;
 }
 
-static void add_threading_attr_step1( type_t *type )
+static void add_threading_attr_step1( const type_t *type )
 {
     UINT assemblyref, scope, typeref, typeref_attr, class, sig_size;
     BYTE sig[32];
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_THREADING )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_THREADING ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
@@ -2950,25 +2989,26 @@
 
     class = memberref_parent( TABLE_TYPEREF, typeref_attr );
     sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig );
-    type->md.member[MD_ATTR_THREADING] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
 }
 
-static void add_threading_attr_step2( type_t *type )
+static void add_threading_attr_step2( const type_t *type )
 {
     UINT parent, attr_type, value_size;
     BYTE value[8];
+    const attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_THREADING )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_THREADING ))) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_THREADING] );
-    value_size = make_threading_value( type, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_threading_value( attr, value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 }
 
-static UINT make_marshalingbehavior_value( const type_t *type, BYTE *buf )
+static UINT make_marshalingbehavior_value( const attr_t *attr, BYTE *buf )
 {
-    UINT marshaling = get_attrv( type->attrs, ATTR_MARSHALING_BEHAVIOR );
+    UINT marshaling = attr->u.ival;
 
     buf[0] = 1;
     buf[1] = 0;
@@ -2977,12 +3017,13 @@
     return 8;
 }
 
-static void add_marshalingbehavior_attr_step1( type_t *type )
+static void add_marshalingbehavior_attr_step1( const type_t *type )
 {
     UINT assemblyref, scope, typeref, typeref_attr, class, sig_size;
     BYTE sig[32];
+    attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR ))) return;
 
     assemblyref = add_assemblyref_row( 0x200, 0, add_string("Windows.Foundation") );
     scope = resolution_scope( TABLE_ASSEMBLYREF, assemblyref );
@@ -2993,19 +3034,20 @@
 
     class = memberref_parent( TABLE_TYPEREF, typeref_attr );
     sig_size = make_member_sig2( ELEMENT_TYPE_VALUETYPE, typedef_or_ref(TABLE_TYPEREF, typeref), sig );
-    type->md.member[MD_ATTR_MARSHALINGBEHAVIOR] = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
+    attr->md_member = add_memberref_row( class, add_string(".ctor"), add_blob(sig, sig_size) );
 }
 
-static void add_marshalingbehavior_attr_step2( type_t *type )
+static void add_marshalingbehavior_attr_step2( const type_t *type )
 {
     UINT parent, attr_type, value_size;
     BYTE value[8];
+    const attr_t *attr;
 
-    if (!is_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR )) return;
+    if (!(attr = get_attr( type->attrs, ATTR_MARSHALING_BEHAVIOR ))) return;
 
     parent = has_customattribute( TABLE_TYPEDEF, type->md.def );
-    attr_type = customattribute_type( TABLE_MEMBERREF, type->md.member[MD_ATTR_MARSHALINGBEHAVIOR] );
-    value_size = make_marshalingbehavior_value( type, value );
+    attr_type = customattribute_type( TABLE_MEMBERREF, attr->md_member );
+    value_size = make_marshalingbehavior_value( attr, value );
     add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
 }
 
@@ -3048,7 +3090,7 @@
     return len_iface + sizeof(access_type) + sizeof(contract_version) + len_contract + 6;
 }
 
-static void add_composable_attr_step1( type_t *type )
+static void add_composable_attr_step1( const type_t *type )
 {
     attr_t *attr;
 
@@ -3073,7 +3115,7 @@
     }
 }
 
-static void add_composable_attr_step2( type_t *type )
+static void add_composable_attr_step2( const type_t *type )
 {
     const attr_t *attr;
 
@@ -3102,7 +3144,7 @@
         UINT interfaceimpl_ref = add_interfaceimpl_row( class->md.def, interface );
         const statement_t *stmt;
 
-        if (is_attr( iface->attrs, ATTR_DEFAULT )) add_default_attr( class, interfaceimpl_ref );
+        if (is_attr( iface->attrs, ATTR_DEFAULT )) add_default_attr( interfaceimpl_ref );
 
         /* add properties in reverse order like midlrt */
         STATEMENTS_FOR_EACH_FUNC_REV( stmt, type_iface_get_stmts(iface->type) )
@@ -3153,7 +3195,7 @@
 static void add_activation_interfaces( const type_t *class )
 {
     UINT flags = METHOD_ATTR_PUBLIC | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME;
-    const attr_t *attr;
+    const attr_t *attr, *contract_attr = get_attr( class->attrs, ATTR_CONTRACT );
 
     if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry )
     {
@@ -3177,7 +3219,7 @@
 
             LIST_FOR_EACH_ENTRY( arg, type_function_get_args(method->declspec.type), var_t, entry )
             {
-                if (is_attr( arg->attrs, ATTR_RETVAL )) continue;
+                if (is_retval( arg )) continue;
                 row = add_param_row( get_param_attrs(arg), seq++, add_string(arg->name) );
                 if (!paramlist) paramlist = row;
             }
@@ -3188,8 +3230,8 @@
         methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist );
 
         parent = has_customattribute( TABLE_METHODDEF, methoddef );
-        attr_type = customattribute_type( TABLE_MEMBERREF, class->md.member[MD_ATTR_CONTRACT] );
-        value_size = make_contract_value( class, value );
+        attr_type = customattribute_type( TABLE_MEMBERREF, contract_attr->md_member );
+        value_size = make_contract_value( contract_attr, value );
         add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
     }
 }
@@ -3197,7 +3239,7 @@
 static void add_composition_interfaces( const type_t *class )
 {
     UINT flags = METHOD_ATTR_FAMILY | METHOD_ATTR_HIDEBYSIG | METHOD_ATTR_SPECIALNAME | METHOD_ATTR_RTSPECIALNAME;
-    const attr_t *attr;
+    const attr_t *attr, *contract_attr = get_attr( class->attrs, ATTR_CONTRACT );
 
     if (class->attrs) LIST_FOR_EACH_ENTRY_REV( attr, class->attrs, const attr_t, entry )
     {
@@ -3233,8 +3275,8 @@
         methoddef = add_methoddef_row( METHOD_IMPL_RUNTIME, flags, add_string(".ctor"), add_blob(sig, sig_size), paramlist );
 
         parent = has_customattribute( TABLE_METHODDEF, methoddef );
-        attr_type = customattribute_type( TABLE_MEMBERREF, class->md.member[MD_ATTR_CONTRACT] );
-        value_size = make_contract_value( class, value );
+        attr_type = customattribute_type( TABLE_MEMBERREF, contract_attr->md_member );
+        value_size = make_contract_value( contract_attr, value );
         add_customattribute_row( parent, attr_type, add_blob(value, value_size) );
     }
 }
diff --git a/mingw-w64-tools/widl/src/parser.l b/mingw-w64-tools/widl/src/parser.l
index 9ff4e7b..c57ad99 100644
--- a/mingw-w64-tools/widl/src/parser.l
+++ b/mingw-w64-tools/widl/src/parser.l
@@ -136,7 +136,10 @@
 
 static int token_str( int token, const char *str, YYSTYPE *yylval )
 {
-    char *tmp = xstrdup( str );
+    int len = strlen( str );
+    char *tmp = xmalloc( len + 1 );
+
+    strcpy( tmp, str );
 
     if (token == aWSTRING || token == aSTRING || token == aSQSTRING)
     {
@@ -149,6 +152,14 @@
         }
         dst[-1] = 0; /* strip last quote */
     }
+    else if (token == aIDENTIFIER)
+    {
+        if (len > 255)
+        {
+            warning( "truncating identifier that exceeds 255 character limit\n" );
+            tmp[255] = 0;
+        }
+    }
 
     yylval->str = tmp;
     return token;
diff --git a/mingw-w64-tools/widl/src/parser.tab.c b/mingw-w64-tools/widl/src/parser.tab.c
index d521169..b18bfff 100644
--- a/mingw-w64-tools/widl/src/parser.tab.c
+++ b/mingw-w64-tools/widl/src/parser.tab.c
@@ -136,6 +136,7 @@
 static void append_chain_type(declarator_t *decl, type_t *type, enum type_qualifier qual);
 static void append_chain_callconv( struct location where, type_t *chain, char *callconv );
 static warning_list_t *append_warning(warning_list_t *, int);
+static version_t *make_version( unsigned short major, unsigned short minor );
 
 static type_t *reg_typedefs( struct location where, decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs );
 static type_t *find_type_or_error(struct namespace *parent, const char *name);
@@ -182,7 +183,7 @@
 static typelib_t *current_typelib;
 
 
-#line 186 "tools/widl/parser.tab.c"
+#line 187 "tools/widl/parser.tab.c"
 
 # ifndef YY_CAST
 #  ifdef __cplusplus
@@ -222,13 +223,13 @@
 extern int parser_debug;
 #endif
 /* "%code requires" blocks.  */
-#line 110 "tools/widl/parser.y"
+#line 111 "tools/widl/parser.y"
 
 
 #define PARSER_LTYPE struct location
 
 
-#line 232 "tools/widl/parser.tab.c"
+#line 233 "tools/widl/parser.tab.c"
 
 /* Token kinds.  */
 #ifndef PARSER_TOKENTYPE
@@ -459,7 +460,7 @@
 #if ! defined PARSER_STYPE && ! defined PARSER_STYPE_IS_DECLARED
 union PARSER_STYPE
 {
-#line 134 "tools/widl/parser.y"
+#line 135 "tools/widl/parser.y"
 
 	attr_t *attr;
 	attr_list_t *attr_list;
@@ -477,6 +478,7 @@
 	warning_list_t *warning_list;
 	typeref_t *typeref;
 	typeref_list_t *typeref_list;
+	version_t *version;
 	char *str;
 	struct uuid *uuid;
 	unsigned int num;
@@ -490,7 +492,7 @@
 	enum function_specifier function_specifier;
 	struct namespace *namespace;
 
-#line 494 "tools/widl/parser.tab.c"
+#line 496 "tools/widl/parser.tab.c"
 
 };
 typedef union PARSER_STYPE PARSER_STYPE;
@@ -518,7 +520,7 @@
 int parser_parse (void);
 
 /* "%code provides" blocks.  */
-#line 117 "tools/widl/parser.y"
+#line 118 "tools/widl/parser.y"
 
 
 int parser_lex( PARSER_STYPE *yylval, PARSER_LTYPE *yylloc );
@@ -530,7 +532,7 @@
              else init_location( &(cur), &YYRHSLOC( rhs, 0 ), NULL ); } while(0)
 
 
-#line 534 "tools/widl/parser.tab.c"
+#line 536 "tools/widl/parser.tab.c"
 
 
 /* Symbol kind.  */
@@ -1332,57 +1334,57 @@
 /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_int16 yyrline[] =
 {
-       0,   370,   370,   388,   389,   393,   394,   400,   404,   405,
-     410,   414,   415,   415,   417,   418,   419,   420,   421,   424,
-     427,   428,   430,   431,   433,   434,   435,   436,   440,   441,
-     442,   443,   443,   445,   446,   447,   448,   451,   452,   454,
-     455,   457,   458,   459,   460,   461,   465,   466,   470,   471,
-     475,   476,   477,   478,   479,   480,   481,   484,   492,   500,
-     501,   505,   506,   507,   508,   509,   510,   511,   512,   513,
-     516,   519,   521,   524,   528,   530,   534,   539,   540,   543,
-     544,   547,   548,   552,   557,   564,   568,   569,   573,   574,
-     578,   581,   582,   583,   586,   587,   591,   592,   593,   597,
-     598,   602,   612,   619,   623,   627,   628,   632,   640,   645,
-     646,   647,   648,   649,   650,   651,   652,   653,   654,   655,
-     656,   657,   658,   659,   660,   661,   662,   663,   664,   665,
-     669,   670,   671,   672,   673,   674,   675,   676,   677,   678,
-     679,   680,   681,   682,   683,   684,   685,   686,   687,   691,
-     692,   693,   694,   695,   696,   697,   698,   699,   701,   702,
-     703,   704,   705,   706,   707,   708,   709,   710,   711,   712,
-     713,   714,   715,   716,   718,   719,   720,   721,   722,   723,
-     724,   725,   726,   727,   728,   729,   730,   731,   732,   733,
-     734,   735,   736,   737,   738,   739,   740,   741,   742,   747,
-     748,   749,   750,   751,   752,   753,   754,   755,   756,   757,
-     758,   759,   760,   761,   762,   763,   764,   765,   766,   767,
-     768,   769,   770,   771,   774,   775,   776,   777,   781,   782,
-     785,   789,   796,   797,   798,   801,   807,   824,   829,   833,
-     838,   841,   842,   846,   847,   850,   851,   852,   853,   855,
-     857,   859,   860,   861,   862,   863,   864,   865,   866,   867,
-     868,   869,   870,   871,   872,   873,   874,   875,   876,   877,
-     878,   879,   880,   881,   882,   883,   884,   885,   886,   887,
-     888,   889,   890,   892,   894,   895,   898,   899,   902,   908,
-     915,   916,   919,   924,   931,   932,   936,   937,   941,   942,
-     945,   949,   955,   963,   967,   973,   974,   978,   979,   982,
-     983,   986,   989,   990,   991,   992,   993,   994,   995,   996,
-     997,   998,   999,  1003,  1004,  1007,  1008,  1009,  1010,  1011,
-    1012,  1013,  1014,  1015,  1019,  1020,  1024,  1025,  1028,  1033,
-    1034,  1035,  1036,  1037,  1041,  1042,  1046,  1049,  1053,  1056,
-    1061,  1064,  1068,  1069,  1073,  1074,  1078,  1079,  1082,  1085,
-    1088,  1089,  1092,  1093,  1097,  1099,  1104,  1105,  1106,  1109,
-    1113,  1114,  1118,  1119,  1119,  1119,  1123,  1128,  1129,  1127,
-    1136,  1137,  1138,  1139,  1143,  1144,  1147,  1147,  1160,  1164,
-    1165,  1166,  1170,  1173,  1176,  1181,  1182,  1183,  1187,  1191,
-    1195,  1196,  1199,  1200,  1204,  1206,  1211,  1212,  1216,  1217,
-    1218,  1222,  1224,  1225,  1229,  1230,  1231,  1232,  1237,  1239,
-    1240,  1245,  1247,  1252,  1253,  1258,  1259,  1260,  1261,  1265,
-    1273,  1275,  1276,  1281,  1283,  1288,  1289,  1296,  1297,  1298,
-    1299,  1300,  1304,  1311,  1312,  1316,  1317,  1320,  1327,  1328,
-    1333,  1334,  1338,  1339,  1340,  1341,  1342,  1343,  1347,  1348,
-    1349,  1352,  1356,  1357,  1358,  1359,  1360,  1361,  1362,  1363,
-    1364,  1365,  1369,  1370,  1371,  1374,  1381,  1383,  1389,  1390,
-    1391,  1395,  1396,  1400,  1401,  1405,  1412,  1421,  1422,  1426,
-    1427,  1431,  1433,  1434,  1435,  1439,  1440,  1445,  1446,  1447,
-    1448
+       0,   372,   372,   390,   391,   395,   396,   402,   406,   407,
+     412,   416,   417,   417,   419,   420,   421,   422,   423,   426,
+     429,   430,   432,   433,   435,   436,   437,   438,   442,   443,
+     444,   445,   445,   447,   448,   449,   450,   453,   454,   456,
+     457,   459,   460,   461,   462,   463,   467,   468,   472,   473,
+     477,   478,   479,   480,   481,   482,   483,   486,   494,   502,
+     503,   507,   508,   509,   510,   511,   512,   513,   514,   515,
+     518,   521,   523,   526,   530,   532,   536,   541,   542,   545,
+     546,   549,   550,   554,   559,   566,   570,   571,   575,   576,
+     580,   583,   584,   585,   588,   589,   593,   594,   595,   599,
+     600,   604,   614,   621,   625,   629,   630,   634,   642,   647,
+     648,   649,   650,   651,   652,   653,   654,   655,   656,   657,
+     658,   659,   660,   661,   662,   663,   664,   665,   666,   667,
+     671,   672,   673,   674,   675,   676,   677,   678,   679,   680,
+     681,   682,   683,   684,   685,   686,   687,   688,   689,   693,
+     694,   695,   696,   697,   698,   699,   700,   701,   703,   704,
+     705,   706,   707,   708,   709,   710,   711,   712,   713,   714,
+     715,   716,   717,   718,   720,   721,   722,   723,   724,   725,
+     726,   727,   728,   729,   730,   731,   732,   733,   734,   735,
+     736,   737,   738,   739,   740,   741,   742,   743,   744,   749,
+     750,   751,   752,   753,   754,   755,   756,   757,   758,   759,
+     760,   761,   762,   763,   764,   765,   766,   767,   768,   769,
+     770,   771,   772,   773,   776,   777,   778,   779,   783,   784,
+     787,   791,   798,   799,   800,   803,   809,   826,   831,   835,
+     840,   843,   844,   848,   849,   852,   853,   854,   855,   857,
+     859,   861,   862,   863,   864,   865,   866,   867,   868,   869,
+     870,   871,   872,   873,   874,   875,   876,   877,   878,   879,
+     880,   881,   882,   883,   884,   885,   886,   887,   888,   889,
+     890,   891,   892,   894,   896,   897,   900,   901,   904,   910,
+     917,   918,   921,   926,   933,   934,   938,   939,   943,   944,
+     947,   951,   957,   965,   969,   975,   976,   980,   981,   984,
+     985,   988,   991,   992,   993,   994,   995,   996,   997,   998,
+     999,  1000,  1001,  1005,  1006,  1009,  1010,  1011,  1012,  1013,
+    1014,  1015,  1016,  1017,  1021,  1022,  1026,  1027,  1030,  1035,
+    1036,  1037,  1038,  1039,  1043,  1044,  1048,  1051,  1055,  1058,
+    1063,  1066,  1070,  1071,  1075,  1076,  1080,  1081,  1084,  1087,
+    1090,  1091,  1094,  1095,  1099,  1101,  1106,  1107,  1108,  1111,
+    1115,  1116,  1120,  1121,  1121,  1121,  1125,  1130,  1131,  1129,
+    1138,  1139,  1140,  1141,  1145,  1146,  1149,  1149,  1162,  1166,
+    1167,  1168,  1172,  1175,  1178,  1183,  1184,  1185,  1189,  1193,
+    1197,  1198,  1201,  1202,  1206,  1208,  1213,  1214,  1218,  1219,
+    1220,  1224,  1226,  1227,  1231,  1232,  1233,  1234,  1239,  1241,
+    1242,  1247,  1249,  1254,  1255,  1260,  1261,  1262,  1263,  1267,
+    1275,  1277,  1278,  1283,  1285,  1290,  1291,  1298,  1299,  1300,
+    1301,  1302,  1306,  1313,  1314,  1318,  1319,  1322,  1329,  1330,
+    1335,  1336,  1340,  1341,  1342,  1343,  1344,  1345,  1349,  1350,
+    1351,  1354,  1358,  1359,  1360,  1361,  1362,  1363,  1364,  1365,
+    1366,  1367,  1371,  1372,  1373,  1376,  1383,  1385,  1391,  1392,
+    1393,  1397,  1398,  1402,  1403,  1407,  1414,  1423,  1424,  1428,
+    1429,  1433,  1435,  1436,  1437,  1441,  1442,  1447,  1448,  1449,
+    1450
 };
 #endif
 
@@ -3549,7 +3551,7 @@
   switch (yyn)
     {
   case 2: /* input: gbl_statements m_acf  */
-#line 370 "tools/widl/parser.y"
+#line 372 "tools/widl/parser.y"
                                                 { (yyvsp[-1].stmt_list) = append_parameterized_type_stmts((yyvsp[-1].stmt_list));
 						  check_statements((yyvsp[-1].stmt_list), FALSE);
 						  check_all_user_types((yyvsp[-1].stmt_list));
@@ -3565,323 +3567,323 @@
 						  write_metadata((yyvsp[-1].stmt_list));
                                                   (void)parser_nerrs;  /* avoid unused variable warning */
 						}
-#line 3569 "tools/widl/parser.tab.c"
+#line 3571 "tools/widl/parser.tab.c"
     break;
 
   case 5: /* decl_statements: %empty  */
-#line 393 "tools/widl/parser.y"
+#line 395 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = NULL; }
-#line 3575 "tools/widl/parser.tab.c"
+#line 3577 "tools/widl/parser.tab.c"
     break;
 
   case 6: /* decl_statements: decl_statements tINTERFACE qualified_type '<' parameterized_type_args '>' ';'  */
-#line 395 "tools/widl/parser.y"
+#line 397 "tools/widl/parser.y"
                                                 { parameterized_type_stmts = append_statement(parameterized_type_stmts, make_statement_parameterized_type((yyvsp[-4].type), (yyvsp[-2].typeref_list)));
 						  (yyval.stmt_list) = append_statement((yyvsp[-6].stmt_list), make_statement_reference(type_parameterized_type_specialize_declare((yyvsp[-4].type), (yyvsp[-2].typeref_list))));
 						}
-#line 3583 "tools/widl/parser.tab.c"
+#line 3585 "tools/widl/parser.tab.c"
     break;
 
   case 7: /* decl_block: tDECLARE '{' decl_statements '}'  */
-#line 400 "tools/widl/parser.y"
+#line 402 "tools/widl/parser.y"
                                              { (yyval.stmt_list) = (yyvsp[-1].stmt_list); }
-#line 3589 "tools/widl/parser.tab.c"
+#line 3591 "tools/widl/parser.tab.c"
     break;
 
   case 8: /* imp_decl_statements: %empty  */
-#line 404 "tools/widl/parser.y"
+#line 406 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = NULL; }
-#line 3595 "tools/widl/parser.tab.c"
+#line 3597 "tools/widl/parser.tab.c"
     break;
 
   case 9: /* imp_decl_statements: imp_decl_statements tINTERFACE qualified_type '<' parameterized_type_args '>' ';'  */
-#line 406 "tools/widl/parser.y"
+#line 408 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-6].stmt_list), make_statement_reference(type_parameterized_type_specialize_declare((yyvsp[-4].type), (yyvsp[-2].typeref_list)))); }
-#line 3601 "tools/widl/parser.tab.c"
+#line 3603 "tools/widl/parser.tab.c"
     break;
 
   case 10: /* imp_decl_block: tDECLARE '{' imp_decl_statements '}'  */
-#line 410 "tools/widl/parser.y"
+#line 412 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = (yyvsp[-1].stmt_list); }
-#line 3607 "tools/widl/parser.tab.c"
+#line 3609 "tools/widl/parser.tab.c"
     break;
 
   case 11: /* gbl_statements: %empty  */
-#line 414 "tools/widl/parser.y"
+#line 416 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = NULL; }
-#line 3613 "tools/widl/parser.tab.c"
+#line 3615 "tools/widl/parser.tab.c"
     break;
 
   case 12: /* $@1: %empty  */
-#line 415 "tools/widl/parser.y"
+#line 417 "tools/widl/parser.y"
                                           { push_namespaces((yyvsp[-1].str_list)); }
-#line 3619 "tools/widl/parser.tab.c"
+#line 3621 "tools/widl/parser.tab.c"
     break;
 
   case 13: /* gbl_statements: gbl_statements namespacedef '{' $@1 gbl_statements '}'  */
-#line 416 "tools/widl/parser.y"
+#line 418 "tools/widl/parser.y"
                                                 { pop_namespaces((yyvsp[-4].str_list)); (yyval.stmt_list) = append_statements((yyvsp[-5].stmt_list), (yyvsp[-1].stmt_list)); }
-#line 3625 "tools/widl/parser.tab.c"
+#line 3627 "tools/widl/parser.tab.c"
     break;
 
   case 14: /* gbl_statements: gbl_statements interface ';'  */
-#line 417 "tools/widl/parser.y"
+#line 419 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-2].stmt_list), make_statement_reference((yyvsp[-1].type))); }
-#line 3631 "tools/widl/parser.tab.c"
+#line 3633 "tools/widl/parser.tab.c"
     break;
 
   case 15: /* gbl_statements: gbl_statements dispinterface ';'  */
-#line 418 "tools/widl/parser.y"
+#line 420 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-2].stmt_list), make_statement_reference((yyvsp[-1].type))); }
-#line 3637 "tools/widl/parser.tab.c"
+#line 3639 "tools/widl/parser.tab.c"
     break;
 
   case 16: /* gbl_statements: gbl_statements interfacedef  */
-#line 419 "tools/widl/parser.y"
+#line 421 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); }
-#line 3643 "tools/widl/parser.tab.c"
+#line 3645 "tools/widl/parser.tab.c"
     break;
 
   case 17: /* gbl_statements: gbl_statements delegatedef  */
-#line 420 "tools/widl/parser.y"
+#line 422 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); }
-#line 3649 "tools/widl/parser.tab.c"
+#line 3651 "tools/widl/parser.tab.c"
     break;
 
   case 18: /* gbl_statements: gbl_statements coclass ';'  */
-#line 421 "tools/widl/parser.y"
+#line 423 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = (yyvsp[-2].stmt_list);
 						  reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0);
 						}
-#line 3657 "tools/widl/parser.tab.c"
+#line 3659 "tools/widl/parser.tab.c"
     break;
 
   case 19: /* gbl_statements: gbl_statements coclassdef  */
-#line 424 "tools/widl/parser.y"
+#line 426 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 						  reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0);
 						}
-#line 3665 "tools/widl/parser.tab.c"
+#line 3667 "tools/widl/parser.tab.c"
     break;
 
   case 20: /* gbl_statements: gbl_statements apicontract ';'  */
-#line 427 "tools/widl/parser.y"
+#line 429 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = (yyvsp[-2].stmt_list); reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); }
-#line 3671 "tools/widl/parser.tab.c"
+#line 3673 "tools/widl/parser.tab.c"
     break;
 
   case 21: /* gbl_statements: gbl_statements apicontract_def  */
-#line 428 "tools/widl/parser.y"
+#line 430 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 						  reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0); }
-#line 3678 "tools/widl/parser.tab.c"
+#line 3680 "tools/widl/parser.tab.c"
     break;
 
   case 22: /* gbl_statements: gbl_statements runtimeclass ';'  */
-#line 430 "tools/widl/parser.y"
+#line 432 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = (yyvsp[-2].stmt_list); reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); }
-#line 3684 "tools/widl/parser.tab.c"
+#line 3686 "tools/widl/parser.tab.c"
     break;
 
   case 23: /* gbl_statements: gbl_statements runtimeclass_def  */
-#line 431 "tools/widl/parser.y"
+#line 433 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 	                                          reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0); }
-#line 3691 "tools/widl/parser.tab.c"
+#line 3693 "tools/widl/parser.tab.c"
     break;
 
   case 24: /* gbl_statements: gbl_statements moduledef  */
-#line 433 "tools/widl/parser.y"
+#line 435 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_module((yyvsp[0].type))); }
-#line 3697 "tools/widl/parser.tab.c"
+#line 3699 "tools/widl/parser.tab.c"
     break;
 
   case 25: /* gbl_statements: gbl_statements librarydef  */
-#line 434 "tools/widl/parser.y"
+#line 436 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_library((yyvsp[0].typelib))); }
-#line 3703 "tools/widl/parser.tab.c"
+#line 3705 "tools/widl/parser.tab.c"
     break;
 
   case 26: /* gbl_statements: gbl_statements statement  */
-#line 435 "tools/widl/parser.y"
+#line 437 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); }
-#line 3709 "tools/widl/parser.tab.c"
+#line 3711 "tools/widl/parser.tab.c"
     break;
 
   case 27: /* gbl_statements: gbl_statements decl_block  */
-#line 436 "tools/widl/parser.y"
+#line 438 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statements((yyvsp[-1].stmt_list), (yyvsp[0].stmt_list)); }
-#line 3715 "tools/widl/parser.tab.c"
+#line 3717 "tools/widl/parser.tab.c"
     break;
 
   case 28: /* imp_statements: %empty  */
-#line 440 "tools/widl/parser.y"
+#line 442 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = NULL; }
-#line 3721 "tools/widl/parser.tab.c"
+#line 3723 "tools/widl/parser.tab.c"
     break;
 
   case 29: /* imp_statements: imp_statements interface ';'  */
-#line 441 "tools/widl/parser.y"
+#line 443 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-2].stmt_list), make_statement_reference((yyvsp[-1].type))); }
-#line 3727 "tools/widl/parser.tab.c"
+#line 3729 "tools/widl/parser.tab.c"
     break;
 
   case 30: /* imp_statements: imp_statements dispinterface ';'  */
-#line 442 "tools/widl/parser.y"
+#line 444 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-2].stmt_list), make_statement_reference((yyvsp[-1].type))); }
-#line 3733 "tools/widl/parser.tab.c"
+#line 3735 "tools/widl/parser.tab.c"
     break;
 
   case 31: /* $@2: %empty  */
-#line 443 "tools/widl/parser.y"
+#line 445 "tools/widl/parser.y"
                                           { push_namespaces((yyvsp[-1].str_list)); }
-#line 3739 "tools/widl/parser.tab.c"
+#line 3741 "tools/widl/parser.tab.c"
     break;
 
   case 32: /* imp_statements: imp_statements namespacedef '{' $@2 imp_statements '}'  */
-#line 444 "tools/widl/parser.y"
+#line 446 "tools/widl/parser.y"
                                                 { pop_namespaces((yyvsp[-4].str_list)); (yyval.stmt_list) = append_statements((yyvsp[-5].stmt_list), (yyvsp[-1].stmt_list)); }
-#line 3745 "tools/widl/parser.tab.c"
+#line 3747 "tools/widl/parser.tab.c"
     break;
 
   case 33: /* imp_statements: imp_statements interfacedef  */
-#line 445 "tools/widl/parser.y"
+#line 447 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); }
-#line 3751 "tools/widl/parser.tab.c"
+#line 3753 "tools/widl/parser.tab.c"
     break;
 
   case 34: /* imp_statements: imp_statements delegatedef  */
-#line 446 "tools/widl/parser.y"
+#line 448 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); }
-#line 3757 "tools/widl/parser.tab.c"
+#line 3759 "tools/widl/parser.tab.c"
     break;
 
   case 35: /* imp_statements: imp_statements coclass ';'  */
-#line 447 "tools/widl/parser.y"
+#line 449 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = (yyvsp[-2].stmt_list); reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); }
-#line 3763 "tools/widl/parser.tab.c"
+#line 3765 "tools/widl/parser.tab.c"
     break;
 
   case 36: /* imp_statements: imp_statements coclassdef  */
-#line 448 "tools/widl/parser.y"
+#line 450 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 						  reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0);
 						}
-#line 3771 "tools/widl/parser.tab.c"
+#line 3773 "tools/widl/parser.tab.c"
     break;
 
   case 37: /* imp_statements: imp_statements apicontract ';'  */
-#line 451 "tools/widl/parser.y"
+#line 453 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = (yyvsp[-2].stmt_list); reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); }
-#line 3777 "tools/widl/parser.tab.c"
+#line 3779 "tools/widl/parser.tab.c"
     break;
 
   case 38: /* imp_statements: imp_statements apicontract_def  */
-#line 452 "tools/widl/parser.y"
+#line 454 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 						  reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0); }
-#line 3784 "tools/widl/parser.tab.c"
+#line 3786 "tools/widl/parser.tab.c"
     break;
 
   case 39: /* imp_statements: imp_statements runtimeclass ';'  */
-#line 454 "tools/widl/parser.y"
+#line 456 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = (yyvsp[-2].stmt_list); reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); }
-#line 3790 "tools/widl/parser.tab.c"
+#line 3792 "tools/widl/parser.tab.c"
     break;
 
   case 40: /* imp_statements: imp_statements runtimeclass_def  */
-#line 455 "tools/widl/parser.y"
+#line 457 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 	                                          reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0); }
-#line 3797 "tools/widl/parser.tab.c"
+#line 3799 "tools/widl/parser.tab.c"
     break;
 
   case 41: /* imp_statements: imp_statements moduledef  */
-#line 457 "tools/widl/parser.y"
+#line 459 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_module((yyvsp[0].type))); }
-#line 3803 "tools/widl/parser.tab.c"
+#line 3805 "tools/widl/parser.tab.c"
     break;
 
   case 42: /* imp_statements: imp_statements statement  */
-#line 458 "tools/widl/parser.y"
+#line 460 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); }
-#line 3809 "tools/widl/parser.tab.c"
+#line 3811 "tools/widl/parser.tab.c"
     break;
 
   case 43: /* imp_statements: imp_statements importlib  */
-#line 459 "tools/widl/parser.y"
+#line 461 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_importlib((yyvsp[0].str))); }
-#line 3815 "tools/widl/parser.tab.c"
+#line 3817 "tools/widl/parser.tab.c"
     break;
 
   case 44: /* imp_statements: imp_statements librarydef  */
-#line 460 "tools/widl/parser.y"
+#line 462 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_library((yyvsp[0].typelib))); }
-#line 3821 "tools/widl/parser.tab.c"
+#line 3823 "tools/widl/parser.tab.c"
     break;
 
   case 45: /* imp_statements: imp_statements imp_decl_block  */
-#line 461 "tools/widl/parser.y"
+#line 463 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statements((yyvsp[-1].stmt_list), (yyvsp[0].stmt_list)); }
-#line 3827 "tools/widl/parser.tab.c"
+#line 3829 "tools/widl/parser.tab.c"
     break;
 
   case 46: /* int_statements: %empty  */
-#line 465 "tools/widl/parser.y"
+#line 467 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = NULL; }
-#line 3833 "tools/widl/parser.tab.c"
+#line 3835 "tools/widl/parser.tab.c"
     break;
 
   case 47: /* int_statements: int_statements statement  */
-#line 466 "tools/widl/parser.y"
+#line 468 "tools/widl/parser.y"
                                                 { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); }
-#line 3839 "tools/widl/parser.tab.c"
+#line 3841 "tools/widl/parser.tab.c"
     break;
 
   case 50: /* statement: cppquote  */
-#line 475 "tools/widl/parser.y"
+#line 477 "tools/widl/parser.y"
                                                 { (yyval.statement) = make_statement_cppquote((yyvsp[0].str)); }
-#line 3845 "tools/widl/parser.tab.c"
+#line 3847 "tools/widl/parser.tab.c"
     break;
 
   case 51: /* statement: typedecl ';'  */
-#line 476 "tools/widl/parser.y"
+#line 478 "tools/widl/parser.y"
                                                 { (yyval.statement) = make_statement_type_decl((yyvsp[-1].type)); }
-#line 3851 "tools/widl/parser.tab.c"
+#line 3853 "tools/widl/parser.tab.c"
     break;
 
   case 52: /* statement: declaration ';'  */
-#line 477 "tools/widl/parser.y"
+#line 479 "tools/widl/parser.y"
                                                 { (yyval.statement) = make_statement_declaration((yyvsp[-1].var)); }
-#line 3857 "tools/widl/parser.tab.c"
+#line 3859 "tools/widl/parser.tab.c"
     break;
 
   case 53: /* statement: import  */
-#line 478 "tools/widl/parser.y"
+#line 480 "tools/widl/parser.y"
                                                 { (yyval.statement) = make_statement_import((yyvsp[0].str)); }
-#line 3863 "tools/widl/parser.tab.c"
+#line 3865 "tools/widl/parser.tab.c"
     break;
 
   case 54: /* statement: typedef ';'  */
-#line 479 "tools/widl/parser.y"
+#line 481 "tools/widl/parser.y"
                                                 { (yyval.statement) = (yyvsp[-1].statement); }
-#line 3869 "tools/widl/parser.tab.c"
+#line 3871 "tools/widl/parser.tab.c"
     break;
 
   case 55: /* statement: aPRAGMA  */
-#line 480 "tools/widl/parser.y"
+#line 482 "tools/widl/parser.y"
                                                 { (yyval.statement) = make_statement_pragma((yyvsp[0].str)); }
-#line 3875 "tools/widl/parser.tab.c"
+#line 3877 "tools/widl/parser.tab.c"
     break;
 
   case 56: /* statement: pragma_warning  */
-#line 481 "tools/widl/parser.y"
+#line 483 "tools/widl/parser.y"
                          { (yyval.statement) = NULL; }
-#line 3881 "tools/widl/parser.tab.c"
+#line 3883 "tools/widl/parser.tab.c"
     break;
 
   case 57: /* pragma_warning: tPRAGMA_WARNING '(' aIDENTIFIER ':' warnings ')'  */
-#line 485 "tools/widl/parser.y"
+#line 487 "tools/widl/parser.y"
                   {
                       int result;
                       (yyval.statement) = NULL;
@@ -3889,1064 +3891,1064 @@
                       if(!result)
                           error_loc("expected \"disable\", \"enable\" or \"default\"\n");
                   }
-#line 3893 "tools/widl/parser.tab.c"
+#line 3895 "tools/widl/parser.tab.c"
     break;
 
   case 58: /* pragma_warning: tPRAGMA_WARNING '(' tDEFAULT ':' warnings ')'  */
-#line 493 "tools/widl/parser.y"
+#line 495 "tools/widl/parser.y"
                   {
                       (yyval.statement) = NULL;
                       do_warning("default", (yyvsp[-1].warning_list));
                   }
-#line 3902 "tools/widl/parser.tab.c"
+#line 3904 "tools/widl/parser.tab.c"
     break;
 
   case 59: /* warnings: aNUM  */
-#line 500 "tools/widl/parser.y"
+#line 502 "tools/widl/parser.y"
                { (yyval.warning_list) = append_warning(NULL, (yyvsp[0].integer).value); }
-#line 3908 "tools/widl/parser.tab.c"
+#line 3910 "tools/widl/parser.tab.c"
     break;
 
   case 60: /* warnings: warnings aNUM  */
-#line 501 "tools/widl/parser.y"
+#line 503 "tools/widl/parser.y"
                         { (yyval.warning_list) = append_warning((yyvsp[-1].warning_list), (yyvsp[0].integer).value); }
-#line 3914 "tools/widl/parser.tab.c"
+#line 3916 "tools/widl/parser.tab.c"
     break;
 
   case 62: /* typedecl: tENUM typename  */
-#line 506 "tools/widl/parser.y"
+#line 508 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_enum((yyvsp[0].str), current_namespace, FALSE, NULL, &(yyloc)); }
-#line 3920 "tools/widl/parser.tab.c"
+#line 3922 "tools/widl/parser.tab.c"
     break;
 
   case 64: /* typedecl: tSTRUCT typename  */
-#line 508 "tools/widl/parser.y"
+#line 510 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_struct((yyvsp[0].str), current_namespace, FALSE, NULL, &(yyloc)); }
-#line 3926 "tools/widl/parser.tab.c"
+#line 3928 "tools/widl/parser.tab.c"
     break;
 
   case 66: /* typedecl: tUNION typename  */
-#line 510 "tools/widl/parser.y"
+#line 512 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_nonencapsulated_union((yyvsp[0].str), current_namespace, FALSE, NULL, &(yyloc)); }
-#line 3932 "tools/widl/parser.tab.c"
+#line 3934 "tools/widl/parser.tab.c"
     break;
 
   case 67: /* typedecl: attributes enumdef  */
-#line 511 "tools/widl/parser.y"
+#line 513 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_enum_attrs((yyvsp[-1].attr_list)); }
-#line 3938 "tools/widl/parser.tab.c"
+#line 3940 "tools/widl/parser.tab.c"
     break;
 
   case 68: /* typedecl: attributes structdef  */
-#line 512 "tools/widl/parser.y"
+#line 514 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_struct_attrs((yyvsp[-1].attr_list)); }
-#line 3944 "tools/widl/parser.tab.c"
+#line 3946 "tools/widl/parser.tab.c"
     break;
 
   case 69: /* typedecl: attributes uniondef  */
-#line 513 "tools/widl/parser.y"
+#line 515 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_union_attrs((yyvsp[-1].attr_list)); }
-#line 3950 "tools/widl/parser.tab.c"
+#line 3952 "tools/widl/parser.tab.c"
     break;
 
   case 70: /* cppquote: tCPPQUOTE '(' aSTRING ')'  */
-#line 516 "tools/widl/parser.y"
+#line 518 "tools/widl/parser.y"
                                                 { (yyval.str) = (yyvsp[-1].str); }
-#line 3956 "tools/widl/parser.tab.c"
+#line 3958 "tools/widl/parser.tab.c"
     break;
 
   case 71: /* import_start: tIMPORT aSTRING ';'  */
-#line 519 "tools/widl/parser.y"
+#line 521 "tools/widl/parser.y"
                                                 { (yyval.str) = (yyvsp[-1].str); push_import( (yyvsp[-1].str), &yylloc ); }
-#line 3962 "tools/widl/parser.tab.c"
+#line 3964 "tools/widl/parser.tab.c"
     break;
 
   case 72: /* import: import_start imp_statements aEOF  */
-#line 521 "tools/widl/parser.y"
+#line 523 "tools/widl/parser.y"
                                                 { yylloc = pop_import(); }
-#line 3968 "tools/widl/parser.tab.c"
+#line 3970 "tools/widl/parser.tab.c"
     break;
 
   case 73: /* importlib: tIMPORTLIB '(' aSTRING ')' semicolon_opt  */
-#line 525 "tools/widl/parser.y"
+#line 527 "tools/widl/parser.y"
                                                 { (yyval.str) = (yyvsp[-2].str); if(!parse_only) add_importlib((yyvsp[-2].str), current_typelib); }
-#line 3974 "tools/widl/parser.tab.c"
+#line 3976 "tools/widl/parser.tab.c"
     break;
 
   case 74: /* libraryhdr: tLIBRARY typename  */
-#line 528 "tools/widl/parser.y"
+#line 530 "tools/widl/parser.y"
                                                 { (yyval.str) = (yyvsp[0].str); }
-#line 3980 "tools/widl/parser.tab.c"
+#line 3982 "tools/widl/parser.tab.c"
     break;
 
   case 75: /* library_start: attributes libraryhdr '{'  */
-#line 530 "tools/widl/parser.y"
+#line 532 "tools/widl/parser.y"
                                                 { (yyval.typelib) = make_library((yyvsp[-1].str), check_library_attrs((yyvsp[-1].str), (yyvsp[-2].attr_list)));
 						  if (!parse_only && do_typelib) current_typelib = (yyval.typelib);
 						}
-#line 3988 "tools/widl/parser.tab.c"
+#line 3990 "tools/widl/parser.tab.c"
     break;
 
   case 76: /* librarydef: library_start imp_statements '}' semicolon_opt  */
-#line 535 "tools/widl/parser.y"
+#line 537 "tools/widl/parser.y"
                                                 { (yyval.typelib) = (yyvsp[-3].typelib); (yyval.typelib)->stmts = (yyvsp[-2].stmt_list); }
-#line 3994 "tools/widl/parser.tab.c"
+#line 3996 "tools/widl/parser.tab.c"
     break;
 
   case 77: /* m_args: %empty  */
-#line 539 "tools/widl/parser.y"
+#line 541 "tools/widl/parser.y"
                                                 { (yyval.var_list) = NULL; }
-#line 4000 "tools/widl/parser.tab.c"
+#line 4002 "tools/widl/parser.tab.c"
     break;
 
   case 79: /* arg_list: arg  */
-#line 543 "tools/widl/parser.y"
+#line 545 "tools/widl/parser.y"
                                                 { check_arg_attrs((yyvsp[0].var)); (yyval.var_list) = append_var( NULL, (yyvsp[0].var) ); }
-#line 4006 "tools/widl/parser.tab.c"
+#line 4008 "tools/widl/parser.tab.c"
     break;
 
   case 80: /* arg_list: arg_list ',' arg  */
-#line 544 "tools/widl/parser.y"
+#line 546 "tools/widl/parser.y"
                                                 { check_arg_attrs((yyvsp[0].var)); (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var) ); }
-#line 4012 "tools/widl/parser.tab.c"
+#line 4014 "tools/widl/parser.tab.c"
     break;
 
   case 82: /* args: arg_list ',' ELLIPSIS  */
-#line 548 "tools/widl/parser.y"
+#line 550 "tools/widl/parser.y"
                                                 { (yyval.var_list) = append_var( (yyvsp[-2].var_list), make_var(xstrdup("...")) ); }
-#line 4018 "tools/widl/parser.tab.c"
+#line 4020 "tools/widl/parser.tab.c"
     break;
 
   case 83: /* arg: attributes decl_spec m_any_declarator  */
-#line 552 "tools/widl/parser.y"
+#line 554 "tools/widl/parser.y"
                                                 { if ((yyvsp[-1].declspec)->stgclass != STG_NONE && (yyvsp[-1].declspec)->stgclass != STG_REGISTER)
 						    error_loc("invalid storage class for function parameter\n");
 						  (yyval.var) = declare_var((yyvsp[-2].attr_list), (yyvsp[-1].declspec), (yyvsp[0].declarator), TRUE);
 						  free((yyvsp[-1].declspec)); free((yyvsp[0].declarator));
 						}
-#line 4028 "tools/widl/parser.tab.c"
+#line 4030 "tools/widl/parser.tab.c"
     break;
 
   case 84: /* arg: decl_spec m_any_declarator  */
-#line 557 "tools/widl/parser.y"
+#line 559 "tools/widl/parser.y"
                                                 { if ((yyvsp[-1].declspec)->stgclass != STG_NONE && (yyvsp[-1].declspec)->stgclass != STG_REGISTER)
 						    error_loc("invalid storage class for function parameter\n");
 						  (yyval.var) = declare_var(NULL, (yyvsp[-1].declspec), (yyvsp[0].declarator), TRUE);
 						  free((yyvsp[-1].declspec)); free((yyvsp[0].declarator));
 						}
-#line 4038 "tools/widl/parser.tab.c"
+#line 4040 "tools/widl/parser.tab.c"
     break;
 
   case 85: /* array: '[' expr ']'  */
-#line 564 "tools/widl/parser.y"
+#line 566 "tools/widl/parser.y"
                                                 { (yyval.expr) = (yyvsp[-1].expr);
 						  if (!(yyval.expr)->is_const || (yyval.expr)->cval <= 0)
 						      error_loc("array dimension is not a positive integer constant\n");
 						}
-#line 4047 "tools/widl/parser.tab.c"
+#line 4049 "tools/widl/parser.tab.c"
     break;
 
   case 86: /* array: '[' '*' ']'  */
-#line 568 "tools/widl/parser.y"
+#line 570 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr(EXPR_VOID); }
-#line 4053 "tools/widl/parser.tab.c"
+#line 4055 "tools/widl/parser.tab.c"
     break;
 
   case 87: /* array: '[' ']'  */
-#line 569 "tools/widl/parser.y"
+#line 571 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr(EXPR_VOID); }
-#line 4059 "tools/widl/parser.tab.c"
+#line 4061 "tools/widl/parser.tab.c"
     break;
 
   case 88: /* m_attributes: %empty  */
-#line 573 "tools/widl/parser.y"
+#line 575 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = NULL; }
-#line 4065 "tools/widl/parser.tab.c"
+#line 4067 "tools/widl/parser.tab.c"
     break;
 
   case 90: /* attributes: '[' attrib_list ']'  */
-#line 578 "tools/widl/parser.y"
+#line 580 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = (yyvsp[-1].attr_list); }
-#line 4071 "tools/widl/parser.tab.c"
+#line 4073 "tools/widl/parser.tab.c"
     break;
 
   case 91: /* attrib_list: attribute  */
-#line 581 "tools/widl/parser.y"
+#line 583 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = append_attr( NULL, (yyvsp[0].attr) ); }
-#line 4077 "tools/widl/parser.tab.c"
+#line 4079 "tools/widl/parser.tab.c"
     break;
 
   case 92: /* attrib_list: attrib_list ',' attribute  */
-#line 582 "tools/widl/parser.y"
+#line 584 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = append_attr( (yyvsp[-2].attr_list), (yyvsp[0].attr) ); }
-#line 4083 "tools/widl/parser.tab.c"
+#line 4085 "tools/widl/parser.tab.c"
     break;
 
   case 93: /* attrib_list: attrib_list ']' '[' attribute  */
-#line 583 "tools/widl/parser.y"
+#line 585 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = append_attr( (yyvsp[-3].attr_list), (yyvsp[0].attr) ); }
-#line 4089 "tools/widl/parser.tab.c"
+#line 4091 "tools/widl/parser.tab.c"
     break;
 
   case 94: /* str_list: aSTRING  */
-#line 586 "tools/widl/parser.y"
+#line 588 "tools/widl/parser.y"
                                                 { (yyval.str_list) = append_str( NULL, (yyvsp[0].str) ); }
-#line 4095 "tools/widl/parser.tab.c"
+#line 4097 "tools/widl/parser.tab.c"
     break;
 
   case 95: /* str_list: str_list ',' aSTRING  */
-#line 587 "tools/widl/parser.y"
+#line 589 "tools/widl/parser.y"
                                                 { (yyval.str_list) = append_str( (yyvsp[-2].str_list), (yyvsp[0].str) ); }
-#line 4101 "tools/widl/parser.tab.c"
+#line 4103 "tools/widl/parser.tab.c"
     break;
 
   case 96: /* marshaling_behavior: tAGILE  */
-#line 591 "tools/widl/parser.y"
+#line 593 "tools/widl/parser.y"
                                                 { (yyval.num) = MARSHALING_AGILE; }
-#line 4107 "tools/widl/parser.tab.c"
+#line 4109 "tools/widl/parser.tab.c"
     break;
 
   case 97: /* marshaling_behavior: tNONE  */
-#line 592 "tools/widl/parser.y"
+#line 594 "tools/widl/parser.y"
                                                 { (yyval.num) = MARSHALING_NONE; }
-#line 4113 "tools/widl/parser.tab.c"
+#line 4115 "tools/widl/parser.tab.c"
     break;
 
   case 98: /* marshaling_behavior: tSTANDARD  */
-#line 593 "tools/widl/parser.y"
+#line 595 "tools/widl/parser.y"
                                                 { (yyval.num) = MARSHALING_STANDARD; }
-#line 4119 "tools/widl/parser.tab.c"
+#line 4121 "tools/widl/parser.tab.c"
     break;
 
   case 99: /* contract_ver: aNUM  */
-#line 597 "tools/widl/parser.y"
-                                                { (yyval.num) = MAKEVERSION(0, (yyvsp[0].integer).value); }
-#line 4125 "tools/widl/parser.tab.c"
+#line 599 "tools/widl/parser.y"
+                                                { (yyval.version) = make_version( (yyvsp[0].integer).value, 0 ); }
+#line 4127 "tools/widl/parser.tab.c"
     break;
 
   case 100: /* contract_ver: aNUM '.' aNUM  */
-#line 598 "tools/widl/parser.y"
-                                                { (yyval.num) = MAKEVERSION((yyvsp[0].integer).value, (yyvsp[-2].integer).value); }
-#line 4131 "tools/widl/parser.tab.c"
+#line 600 "tools/widl/parser.y"
+                                                { (yyval.version) = make_version( (yyvsp[-2].integer).value, (yyvsp[0].integer).value ); }
+#line 4133 "tools/widl/parser.tab.c"
     break;
 
   case 101: /* contract_req: decl_spec ',' contract_ver  */
-#line 602 "tools/widl/parser.y"
+#line 604 "tools/widl/parser.y"
                                                 {
-                                                  struct integer integer = {.value = (yyvsp[0].num)};
+                                                  struct integer integer = {.value = ((yyvsp[0].version)->major << 16) | (yyvsp[0].version)->minor };
                                                   if ((yyvsp[-2].declspec)->type->type_type != TYPE_APICONTRACT)
                                                     error_loc("type %s is not an apicontract\n", (yyvsp[-2].declspec)->type->name);
                                                   (yyval.expr) = make_exprl(EXPR_NUM, &integer);
                                                   (yyval.expr) = make_exprt(EXPR_GTREQL, declare_var(NULL, (yyvsp[-2].declspec), make_declarator(NULL), 0), (yyval.expr));
                                                 }
-#line 4143 "tools/widl/parser.tab.c"
+#line 4145 "tools/widl/parser.tab.c"
     break;
 
   case 102: /* static_attr: decl_spec ',' contract_req  */
-#line 612 "tools/widl/parser.y"
+#line 614 "tools/widl/parser.y"
                                                 { if ((yyvsp[-2].declspec)->type->type_type != TYPE_INTERFACE)
 						      error_loc("type %s is not an interface\n", (yyvsp[-2].declspec)->type->name);
 						  (yyval.expr) = make_exprt(EXPR_MEMBER, declare_var(NULL, (yyvsp[-2].declspec), make_declarator(NULL), 0), (yyvsp[0].expr));
 						}
-#line 4152 "tools/widl/parser.tab.c"
+#line 4154 "tools/widl/parser.tab.c"
     break;
 
   case 103: /* activatable_attr: decl_spec ',' contract_req  */
-#line 619 "tools/widl/parser.y"
+#line 621 "tools/widl/parser.y"
                                                 { if ((yyvsp[-2].declspec)->type->type_type != TYPE_INTERFACE)
 						      error_loc("type %s is not an interface\n", (yyvsp[-2].declspec)->type->name);
 						  (yyval.expr) = make_exprt(EXPR_MEMBER, declare_var(NULL, (yyvsp[-2].declspec), make_declarator(NULL), 0), (yyvsp[0].expr));
 						}
-#line 4161 "tools/widl/parser.tab.c"
+#line 4163 "tools/widl/parser.tab.c"
     break;
 
   case 104: /* activatable_attr: contract_req  */
-#line 623 "tools/widl/parser.y"
+#line 625 "tools/widl/parser.y"
                                                 { (yyval.expr) = (yyvsp[0].expr); }
-#line 4167 "tools/widl/parser.tab.c"
+#line 4169 "tools/widl/parser.tab.c"
     break;
 
   case 105: /* access_attr: tPUBLIC  */
-#line 627 "tools/widl/parser.y"
+#line 629 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PUBLIC, 0 ); }
-#line 4173 "tools/widl/parser.tab.c"
+#line 4175 "tools/widl/parser.tab.c"
     break;
 
   case 106: /* access_attr: tPROTECTED  */
-#line 628 "tools/widl/parser.y"
+#line 630 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PROTECTED, 0 ); }
-#line 4179 "tools/widl/parser.tab.c"
+#line 4181 "tools/widl/parser.tab.c"
     break;
 
   case 107: /* composable_attr: decl_spec ',' access_attr ',' contract_req  */
-#line 633 "tools/widl/parser.y"
+#line 635 "tools/widl/parser.y"
                                                 { if ((yyvsp[-4].declspec)->type->type_type != TYPE_INTERFACE)
                                                       error_loc( "type %s is not an interface\n", (yyvsp[-4].declspec)->type->name );
                                                   (yyval.expr) = make_exprt( EXPR_MEMBER, declare_var( append_attr( NULL, (yyvsp[-2].attr) ), (yyvsp[-4].declspec), make_declarator( NULL ), 0 ), (yyvsp[0].expr) );
                                                 }
-#line 4188 "tools/widl/parser.tab.c"
+#line 4190 "tools/widl/parser.tab.c"
     break;
 
   case 108: /* deprecated_attr: aSTRING ',' aIDENTIFIER ',' contract_req  */
-#line 641 "tools/widl/parser.y"
+#line 643 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr3( EXPR_MEMBER, make_exprs( EXPR_STRLIT, (yyvsp[-4].str) ), make_exprs( EXPR_IDENTIFIER, (yyvsp[-2].str) ), (yyvsp[0].expr) ); }
-#line 4194 "tools/widl/parser.tab.c"
+#line 4196 "tools/widl/parser.tab.c"
     break;
 
   case 109: /* attribute: %empty  */
-#line 645 "tools/widl/parser.y"
+#line 647 "tools/widl/parser.y"
                                                 { (yyval.attr) = NULL; }
-#line 4200 "tools/widl/parser.tab.c"
+#line 4202 "tools/widl/parser.tab.c"
     break;
 
   case 110: /* attribute: tACTIVATABLE '(' activatable_attr ')'  */
-#line 646 "tools/widl/parser.y"
+#line 648 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_ACTIVATABLE, (yyvsp[-1].expr) ); }
-#line 4206 "tools/widl/parser.tab.c"
+#line 4208 "tools/widl/parser.tab.c"
     break;
 
   case 111: /* attribute: tAGGREGATABLE  */
-#line 647 "tools/widl/parser.y"
+#line 649 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_AGGREGATABLE, 0 ); }
-#line 4212 "tools/widl/parser.tab.c"
+#line 4214 "tools/widl/parser.tab.c"
     break;
 
   case 112: /* attribute: tANNOTATION '(' aSTRING ')'  */
-#line 648 "tools/widl/parser.y"
+#line 650 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_ANNOTATION, (yyvsp[-1].str) ); }
-#line 4218 "tools/widl/parser.tab.c"
+#line 4220 "tools/widl/parser.tab.c"
     break;
 
   case 113: /* attribute: tAPPOBJECT  */
-#line 649 "tools/widl/parser.y"
+#line 651 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_APPOBJECT, 0 ); }
-#line 4224 "tools/widl/parser.tab.c"
+#line 4226 "tools/widl/parser.tab.c"
     break;
 
   case 114: /* attribute: tASYNC  */
-#line 650 "tools/widl/parser.y"
+#line 652 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_ASYNC, 0 ); }
-#line 4230 "tools/widl/parser.tab.c"
+#line 4232 "tools/widl/parser.tab.c"
     break;
 
   case 115: /* attribute: tAUTOHANDLE  */
-#line 651 "tools/widl/parser.y"
+#line 653 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_AUTO_HANDLE, 0 ); }
-#line 4236 "tools/widl/parser.tab.c"
+#line 4238 "tools/widl/parser.tab.c"
     break;
 
   case 116: /* attribute: tBINDABLE  */
-#line 652 "tools/widl/parser.y"
+#line 654 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_BINDABLE, 0 ); }
-#line 4242 "tools/widl/parser.tab.c"
+#line 4244 "tools/widl/parser.tab.c"
     break;
 
   case 117: /* attribute: tBROADCAST  */
-#line 653 "tools/widl/parser.y"
+#line 655 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_BROADCAST, 0 ); }
-#line 4248 "tools/widl/parser.tab.c"
+#line 4250 "tools/widl/parser.tab.c"
     break;
 
   case 118: /* attribute: tCALLAS '(' ident ')'  */
-#line 654 "tools/widl/parser.y"
+#line 656 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_CALLAS, (yyvsp[-1].var) ); }
-#line 4254 "tools/widl/parser.tab.c"
+#line 4256 "tools/widl/parser.tab.c"
     break;
 
   case 119: /* attribute: tCASE '(' expr_list_int_const ')'  */
-#line 655 "tools/widl/parser.y"
+#line 657 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_CASE, (yyvsp[-1].expr_list) ); }
-#line 4260 "tools/widl/parser.tab.c"
+#line 4262 "tools/widl/parser.tab.c"
     break;
 
   case 120: /* attribute: tCODE  */
-#line 656 "tools/widl/parser.y"
+#line 658 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_CODE, 0 ); }
-#line 4266 "tools/widl/parser.tab.c"
+#line 4268 "tools/widl/parser.tab.c"
     break;
 
   case 121: /* attribute: tCOMPOSABLE '(' composable_attr ')'  */
-#line 657 "tools/widl/parser.y"
+#line 659 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_COMPOSABLE, (yyvsp[-1].expr) ); }
-#line 4272 "tools/widl/parser.tab.c"
+#line 4274 "tools/widl/parser.tab.c"
     break;
 
   case 122: /* attribute: tCOMMSTATUS  */
-#line 658 "tools/widl/parser.y"
+#line 660 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_COMMSTATUS, 0 ); }
-#line 4278 "tools/widl/parser.tab.c"
+#line 4280 "tools/widl/parser.tab.c"
     break;
 
   case 123: /* attribute: tCONTEXTHANDLE  */
-#line 659 "tools/widl/parser.y"
+#line 661 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_CONTEXTHANDLE, 0 ); }
-#line 4284 "tools/widl/parser.tab.c"
+#line 4286 "tools/widl/parser.tab.c"
     break;
 
   case 124: /* attribute: tCONTEXTHANDLENOSERIALIZE  */
-#line 660 "tools/widl/parser.y"
+#line 662 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_CONTEXTHANDLE, 0 ); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
-#line 4290 "tools/widl/parser.tab.c"
+#line 4292 "tools/widl/parser.tab.c"
     break;
 
   case 125: /* attribute: tCONTEXTHANDLESERIALIZE  */
-#line 661 "tools/widl/parser.y"
+#line 663 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_CONTEXTHANDLE, 0 ); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
-#line 4296 "tools/widl/parser.tab.c"
+#line 4298 "tools/widl/parser.tab.c"
     break;
 
   case 126: /* attribute: tCONTRACT '(' contract_req ')'  */
-#line 662 "tools/widl/parser.y"
+#line 664 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_CONTRACT, (yyvsp[-1].expr) ); }
-#line 4302 "tools/widl/parser.tab.c"
+#line 4304 "tools/widl/parser.tab.c"
     break;
 
   case 127: /* attribute: tCONTRACTVERSION '(' contract_ver ')'  */
-#line 663 "tools/widl/parser.y"
-                                                { (yyval.attr) = attr_int( (yyloc), ATTR_CONTRACTVERSION, (yyvsp[-1].num) ); }
-#line 4308 "tools/widl/parser.tab.c"
+#line 665 "tools/widl/parser.y"
+                                                { (yyval.attr) = attr_ptr( (yyloc), ATTR_CONTRACTVERSION, (yyvsp[-1].version) ); }
+#line 4310 "tools/widl/parser.tab.c"
     break;
 
   case 128: /* attribute: tCONTROL  */
-#line 664 "tools/widl/parser.y"
+#line 666 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_CONTROL, 0 ); }
-#line 4314 "tools/widl/parser.tab.c"
+#line 4316 "tools/widl/parser.tab.c"
     break;
 
   case 129: /* attribute: tCUSTOM '(' aUUID ',' expr_const ')'  */
-#line 665 "tools/widl/parser.y"
+#line 667 "tools/widl/parser.y"
                                                 { attr_custdata_t *data = xmalloc( sizeof(*data) );
                                                   data->id = *(yyvsp[-3].uuid); data->pval = (yyvsp[-1].expr);
                                                   (yyval.attr) = attr_ptr( (yyloc), ATTR_CUSTOM, data );
                                                 }
-#line 4323 "tools/widl/parser.tab.c"
+#line 4325 "tools/widl/parser.tab.c"
     break;
 
   case 130: /* attribute: tDECODE  */
-#line 669 "tools/widl/parser.y"
+#line 671 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DECODE, 0 ); }
-#line 4329 "tools/widl/parser.tab.c"
+#line 4331 "tools/widl/parser.tab.c"
     break;
 
   case 131: /* attribute: tDEFAULT  */
-#line 670 "tools/widl/parser.y"
+#line 672 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DEFAULT, 0 ); }
-#line 4335 "tools/widl/parser.tab.c"
+#line 4337 "tools/widl/parser.tab.c"
     break;
 
   case 132: /* attribute: tDEFAULT_OVERLOAD  */
-#line 671 "tools/widl/parser.y"
+#line 673 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DEFAULT_OVERLOAD, 0 ); }
-#line 4341 "tools/widl/parser.tab.c"
+#line 4343 "tools/widl/parser.tab.c"
     break;
 
   case 133: /* attribute: tDEFAULTBIND  */
-#line 672 "tools/widl/parser.y"
+#line 674 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DEFAULTBIND, 0 ); }
-#line 4347 "tools/widl/parser.tab.c"
+#line 4349 "tools/widl/parser.tab.c"
     break;
 
   case 134: /* attribute: tDEFAULTCOLLELEM  */
-#line 673 "tools/widl/parser.y"
+#line 675 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DEFAULTCOLLELEM, 0 ); }
-#line 4353 "tools/widl/parser.tab.c"
+#line 4355 "tools/widl/parser.tab.c"
     break;
 
   case 135: /* attribute: tDEFAULTVALUE '(' expr_const ')'  */
-#line 674 "tools/widl/parser.y"
+#line 676 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_DEFAULTVALUE, (yyvsp[-1].expr) ); }
-#line 4359 "tools/widl/parser.tab.c"
+#line 4361 "tools/widl/parser.tab.c"
     break;
 
   case 136: /* attribute: tDEFAULTVTABLE  */
-#line 675 "tools/widl/parser.y"
+#line 677 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DEFAULTVTABLE, 0 ); }
-#line 4365 "tools/widl/parser.tab.c"
+#line 4367 "tools/widl/parser.tab.c"
     break;
 
   case 137: /* attribute: tDEPRECATED '(' deprecated_attr ')'  */
-#line 676 "tools/widl/parser.y"
+#line 678 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_DEPRECATED, (yyvsp[-1].expr) ); }
-#line 4371 "tools/widl/parser.tab.c"
+#line 4373 "tools/widl/parser.tab.c"
     break;
 
   case 138: /* attribute: tDISABLECONSISTENCYCHECK  */
-#line 677 "tools/widl/parser.y"
+#line 679 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DISABLECONSISTENCYCHECK, 0 ); }
-#line 4377 "tools/widl/parser.tab.c"
+#line 4379 "tools/widl/parser.tab.c"
     break;
 
   case 139: /* attribute: tDISPLAYBIND  */
-#line 678 "tools/widl/parser.y"
+#line 680 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DISPLAYBIND, 0 ); }
-#line 4383 "tools/widl/parser.tab.c"
+#line 4385 "tools/widl/parser.tab.c"
     break;
 
   case 140: /* attribute: tDLLNAME '(' aSTRING ')'  */
-#line 679 "tools/widl/parser.y"
+#line 681 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_DLLNAME, (yyvsp[-1].str) ); }
-#line 4389 "tools/widl/parser.tab.c"
+#line 4391 "tools/widl/parser.tab.c"
     break;
 
   case 141: /* attribute: tDUAL  */
-#line 680 "tools/widl/parser.y"
+#line 682 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DUAL, 0 ); }
-#line 4395 "tools/widl/parser.tab.c"
+#line 4397 "tools/widl/parser.tab.c"
     break;
 
   case 142: /* attribute: tENABLEALLOCATE  */
-#line 681 "tools/widl/parser.y"
+#line 683 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_ENABLEALLOCATE, 0 ); }
-#line 4401 "tools/widl/parser.tab.c"
+#line 4403 "tools/widl/parser.tab.c"
     break;
 
   case 143: /* attribute: tENCODE  */
-#line 682 "tools/widl/parser.y"
+#line 684 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_ENCODE, 0 ); }
-#line 4407 "tools/widl/parser.tab.c"
+#line 4409 "tools/widl/parser.tab.c"
     break;
 
   case 144: /* attribute: tENDPOINT '(' str_list ')'  */
-#line 683 "tools/widl/parser.y"
+#line 685 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_ENDPOINT, (yyvsp[-1].str_list) ); }
-#line 4413 "tools/widl/parser.tab.c"
+#line 4415 "tools/widl/parser.tab.c"
     break;
 
   case 145: /* attribute: tENTRY '(' expr_const ')'  */
-#line 684 "tools/widl/parser.y"
+#line 686 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_ENTRY, (yyvsp[-1].expr) ); }
-#line 4419 "tools/widl/parser.tab.c"
+#line 4421 "tools/widl/parser.tab.c"
     break;
 
   case 146: /* attribute: tEVENTADD  */
-#line 685 "tools/widl/parser.y"
+#line 687 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_EVENTADD, 0 ); }
-#line 4425 "tools/widl/parser.tab.c"
+#line 4427 "tools/widl/parser.tab.c"
     break;
 
   case 147: /* attribute: tEVENTREMOVE  */
-#line 686 "tools/widl/parser.y"
+#line 688 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_EVENTREMOVE, 0 ); }
-#line 4431 "tools/widl/parser.tab.c"
+#line 4433 "tools/widl/parser.tab.c"
     break;
 
   case 148: /* attribute: tEXCLUSIVETO '(' decl_spec ')'  */
-#line 687 "tools/widl/parser.y"
+#line 689 "tools/widl/parser.y"
                                                 { if ((yyvsp[-1].declspec)->type->type_type != TYPE_RUNTIMECLASS)
                                                       error_loc( "type %s is not a runtimeclass\n", (yyvsp[-1].declspec)->type->name );
                                                   (yyval.attr) = attr_ptr( (yyloc), ATTR_EXCLUSIVETO, (yyvsp[-1].declspec)->type );
                                                 }
-#line 4440 "tools/widl/parser.tab.c"
+#line 4442 "tools/widl/parser.tab.c"
     break;
 
   case 149: /* attribute: tEXPLICITHANDLE  */
-#line 691 "tools/widl/parser.y"
+#line 693 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_EXPLICIT_HANDLE, 0 ); }
-#line 4446 "tools/widl/parser.tab.c"
+#line 4448 "tools/widl/parser.tab.c"
     break;
 
   case 150: /* attribute: tFAULTSTATUS  */
-#line 692 "tools/widl/parser.y"
+#line 694 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_FAULTSTATUS, 0 ); }
-#line 4452 "tools/widl/parser.tab.c"
+#line 4454 "tools/widl/parser.tab.c"
     break;
 
   case 151: /* attribute: tFLAGS  */
-#line 693 "tools/widl/parser.y"
+#line 695 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_FLAGS, 0 ); }
-#line 4458 "tools/widl/parser.tab.c"
+#line 4460 "tools/widl/parser.tab.c"
     break;
 
   case 152: /* attribute: tFORCEALLOCATE  */
-#line 694 "tools/widl/parser.y"
+#line 696 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_FORCEALLOCATE, 0 ); }
-#line 4464 "tools/widl/parser.tab.c"
+#line 4466 "tools/widl/parser.tab.c"
     break;
 
   case 153: /* attribute: tHANDLE  */
-#line 695 "tools/widl/parser.y"
+#line 697 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_HANDLE, 0 ); }
-#line 4470 "tools/widl/parser.tab.c"
+#line 4472 "tools/widl/parser.tab.c"
     break;
 
   case 154: /* attribute: tHELPCONTEXT '(' expr_int_const ')'  */
-#line 696 "tools/widl/parser.y"
+#line 698 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_HELPCONTEXT, (yyvsp[-1].expr) ); }
-#line 4476 "tools/widl/parser.tab.c"
+#line 4478 "tools/widl/parser.tab.c"
     break;
 
   case 155: /* attribute: tHELPFILE '(' aSTRING ')'  */
-#line 697 "tools/widl/parser.y"
+#line 699 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_HELPFILE, (yyvsp[-1].str) ); }
-#line 4482 "tools/widl/parser.tab.c"
+#line 4484 "tools/widl/parser.tab.c"
     break;
 
   case 156: /* attribute: tHELPSTRING '(' aSTRING ')'  */
-#line 698 "tools/widl/parser.y"
+#line 700 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_HELPSTRING, (yyvsp[-1].str) ); }
-#line 4488 "tools/widl/parser.tab.c"
+#line 4490 "tools/widl/parser.tab.c"
     break;
 
   case 157: /* attribute: tHELPSTRINGCONTEXT '(' expr_int_const ')'  */
-#line 700 "tools/widl/parser.y"
+#line 702 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_HELPSTRINGCONTEXT, (yyvsp[-1].expr) ); }
-#line 4494 "tools/widl/parser.tab.c"
+#line 4496 "tools/widl/parser.tab.c"
     break;
 
   case 158: /* attribute: tHELPSTRINGDLL '(' aSTRING ')'  */
-#line 701 "tools/widl/parser.y"
+#line 703 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_HELPSTRINGDLL, (yyvsp[-1].str) ); }
-#line 4500 "tools/widl/parser.tab.c"
+#line 4502 "tools/widl/parser.tab.c"
     break;
 
   case 159: /* attribute: tHIDDEN  */
-#line 702 "tools/widl/parser.y"
+#line 704 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_HIDDEN, 0 ); }
-#line 4506 "tools/widl/parser.tab.c"
+#line 4508 "tools/widl/parser.tab.c"
     break;
 
   case 160: /* attribute: tID '(' expr_int_const ')'  */
-#line 703 "tools/widl/parser.y"
+#line 705 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_ID, (yyvsp[-1].expr) ); }
-#line 4512 "tools/widl/parser.tab.c"
+#line 4514 "tools/widl/parser.tab.c"
     break;
 
   case 161: /* attribute: tIDEMPOTENT  */
-#line 704 "tools/widl/parser.y"
+#line 706 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_IDEMPOTENT, 0 ); }
-#line 4518 "tools/widl/parser.tab.c"
+#line 4520 "tools/widl/parser.tab.c"
     break;
 
   case 162: /* attribute: tIGNORE  */
-#line 705 "tools/widl/parser.y"
+#line 707 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_IGNORE, 0 ); }
-#line 4524 "tools/widl/parser.tab.c"
+#line 4526 "tools/widl/parser.tab.c"
     break;
 
   case 163: /* attribute: tIIDIS '(' expr ')'  */
-#line 706 "tools/widl/parser.y"
+#line 708 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_IIDIS, (yyvsp[-1].expr) ); }
-#line 4530 "tools/widl/parser.tab.c"
+#line 4532 "tools/widl/parser.tab.c"
     break;
 
   case 164: /* attribute: tIMMEDIATEBIND  */
-#line 707 "tools/widl/parser.y"
+#line 709 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_IMMEDIATEBIND, 0 ); }
-#line 4536 "tools/widl/parser.tab.c"
+#line 4538 "tools/widl/parser.tab.c"
     break;
 
   case 165: /* attribute: tIMPLICITHANDLE '(' arg ')'  */
-#line 708 "tools/widl/parser.y"
+#line 710 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_IMPLICIT_HANDLE, (yyvsp[-1].var) ); }
-#line 4542 "tools/widl/parser.tab.c"
+#line 4544 "tools/widl/parser.tab.c"
     break;
 
   case 166: /* attribute: tIN  */
-#line 709 "tools/widl/parser.y"
+#line 711 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_IN, 0 ); }
-#line 4548 "tools/widl/parser.tab.c"
+#line 4550 "tools/widl/parser.tab.c"
     break;
 
   case 167: /* attribute: tINPUTSYNC  */
-#line 710 "tools/widl/parser.y"
+#line 712 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_INPUTSYNC, 0 ); }
-#line 4554 "tools/widl/parser.tab.c"
+#line 4556 "tools/widl/parser.tab.c"
     break;
 
   case 168: /* attribute: tLENGTHIS '(' m_exprs ')'  */
-#line 711 "tools/widl/parser.y"
+#line 713 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_LENGTHIS, (yyvsp[-1].expr_list) ); }
-#line 4560 "tools/widl/parser.tab.c"
+#line 4562 "tools/widl/parser.tab.c"
     break;
 
   case 169: /* attribute: tLCID '(' expr_int_const ')'  */
-#line 712 "tools/widl/parser.y"
+#line 714 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_LIBLCID, (yyvsp[-1].expr) ); }
-#line 4566 "tools/widl/parser.tab.c"
+#line 4568 "tools/widl/parser.tab.c"
     break;
 
   case 170: /* attribute: tLCID  */
-#line 713 "tools/widl/parser.y"
+#line 715 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PARAMLCID, 0 ); }
-#line 4572 "tools/widl/parser.tab.c"
+#line 4574 "tools/widl/parser.tab.c"
     break;
 
   case 171: /* attribute: tLICENSED  */
-#line 714 "tools/widl/parser.y"
+#line 716 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_LICENSED, 0 ); }
-#line 4578 "tools/widl/parser.tab.c"
+#line 4580 "tools/widl/parser.tab.c"
     break;
 
   case 172: /* attribute: tLOCAL  */
-#line 715 "tools/widl/parser.y"
+#line 717 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_LOCAL, 0 ); }
-#line 4584 "tools/widl/parser.tab.c"
+#line 4586 "tools/widl/parser.tab.c"
     break;
 
   case 173: /* attribute: tMARSHALINGBEHAVIOR '(' marshaling_behavior ')'  */
-#line 717 "tools/widl/parser.y"
+#line 719 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_MARSHALING_BEHAVIOR, (yyvsp[-1].num) ); }
-#line 4590 "tools/widl/parser.tab.c"
+#line 4592 "tools/widl/parser.tab.c"
     break;
 
   case 174: /* attribute: tMAYBE  */
-#line 718 "tools/widl/parser.y"
+#line 720 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_MAYBE, 0 ); }
-#line 4596 "tools/widl/parser.tab.c"
+#line 4598 "tools/widl/parser.tab.c"
     break;
 
   case 175: /* attribute: tMESSAGE  */
-#line 719 "tools/widl/parser.y"
+#line 721 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_MESSAGE, 0 ); }
-#line 4602 "tools/widl/parser.tab.c"
+#line 4604 "tools/widl/parser.tab.c"
     break;
 
   case 176: /* attribute: tNOCODE  */
-#line 720 "tools/widl/parser.y"
+#line 722 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_NOCODE, 0 ); }
-#line 4608 "tools/widl/parser.tab.c"
+#line 4610 "tools/widl/parser.tab.c"
     break;
 
   case 177: /* attribute: tNONBROWSABLE  */
-#line 721 "tools/widl/parser.y"
+#line 723 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_NONBROWSABLE, 0 ); }
-#line 4614 "tools/widl/parser.tab.c"
+#line 4616 "tools/widl/parser.tab.c"
     break;
 
   case 178: /* attribute: tNONCREATABLE  */
-#line 722 "tools/widl/parser.y"
+#line 724 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_NONCREATABLE, 0 ); }
-#line 4620 "tools/widl/parser.tab.c"
+#line 4622 "tools/widl/parser.tab.c"
     break;
 
   case 179: /* attribute: tNONEXTENSIBLE  */
-#line 723 "tools/widl/parser.y"
+#line 725 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_NONEXTENSIBLE, 0 ); }
-#line 4626 "tools/widl/parser.tab.c"
+#line 4628 "tools/widl/parser.tab.c"
     break;
 
   case 180: /* attribute: tNOTIFY  */
-#line 724 "tools/widl/parser.y"
+#line 726 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_NOTIFY, 0 ); }
-#line 4632 "tools/widl/parser.tab.c"
+#line 4634 "tools/widl/parser.tab.c"
     break;
 
   case 181: /* attribute: tNOTIFYFLAG  */
-#line 725 "tools/widl/parser.y"
+#line 727 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_NOTIFYFLAG, 0 ); }
-#line 4638 "tools/widl/parser.tab.c"
+#line 4640 "tools/widl/parser.tab.c"
     break;
 
   case 182: /* attribute: tOBJECT  */
-#line 726 "tools/widl/parser.y"
+#line 728 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_OBJECT, 0 ); }
-#line 4644 "tools/widl/parser.tab.c"
+#line 4646 "tools/widl/parser.tab.c"
     break;
 
   case 183: /* attribute: tODL  */
-#line 727 "tools/widl/parser.y"
+#line 729 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_ODL, 0 ); }
-#line 4650 "tools/widl/parser.tab.c"
+#line 4652 "tools/widl/parser.tab.c"
     break;
 
   case 184: /* attribute: tOLEAUTOMATION  */
-#line 728 "tools/widl/parser.y"
+#line 730 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_OLEAUTOMATION, 0 ); }
-#line 4656 "tools/widl/parser.tab.c"
+#line 4658 "tools/widl/parser.tab.c"
     break;
 
   case 185: /* attribute: tOPTIMIZE '(' aSTRING ')'  */
-#line 729 "tools/widl/parser.y"
+#line 731 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_OPTIMIZE, (yyvsp[-1].str) ); }
-#line 4662 "tools/widl/parser.tab.c"
+#line 4664 "tools/widl/parser.tab.c"
     break;
 
   case 186: /* attribute: tOPTIONAL  */
-#line 730 "tools/widl/parser.y"
+#line 732 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_OPTIONAL, 0 ); }
-#line 4668 "tools/widl/parser.tab.c"
+#line 4670 "tools/widl/parser.tab.c"
     break;
 
   case 187: /* attribute: tOUT  */
-#line 731 "tools/widl/parser.y"
+#line 733 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_OUT, 0 ); }
-#line 4674 "tools/widl/parser.tab.c"
+#line 4676 "tools/widl/parser.tab.c"
     break;
 
   case 188: /* attribute: tOVERLOAD '(' aSTRING ')'  */
-#line 732 "tools/widl/parser.y"
+#line 734 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_OVERLOAD, (yyvsp[-1].str) ); }
-#line 4680 "tools/widl/parser.tab.c"
+#line 4682 "tools/widl/parser.tab.c"
     break;
 
   case 189: /* attribute: tPARTIALIGNORE  */
-#line 733 "tools/widl/parser.y"
+#line 735 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PARTIALIGNORE, 0 ); }
-#line 4686 "tools/widl/parser.tab.c"
+#line 4688 "tools/widl/parser.tab.c"
     break;
 
   case 190: /* attribute: tPOINTERDEFAULT '(' pointer_type ')'  */
-#line 734 "tools/widl/parser.y"
+#line 736 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_POINTERDEFAULT, (yyvsp[-1].num) ); }
-#line 4692 "tools/widl/parser.tab.c"
+#line 4694 "tools/widl/parser.tab.c"
     break;
 
   case 191: /* attribute: tPROGID '(' aSTRING ')'  */
-#line 735 "tools/widl/parser.y"
+#line 737 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_PROGID, (yyvsp[-1].str) ); }
-#line 4698 "tools/widl/parser.tab.c"
+#line 4700 "tools/widl/parser.tab.c"
     break;
 
   case 192: /* attribute: tPROPGET  */
-#line 736 "tools/widl/parser.y"
+#line 738 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PROPGET, 0 ); }
-#line 4704 "tools/widl/parser.tab.c"
+#line 4706 "tools/widl/parser.tab.c"
     break;
 
   case 193: /* attribute: tPROPPUT  */
-#line 737 "tools/widl/parser.y"
+#line 739 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PROPPUT, 0 ); }
-#line 4710 "tools/widl/parser.tab.c"
+#line 4712 "tools/widl/parser.tab.c"
     break;
 
   case 194: /* attribute: tPROPPUTREF  */
-#line 738 "tools/widl/parser.y"
+#line 740 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PROPPUTREF, 0 ); }
-#line 4716 "tools/widl/parser.tab.c"
+#line 4718 "tools/widl/parser.tab.c"
     break;
 
   case 195: /* attribute: tPROTECTED  */
-#line 739 "tools/widl/parser.y"
+#line 741 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PROTECTED, 0 ); }
-#line 4722 "tools/widl/parser.tab.c"
+#line 4724 "tools/widl/parser.tab.c"
     break;
 
   case 196: /* attribute: tPROXY  */
-#line 740 "tools/widl/parser.y"
+#line 742 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PROXY, 0 ); }
-#line 4728 "tools/widl/parser.tab.c"
+#line 4730 "tools/widl/parser.tab.c"
     break;
 
   case 197: /* attribute: tPUBLIC  */
-#line 741 "tools/widl/parser.y"
+#line 743 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_PUBLIC, 0 ); }
-#line 4734 "tools/widl/parser.tab.c"
+#line 4736 "tools/widl/parser.tab.c"
     break;
 
   case 198: /* attribute: tRANGE '(' expr_int_const ',' expr_int_const ')'  */
-#line 743 "tools/widl/parser.y"
+#line 745 "tools/widl/parser.y"
                                                 { expr_list_t *list = append_expr( NULL, (yyvsp[-3].expr) );
                                                   list = append_expr( list, (yyvsp[-1].expr) );
                                                   (yyval.attr) = attr_ptr( (yyloc), ATTR_RANGE, list );
                                                 }
-#line 4743 "tools/widl/parser.tab.c"
+#line 4745 "tools/widl/parser.tab.c"
     break;
 
   case 199: /* attribute: tREADONLY  */
-#line 747 "tools/widl/parser.y"
+#line 749 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_READONLY, 0 ); }
-#line 4749 "tools/widl/parser.tab.c"
+#line 4751 "tools/widl/parser.tab.c"
     break;
 
   case 200: /* attribute: tREPRESENTAS '(' type ')'  */
-#line 748 "tools/widl/parser.y"
+#line 750 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_REPRESENTAS, (yyvsp[-1].type) ); }
-#line 4755 "tools/widl/parser.tab.c"
+#line 4757 "tools/widl/parser.tab.c"
     break;
 
   case 201: /* attribute: tREQUESTEDIT  */
-#line 749 "tools/widl/parser.y"
+#line 751 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_REQUESTEDIT, 0 ); }
-#line 4761 "tools/widl/parser.tab.c"
+#line 4763 "tools/widl/parser.tab.c"
     break;
 
   case 202: /* attribute: tRESTRICTED  */
-#line 750 "tools/widl/parser.y"
+#line 752 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_RESTRICTED, 0 ); }
-#line 4767 "tools/widl/parser.tab.c"
+#line 4769 "tools/widl/parser.tab.c"
     break;
 
   case 203: /* attribute: tRETVAL  */
-#line 751 "tools/widl/parser.y"
+#line 753 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_RETVAL, 0 ); }
-#line 4773 "tools/widl/parser.tab.c"
+#line 4775 "tools/widl/parser.tab.c"
     break;
 
   case 204: /* attribute: tSIZEIS '(' m_exprs ')'  */
-#line 752 "tools/widl/parser.y"
+#line 754 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_SIZEIS, (yyvsp[-1].expr_list) ); }
-#line 4779 "tools/widl/parser.tab.c"
+#line 4781 "tools/widl/parser.tab.c"
     break;
 
   case 205: /* attribute: tSOURCE  */
-#line 753 "tools/widl/parser.y"
+#line 755 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_SOURCE, 0 ); }
-#line 4785 "tools/widl/parser.tab.c"
+#line 4787 "tools/widl/parser.tab.c"
     break;
 
   case 206: /* attribute: tSTATIC '(' static_attr ')'  */
-#line 754 "tools/widl/parser.y"
+#line 756 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_STATIC, (yyvsp[-1].expr) ); }
-#line 4791 "tools/widl/parser.tab.c"
+#line 4793 "tools/widl/parser.tab.c"
     break;
 
   case 207: /* attribute: tSTRICTCONTEXTHANDLE  */
-#line 755 "tools/widl/parser.y"
+#line 757 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_STRICTCONTEXTHANDLE, 0 ); }
-#line 4797 "tools/widl/parser.tab.c"
+#line 4799 "tools/widl/parser.tab.c"
     break;
 
   case 208: /* attribute: tSTRING  */
-#line 756 "tools/widl/parser.y"
+#line 758 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_STRING, 0 ); }
-#line 4803 "tools/widl/parser.tab.c"
+#line 4805 "tools/widl/parser.tab.c"
     break;
 
   case 209: /* attribute: tSWITCHIS '(' expr ')'  */
-#line 757 "tools/widl/parser.y"
+#line 759 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_SWITCHIS, (yyvsp[-1].expr) ); }
-#line 4809 "tools/widl/parser.tab.c"
+#line 4811 "tools/widl/parser.tab.c"
     break;
 
   case 210: /* attribute: tSWITCHTYPE '(' type ')'  */
-#line 758 "tools/widl/parser.y"
+#line 760 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_SWITCHTYPE, (yyvsp[-1].type) ); }
-#line 4815 "tools/widl/parser.tab.c"
+#line 4817 "tools/widl/parser.tab.c"
     break;
 
   case 211: /* attribute: tTRANSMITAS '(' type ')'  */
-#line 759 "tools/widl/parser.y"
+#line 761 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_TRANSMITAS, (yyvsp[-1].type) ); }
-#line 4821 "tools/widl/parser.tab.c"
+#line 4823 "tools/widl/parser.tab.c"
     break;
 
   case 212: /* attribute: tTHREADING '(' threading_type ')'  */
-#line 760 "tools/widl/parser.y"
+#line 762 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_THREADING, (yyvsp[-1].num) ); }
-#line 4827 "tools/widl/parser.tab.c"
+#line 4829 "tools/widl/parser.tab.c"
     break;
 
   case 213: /* attribute: tUIDEFAULT  */
-#line 761 "tools/widl/parser.y"
+#line 763 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_UIDEFAULT, 0 ); }
-#line 4833 "tools/widl/parser.tab.c"
+#line 4835 "tools/widl/parser.tab.c"
     break;
 
   case 214: /* attribute: tUSESGETLASTERROR  */
-#line 762 "tools/widl/parser.y"
+#line 764 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_USESGETLASTERROR, 0 ); }
-#line 4839 "tools/widl/parser.tab.c"
+#line 4841 "tools/widl/parser.tab.c"
     break;
 
   case 215: /* attribute: tUSERMARSHAL '(' type ')'  */
-#line 763 "tools/widl/parser.y"
+#line 765 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_USERMARSHAL, (yyvsp[-1].type) ); }
-#line 4845 "tools/widl/parser.tab.c"
+#line 4847 "tools/widl/parser.tab.c"
     break;
 
   case 216: /* attribute: tUUID '(' aUUID ')'  */
-#line 764 "tools/widl/parser.y"
+#line 766 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_UUID, (yyvsp[-1].uuid) ); }
-#line 4851 "tools/widl/parser.tab.c"
+#line 4853 "tools/widl/parser.tab.c"
     break;
 
   case 217: /* attribute: tASYNCUUID '(' aUUID ')'  */
-#line 765 "tools/widl/parser.y"
+#line 767 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_ASYNCUUID, (yyvsp[-1].uuid) ); }
-#line 4857 "tools/widl/parser.tab.c"
+#line 4859 "tools/widl/parser.tab.c"
     break;
 
   case 218: /* attribute: tV1ENUM  */
-#line 766 "tools/widl/parser.y"
+#line 768 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_V1ENUM, 0 ); }
-#line 4863 "tools/widl/parser.tab.c"
+#line 4865 "tools/widl/parser.tab.c"
     break;
 
   case 219: /* attribute: tVARARG  */
-#line 767 "tools/widl/parser.y"
+#line 769 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_VARARG, 0 ); }
-#line 4869 "tools/widl/parser.tab.c"
+#line 4871 "tools/widl/parser.tab.c"
     break;
 
   case 220: /* attribute: tVERSION '(' version ')'  */
-#line 768 "tools/widl/parser.y"
-                                                { (yyval.attr) = attr_int( (yyloc), ATTR_VERSION, (yyvsp[-1].num) ); }
-#line 4875 "tools/widl/parser.tab.c"
+#line 770 "tools/widl/parser.y"
+                                                { (yyval.attr) = attr_ptr( (yyloc), ATTR_VERSION, (yyvsp[-1].version) ); }
+#line 4877 "tools/widl/parser.tab.c"
     break;
 
   case 221: /* attribute: tVIPROGID '(' aSTRING ')'  */
-#line 769 "tools/widl/parser.y"
+#line 771 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_VIPROGID, (yyvsp[-1].str) ); }
-#line 4881 "tools/widl/parser.tab.c"
+#line 4883 "tools/widl/parser.tab.c"
     break;
 
   case 222: /* attribute: tWIREMARSHAL '(' type ')'  */
-#line 770 "tools/widl/parser.y"
+#line 772 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_ptr( (yyloc), ATTR_WIREMARSHAL, (yyvsp[-1].type) ); }
-#line 4887 "tools/widl/parser.tab.c"
+#line 4889 "tools/widl/parser.tab.c"
     break;
 
   case 223: /* attribute: pointer_type  */
-#line 771 "tools/widl/parser.y"
+#line 773 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_POINTERTYPE, (yyvsp[0].num) ); }
-#line 4893 "tools/widl/parser.tab.c"
+#line 4895 "tools/widl/parser.tab.c"
     break;
 
   case 228: /* cases: %empty  */
-#line 781 "tools/widl/parser.y"
+#line 783 "tools/widl/parser.y"
                                                 { (yyval.var_list) = NULL; }
-#line 4899 "tools/widl/parser.tab.c"
+#line 4901 "tools/widl/parser.tab.c"
     break;
 
   case 229: /* cases: cases case  */
-#line 782 "tools/widl/parser.y"
+#line 784 "tools/widl/parser.y"
                                                 { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); }
-#line 4905 "tools/widl/parser.tab.c"
+#line 4907 "tools/widl/parser.tab.c"
     break;
 
   case 230: /* case: tCASE expr_int_const ':' union_field  */
-#line 785 "tools/widl/parser.y"
+#line 787 "tools/widl/parser.y"
                                                 { attr_t *a = attr_ptr( (yyloc), ATTR_CASE, append_expr( NULL, (yyvsp[-2].expr) ) );
                                                   (yyval.var) = (yyvsp[0].var); if (!(yyval.var)) (yyval.var) = make_var( NULL );
                                                   (yyval.var)->attrs = append_attr( (yyval.var)->attrs, a );
                                                 }
-#line 4914 "tools/widl/parser.tab.c"
+#line 4916 "tools/widl/parser.tab.c"
     break;
 
   case 231: /* case: tDEFAULT ':' union_field  */
-#line 789 "tools/widl/parser.y"
+#line 791 "tools/widl/parser.y"
                                                 { attr_t *a = attr_int( (yyloc), ATTR_DEFAULT, 0 );
                                                   (yyval.var) = (yyvsp[0].var); if (!(yyval.var)) (yyval.var) = make_var( NULL );
                                                   (yyval.var)->attrs = append_attr( (yyval.var)->attrs, a );
                                                 }
-#line 4923 "tools/widl/parser.tab.c"
+#line 4925 "tools/widl/parser.tab.c"
     break;
 
   case 232: /* enums: %empty  */
-#line 796 "tools/widl/parser.y"
+#line 798 "tools/widl/parser.y"
                                                 { (yyval.var_list) = NULL; }
-#line 4929 "tools/widl/parser.tab.c"
+#line 4931 "tools/widl/parser.tab.c"
     break;
 
   case 233: /* enums: enum_list ','  */
-#line 797 "tools/widl/parser.y"
+#line 799 "tools/widl/parser.y"
                                                 { (yyval.var_list) = (yyvsp[-1].var_list); }
-#line 4935 "tools/widl/parser.tab.c"
+#line 4937 "tools/widl/parser.tab.c"
     break;
 
   case 235: /* enum_list: enum  */
-#line 801 "tools/widl/parser.y"
+#line 803 "tools/widl/parser.y"
                                                 {
                                                   struct integer integer = {.value = 0};
                                                   if (!(yyvsp[0].var)->eval)
                                                     (yyvsp[0].var)->eval = make_exprl(EXPR_NUM, &integer);
                                                   (yyval.var_list) = append_var( NULL, (yyvsp[0].var) );
                                                 }
-#line 4946 "tools/widl/parser.tab.c"
+#line 4948 "tools/widl/parser.tab.c"
     break;
 
   case 236: /* enum_list: enum_list ',' enum  */
-#line 807 "tools/widl/parser.y"
+#line 809 "tools/widl/parser.y"
                                                 {
                                                   if (!(yyvsp[0].var)->eval)
                                                   {
@@ -4962,904 +4964,904 @@
                                                   }
                                                   (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var) );
                                                 }
-#line 4966 "tools/widl/parser.tab.c"
+#line 4968 "tools/widl/parser.tab.c"
     break;
 
   case 237: /* enum_member: m_attributes ident  */
-#line 824 "tools/widl/parser.y"
+#line 826 "tools/widl/parser.y"
                                                 { (yyval.var) = (yyvsp[0].var);
 						  (yyval.var)->attrs = check_enum_member_attrs((yyvsp[-1].attr_list));
 						}
-#line 4974 "tools/widl/parser.tab.c"
+#line 4976 "tools/widl/parser.tab.c"
     break;
 
   case 238: /* enum: enum_member '=' expr_int_const  */
-#line 829 "tools/widl/parser.y"
+#line 831 "tools/widl/parser.y"
                                                 { (yyval.var) = reg_const((yyvsp[-2].var));
 						  (yyval.var)->eval = (yyvsp[0].expr);
                                                   (yyval.var)->declspec.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
-#line 4983 "tools/widl/parser.tab.c"
+#line 4985 "tools/widl/parser.tab.c"
     break;
 
   case 239: /* enum: enum_member  */
-#line 833 "tools/widl/parser.y"
+#line 835 "tools/widl/parser.y"
                                                 { (yyval.var) = reg_const((yyvsp[0].var));
                                                   (yyval.var)->declspec.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
-#line 4991 "tools/widl/parser.tab.c"
+#line 4993 "tools/widl/parser.tab.c"
     break;
 
   case 240: /* enumdef: tENUM m_typename '{' enums '}'  */
-#line 838 "tools/widl/parser.y"
+#line 840 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_enum((yyvsp[-3].str), current_namespace, TRUE, (yyvsp[-1].var_list), &(yylsp[-3])); }
-#line 4997 "tools/widl/parser.tab.c"
+#line 4999 "tools/widl/parser.tab.c"
     break;
 
   case 241: /* m_exprs: m_expr  */
-#line 841 "tools/widl/parser.y"
+#line 843 "tools/widl/parser.y"
                                                 { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); }
-#line 5003 "tools/widl/parser.tab.c"
+#line 5005 "tools/widl/parser.tab.c"
     break;
 
   case 242: /* m_exprs: m_exprs ',' m_expr  */
-#line 842 "tools/widl/parser.y"
+#line 844 "tools/widl/parser.y"
                                                 { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); }
-#line 5009 "tools/widl/parser.tab.c"
+#line 5011 "tools/widl/parser.tab.c"
     break;
 
   case 243: /* m_expr: %empty  */
-#line 846 "tools/widl/parser.y"
+#line 848 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr(EXPR_VOID); }
-#line 5015 "tools/widl/parser.tab.c"
+#line 5017 "tools/widl/parser.tab.c"
     break;
 
   case 245: /* expr: aNUM  */
-#line 850 "tools/widl/parser.y"
+#line 852 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprl(EXPR_NUM, &(yyvsp[0].integer)); }
-#line 5021 "tools/widl/parser.tab.c"
+#line 5023 "tools/widl/parser.tab.c"
     break;
 
   case 246: /* expr: aHEXNUM  */
-#line 851 "tools/widl/parser.y"
+#line 853 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprl(EXPR_NUM, &(yyvsp[0].integer)); }
-#line 5027 "tools/widl/parser.tab.c"
+#line 5029 "tools/widl/parser.tab.c"
     break;
 
   case 247: /* expr: aDOUBLE  */
-#line 852 "tools/widl/parser.y"
+#line 854 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprd(EXPR_DOUBLE, (yyvsp[0].dbl)); }
-#line 5033 "tools/widl/parser.tab.c"
+#line 5035 "tools/widl/parser.tab.c"
     break;
 
   case 248: /* expr: tFALSE  */
-#line 853 "tools/widl/parser.y"
+#line 855 "tools/widl/parser.y"
                                                 { struct integer integer = {.value = 0};
                                                   (yyval.expr) = make_exprl(EXPR_TRUEFALSE, &integer); }
-#line 5040 "tools/widl/parser.tab.c"
+#line 5042 "tools/widl/parser.tab.c"
     break;
 
   case 249: /* expr: tNULL  */
-#line 855 "tools/widl/parser.y"
+#line 857 "tools/widl/parser.y"
                                                 { struct integer integer = {.value = 0};
                                                   (yyval.expr) = make_exprl(EXPR_NUM, &integer); }
-#line 5047 "tools/widl/parser.tab.c"
+#line 5049 "tools/widl/parser.tab.c"
     break;
 
   case 250: /* expr: tTRUE  */
-#line 857 "tools/widl/parser.y"
+#line 859 "tools/widl/parser.y"
                                                 { struct integer integer = {.value = 1};
                                                   (yyval.expr) = make_exprl(EXPR_TRUEFALSE, &integer); }
-#line 5054 "tools/widl/parser.tab.c"
+#line 5056 "tools/widl/parser.tab.c"
     break;
 
   case 251: /* expr: aSTRING  */
-#line 859 "tools/widl/parser.y"
+#line 861 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprs(EXPR_STRLIT, (yyvsp[0].str)); }
-#line 5060 "tools/widl/parser.tab.c"
+#line 5062 "tools/widl/parser.tab.c"
     break;
 
   case 252: /* expr: aWSTRING  */
-#line 860 "tools/widl/parser.y"
+#line 862 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprs(EXPR_WSTRLIT, (yyvsp[0].str)); }
-#line 5066 "tools/widl/parser.tab.c"
+#line 5068 "tools/widl/parser.tab.c"
     break;
 
   case 253: /* expr: aSQSTRING  */
-#line 861 "tools/widl/parser.y"
+#line 863 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprs(EXPR_CHARCONST, (yyvsp[0].str)); }
-#line 5072 "tools/widl/parser.tab.c"
+#line 5074 "tools/widl/parser.tab.c"
     break;
 
   case 254: /* expr: aIDENTIFIER  */
-#line 862 "tools/widl/parser.y"
+#line 864 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str)); }
-#line 5078 "tools/widl/parser.tab.c"
+#line 5080 "tools/widl/parser.tab.c"
     break;
 
   case 255: /* expr: expr '?' expr ':' expr  */
-#line 863 "tools/widl/parser.y"
+#line 865 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr3(EXPR_COND, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5084 "tools/widl/parser.tab.c"
+#line 5086 "tools/widl/parser.tab.c"
     break;
 
   case 256: /* expr: expr LOGICALOR expr  */
-#line 864 "tools/widl/parser.y"
+#line 866 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_LOGOR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5090 "tools/widl/parser.tab.c"
+#line 5092 "tools/widl/parser.tab.c"
     break;
 
   case 257: /* expr: expr LOGICALAND expr  */
-#line 865 "tools/widl/parser.y"
+#line 867 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_LOGAND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5096 "tools/widl/parser.tab.c"
+#line 5098 "tools/widl/parser.tab.c"
     break;
 
   case 258: /* expr: expr '|' expr  */
-#line 866 "tools/widl/parser.y"
+#line 868 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_OR , (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5102 "tools/widl/parser.tab.c"
+#line 5104 "tools/widl/parser.tab.c"
     break;
 
   case 259: /* expr: expr '^' expr  */
-#line 867 "tools/widl/parser.y"
+#line 869 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_XOR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5108 "tools/widl/parser.tab.c"
+#line 5110 "tools/widl/parser.tab.c"
     break;
 
   case 260: /* expr: expr '&' expr  */
-#line 868 "tools/widl/parser.y"
+#line 870 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5114 "tools/widl/parser.tab.c"
+#line 5116 "tools/widl/parser.tab.c"
     break;
 
   case 261: /* expr: expr EQUALITY expr  */
-#line 869 "tools/widl/parser.y"
+#line 871 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_EQUALITY, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5120 "tools/widl/parser.tab.c"
+#line 5122 "tools/widl/parser.tab.c"
     break;
 
   case 262: /* expr: expr INEQUALITY expr  */
-#line 870 "tools/widl/parser.y"
+#line 872 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_INEQUALITY, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5126 "tools/widl/parser.tab.c"
+#line 5128 "tools/widl/parser.tab.c"
     break;
 
   case 263: /* expr: expr '>' expr  */
-#line 871 "tools/widl/parser.y"
+#line 873 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_GTR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5132 "tools/widl/parser.tab.c"
+#line 5134 "tools/widl/parser.tab.c"
     break;
 
   case 264: /* expr: expr '<' expr  */
-#line 872 "tools/widl/parser.y"
+#line 874 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_LESS, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5138 "tools/widl/parser.tab.c"
+#line 5140 "tools/widl/parser.tab.c"
     break;
 
   case 265: /* expr: expr GREATEREQUAL expr  */
-#line 873 "tools/widl/parser.y"
+#line 875 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_GTREQL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5144 "tools/widl/parser.tab.c"
+#line 5146 "tools/widl/parser.tab.c"
     break;
 
   case 266: /* expr: expr LESSEQUAL expr  */
-#line 874 "tools/widl/parser.y"
+#line 876 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_LESSEQL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5150 "tools/widl/parser.tab.c"
+#line 5152 "tools/widl/parser.tab.c"
     break;
 
   case 267: /* expr: expr SHL expr  */
-#line 875 "tools/widl/parser.y"
+#line 877 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_SHL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5156 "tools/widl/parser.tab.c"
+#line 5158 "tools/widl/parser.tab.c"
     break;
 
   case 268: /* expr: expr SHR expr  */
-#line 876 "tools/widl/parser.y"
+#line 878 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_SHR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5162 "tools/widl/parser.tab.c"
+#line 5164 "tools/widl/parser.tab.c"
     break;
 
   case 269: /* expr: expr '+' expr  */
-#line 877 "tools/widl/parser.y"
+#line 879 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_ADD, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5168 "tools/widl/parser.tab.c"
+#line 5170 "tools/widl/parser.tab.c"
     break;
 
   case 270: /* expr: expr '-' expr  */
-#line 878 "tools/widl/parser.y"
+#line 880 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_SUB, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5174 "tools/widl/parser.tab.c"
+#line 5176 "tools/widl/parser.tab.c"
     break;
 
   case 271: /* expr: expr '%' expr  */
-#line 879 "tools/widl/parser.y"
+#line 881 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_MOD, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5180 "tools/widl/parser.tab.c"
+#line 5182 "tools/widl/parser.tab.c"
     break;
 
   case 272: /* expr: expr '*' expr  */
-#line 880 "tools/widl/parser.y"
+#line 882 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_MUL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5186 "tools/widl/parser.tab.c"
+#line 5188 "tools/widl/parser.tab.c"
     break;
 
   case 273: /* expr: expr '/' expr  */
-#line 881 "tools/widl/parser.y"
+#line 883 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_DIV, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 5192 "tools/widl/parser.tab.c"
+#line 5194 "tools/widl/parser.tab.c"
     break;
 
   case 274: /* expr: '!' expr  */
-#line 882 "tools/widl/parser.y"
+#line 884 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr1(EXPR_LOGNOT, (yyvsp[0].expr)); }
-#line 5198 "tools/widl/parser.tab.c"
+#line 5200 "tools/widl/parser.tab.c"
     break;
 
   case 275: /* expr: '~' expr  */
-#line 883 "tools/widl/parser.y"
+#line 885 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr1(EXPR_NOT, (yyvsp[0].expr)); }
-#line 5204 "tools/widl/parser.tab.c"
+#line 5206 "tools/widl/parser.tab.c"
     break;
 
   case 276: /* expr: '+' expr  */
-#line 884 "tools/widl/parser.y"
+#line 886 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr1(EXPR_POS, (yyvsp[0].expr)); }
-#line 5210 "tools/widl/parser.tab.c"
+#line 5212 "tools/widl/parser.tab.c"
     break;
 
   case 277: /* expr: '-' expr  */
-#line 885 "tools/widl/parser.y"
+#line 887 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr1(EXPR_NEG, (yyvsp[0].expr)); }
-#line 5216 "tools/widl/parser.tab.c"
+#line 5218 "tools/widl/parser.tab.c"
     break;
 
   case 278: /* expr: '&' expr  */
-#line 886 "tools/widl/parser.y"
+#line 888 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr1(EXPR_ADDRESSOF, (yyvsp[0].expr)); }
-#line 5222 "tools/widl/parser.tab.c"
+#line 5224 "tools/widl/parser.tab.c"
     break;
 
   case 279: /* expr: '*' expr  */
-#line 887 "tools/widl/parser.y"
+#line 889 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr1(EXPR_PPTR, (yyvsp[0].expr)); }
-#line 5228 "tools/widl/parser.tab.c"
+#line 5230 "tools/widl/parser.tab.c"
     break;
 
   case 280: /* expr: expr MEMBERPTR aIDENTIFIER  */
-#line 888 "tools/widl/parser.y"
+#line 890 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_MEMBER, make_expr1(EXPR_PPTR, (yyvsp[-2].expr)), make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str))); }
-#line 5234 "tools/widl/parser.tab.c"
+#line 5236 "tools/widl/parser.tab.c"
     break;
 
   case 281: /* expr: expr '.' aIDENTIFIER  */
-#line 889 "tools/widl/parser.y"
+#line 891 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_MEMBER, (yyvsp[-2].expr), make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str))); }
-#line 5240 "tools/widl/parser.tab.c"
+#line 5242 "tools/widl/parser.tab.c"
     break;
 
   case 282: /* expr: '(' unqualified_decl_spec m_abstract_declarator ')' expr  */
-#line 891 "tools/widl/parser.y"
+#line 893 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprt(EXPR_CAST, declare_var(NULL, (yyvsp[-3].declspec), (yyvsp[-2].declarator), 0), (yyvsp[0].expr)); free((yyvsp[-3].declspec)); free((yyvsp[-2].declarator)); }
-#line 5246 "tools/widl/parser.tab.c"
+#line 5248 "tools/widl/parser.tab.c"
     break;
 
   case 283: /* expr: tSIZEOF '(' unqualified_decl_spec m_abstract_declarator ')'  */
-#line 893 "tools/widl/parser.y"
+#line 895 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_exprt(EXPR_SIZEOF, declare_var(NULL, (yyvsp[-2].declspec), (yyvsp[-1].declarator), 0), NULL); free((yyvsp[-2].declspec)); free((yyvsp[-1].declarator)); }
-#line 5252 "tools/widl/parser.tab.c"
+#line 5254 "tools/widl/parser.tab.c"
     break;
 
   case 284: /* expr: expr '[' expr ']'  */
-#line 894 "tools/widl/parser.y"
+#line 896 "tools/widl/parser.y"
                                                 { (yyval.expr) = make_expr2(EXPR_ARRAY, (yyvsp[-3].expr), (yyvsp[-1].expr)); }
-#line 5258 "tools/widl/parser.tab.c"
+#line 5260 "tools/widl/parser.tab.c"
     break;
 
   case 285: /* expr: '(' expr ')'  */
-#line 895 "tools/widl/parser.y"
+#line 897 "tools/widl/parser.y"
                                                 { (yyval.expr) = (yyvsp[-1].expr); }
-#line 5264 "tools/widl/parser.tab.c"
+#line 5266 "tools/widl/parser.tab.c"
     break;
 
   case 286: /* expr_list_int_const: expr_int_const  */
-#line 898 "tools/widl/parser.y"
+#line 900 "tools/widl/parser.y"
                                                 { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); }
-#line 5270 "tools/widl/parser.tab.c"
+#line 5272 "tools/widl/parser.tab.c"
     break;
 
   case 287: /* expr_list_int_const: expr_list_int_const ',' expr_int_const  */
-#line 899 "tools/widl/parser.y"
+#line 901 "tools/widl/parser.y"
                                                         { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); }
-#line 5276 "tools/widl/parser.tab.c"
+#line 5278 "tools/widl/parser.tab.c"
     break;
 
   case 288: /* expr_int_const: expr  */
-#line 902 "tools/widl/parser.y"
+#line 904 "tools/widl/parser.y"
                                                 { (yyval.expr) = (yyvsp[0].expr);
 						  if (!(yyval.expr)->is_const)
 						      error_loc("expression is not an integer constant\n");
 						}
-#line 5285 "tools/widl/parser.tab.c"
+#line 5287 "tools/widl/parser.tab.c"
     break;
 
   case 289: /* expr_const: expr  */
-#line 908 "tools/widl/parser.y"
+#line 910 "tools/widl/parser.y"
                                                 { (yyval.expr) = (yyvsp[0].expr);
 						  if (!(yyval.expr)->is_const && (yyval.expr)->type != EXPR_STRLIT && (yyval.expr)->type != EXPR_WSTRLIT)
 						      error_loc("expression is not constant\n");
 						}
-#line 5294 "tools/widl/parser.tab.c"
+#line 5296 "tools/widl/parser.tab.c"
     break;
 
   case 290: /* fields: %empty  */
-#line 915 "tools/widl/parser.y"
+#line 917 "tools/widl/parser.y"
                                                 { (yyval.var_list) = NULL; }
-#line 5300 "tools/widl/parser.tab.c"
+#line 5302 "tools/widl/parser.tab.c"
     break;
 
   case 291: /* fields: fields field  */
-#line 916 "tools/widl/parser.y"
+#line 918 "tools/widl/parser.y"
                                                 { (yyval.var_list) = append_var_list((yyvsp[-1].var_list), (yyvsp[0].var_list)); }
-#line 5306 "tools/widl/parser.tab.c"
+#line 5308 "tools/widl/parser.tab.c"
     break;
 
   case 292: /* field: m_attributes decl_spec struct_declarator_list ';'  */
-#line 920 "tools/widl/parser.y"
+#line 922 "tools/widl/parser.y"
                                                 { const char *first = LIST_ENTRY(list_head((yyvsp[-1].declarator_list)), declarator_t, entry)->var->name;
 						  check_field_attrs(first, (yyvsp[-3].attr_list));
 						  (yyval.var_list) = set_var_types((yyvsp[-3].attr_list), (yyvsp[-2].declspec), (yyvsp[-1].declarator_list));
 						}
-#line 5315 "tools/widl/parser.tab.c"
+#line 5317 "tools/widl/parser.tab.c"
     break;
 
   case 293: /* field: m_attributes uniondef ';'  */
-#line 924 "tools/widl/parser.y"
+#line 926 "tools/widl/parser.y"
                                                 { var_t *v = make_var(NULL);
 						  v->declspec.type = (yyvsp[-1].type); v->attrs = (yyvsp[-2].attr_list);
 						  (yyval.var_list) = append_var(NULL, v);
 						}
-#line 5324 "tools/widl/parser.tab.c"
+#line 5326 "tools/widl/parser.tab.c"
     break;
 
   case 294: /* ne_union_field: s_field ';'  */
-#line 931 "tools/widl/parser.y"
+#line 933 "tools/widl/parser.y"
                                                 { (yyval.var) = (yyvsp[-1].var); }
-#line 5330 "tools/widl/parser.tab.c"
+#line 5332 "tools/widl/parser.tab.c"
     break;
 
   case 295: /* ne_union_field: attributes ';'  */
-#line 932 "tools/widl/parser.y"
+#line 934 "tools/widl/parser.y"
                                                 { (yyval.var) = make_var(NULL); (yyval.var)->attrs = (yyvsp[-1].attr_list); }
-#line 5336 "tools/widl/parser.tab.c"
+#line 5338 "tools/widl/parser.tab.c"
     break;
 
   case 296: /* ne_union_fields: %empty  */
-#line 936 "tools/widl/parser.y"
+#line 938 "tools/widl/parser.y"
                                                 { (yyval.var_list) = NULL; }
-#line 5342 "tools/widl/parser.tab.c"
+#line 5344 "tools/widl/parser.tab.c"
     break;
 
   case 297: /* ne_union_fields: ne_union_fields ne_union_field  */
-#line 937 "tools/widl/parser.y"
+#line 939 "tools/widl/parser.y"
                                                 { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); }
-#line 5348 "tools/widl/parser.tab.c"
+#line 5350 "tools/widl/parser.tab.c"
     break;
 
   case 298: /* union_field: s_field ';'  */
-#line 941 "tools/widl/parser.y"
+#line 943 "tools/widl/parser.y"
                                                 { (yyval.var) = (yyvsp[-1].var); }
-#line 5354 "tools/widl/parser.tab.c"
+#line 5356 "tools/widl/parser.tab.c"
     break;
 
   case 299: /* union_field: ';'  */
-#line 942 "tools/widl/parser.y"
+#line 944 "tools/widl/parser.y"
                                                 { (yyval.var) = NULL; }
-#line 5360 "tools/widl/parser.tab.c"
+#line 5362 "tools/widl/parser.tab.c"
     break;
 
   case 300: /* s_field: m_attributes decl_spec declarator  */
-#line 945 "tools/widl/parser.y"
+#line 947 "tools/widl/parser.y"
                                                 { (yyval.var) = declare_var(check_field_attrs((yyvsp[0].declarator)->var->name, (yyvsp[-2].attr_list)),
 						                (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE);
 						  free((yyvsp[0].declarator));
 						}
-#line 5369 "tools/widl/parser.tab.c"
+#line 5371 "tools/widl/parser.tab.c"
     break;
 
   case 301: /* s_field: m_attributes structdef  */
-#line 949 "tools/widl/parser.y"
+#line 951 "tools/widl/parser.y"
                                                 { var_t *v = make_var(NULL);
 						  v->declspec.type = (yyvsp[0].type); v->attrs = (yyvsp[-1].attr_list);
 						  (yyval.var) = v;
 						}
-#line 5378 "tools/widl/parser.tab.c"
+#line 5380 "tools/widl/parser.tab.c"
     break;
 
   case 302: /* funcdef: declaration  */
-#line 955 "tools/widl/parser.y"
+#line 957 "tools/widl/parser.y"
                                                 { (yyval.var) = (yyvsp[0].var);
 						  if (type_get_type((yyval.var)->declspec.type) != TYPE_FUNCTION)
 						    error_loc("only methods may be declared inside the methods section of a dispinterface\n");
 						  check_function_attrs((yyval.var)->name, (yyval.var)->attrs);
 						}
-#line 5388 "tools/widl/parser.tab.c"
+#line 5390 "tools/widl/parser.tab.c"
     break;
 
   case 303: /* declaration: attributes decl_spec init_declarator  */
-#line 964 "tools/widl/parser.y"
+#line 966 "tools/widl/parser.y"
                                                 { (yyval.var) = declare_var((yyvsp[-2].attr_list), (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE);
 						  free((yyvsp[0].declarator));
 						}
-#line 5396 "tools/widl/parser.tab.c"
+#line 5398 "tools/widl/parser.tab.c"
     break;
 
   case 304: /* declaration: decl_spec init_declarator  */
-#line 967 "tools/widl/parser.y"
+#line 969 "tools/widl/parser.y"
                                                 { (yyval.var) = declare_var(NULL, (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE);
 						  free((yyvsp[0].declarator));
 						}
-#line 5404 "tools/widl/parser.tab.c"
+#line 5406 "tools/widl/parser.tab.c"
     break;
 
   case 305: /* m_ident: %empty  */
-#line 973 "tools/widl/parser.y"
+#line 975 "tools/widl/parser.y"
                                                 { (yyval.var) = NULL; }
-#line 5410 "tools/widl/parser.tab.c"
+#line 5412 "tools/widl/parser.tab.c"
     break;
 
   case 307: /* m_typename: %empty  */
-#line 978 "tools/widl/parser.y"
+#line 980 "tools/widl/parser.y"
                                                 { (yyval.str) = NULL; }
-#line 5416 "tools/widl/parser.tab.c"
+#line 5418 "tools/widl/parser.tab.c"
     break;
 
   case 311: /* ident: typename  */
-#line 986 "tools/widl/parser.y"
+#line 988 "tools/widl/parser.y"
                                                 { (yyval.var) = make_var((yyvsp[0].str)); }
-#line 5422 "tools/widl/parser.tab.c"
+#line 5424 "tools/widl/parser.tab.c"
     break;
 
   case 312: /* base_type: tBYTE  */
-#line 989 "tools/widl/parser.y"
+#line 991 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error( NULL, "byte" ); }
-#line 5428 "tools/widl/parser.tab.c"
+#line 5430 "tools/widl/parser.tab.c"
     break;
 
   case 313: /* base_type: tWCHAR  */
-#line 990 "tools/widl/parser.y"
+#line 992 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error( NULL, "wchar_t" ); }
-#line 5434 "tools/widl/parser.tab.c"
+#line 5436 "tools/widl/parser.tab.c"
     break;
 
   case 315: /* base_type: tSIGNED int_std  */
-#line 992 "tools/widl/parser.y"
+#line 994 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(type_basic_get_type((yyvsp[0].type)), -1); }
-#line 5440 "tools/widl/parser.tab.c"
+#line 5442 "tools/widl/parser.tab.c"
     break;
 
   case 316: /* base_type: tUNSIGNED int_std  */
-#line 993 "tools/widl/parser.y"
+#line 995 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(type_basic_get_type((yyvsp[0].type)), 1); }
-#line 5446 "tools/widl/parser.tab.c"
+#line 5448 "tools/widl/parser.tab.c"
     break;
 
   case 317: /* base_type: tUNSIGNED  */
-#line 994 "tools/widl/parser.y"
+#line 996 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_INT, 1); }
-#line 5452 "tools/widl/parser.tab.c"
+#line 5454 "tools/widl/parser.tab.c"
     break;
 
   case 318: /* base_type: tFLOAT  */
-#line 995 "tools/widl/parser.y"
+#line 997 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error( NULL, "float" ); }
-#line 5458 "tools/widl/parser.tab.c"
+#line 5460 "tools/widl/parser.tab.c"
     break;
 
   case 319: /* base_type: tDOUBLE  */
-#line 996 "tools/widl/parser.y"
+#line 998 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error( NULL, "double" ); }
-#line 5464 "tools/widl/parser.tab.c"
+#line 5466 "tools/widl/parser.tab.c"
     break;
 
   case 320: /* base_type: tBOOLEAN  */
-#line 997 "tools/widl/parser.y"
+#line 999 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error( NULL, "boolean" ); }
-#line 5470 "tools/widl/parser.tab.c"
+#line 5472 "tools/widl/parser.tab.c"
     break;
 
   case 321: /* base_type: tERRORSTATUST  */
-#line 998 "tools/widl/parser.y"
+#line 1000 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error( NULL, "error_status_t" ); }
-#line 5476 "tools/widl/parser.tab.c"
+#line 5478 "tools/widl/parser.tab.c"
     break;
 
   case 322: /* base_type: tHANDLET  */
-#line 999 "tools/widl/parser.y"
+#line 1001 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error( NULL, "handle_t" ); }
-#line 5482 "tools/widl/parser.tab.c"
+#line 5484 "tools/widl/parser.tab.c"
     break;
 
   case 325: /* int_std: tINT  */
-#line 1007 "tools/widl/parser.y"
+#line 1009 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_INT, 0); }
-#line 5488 "tools/widl/parser.tab.c"
+#line 5490 "tools/widl/parser.tab.c"
     break;
 
   case 326: /* int_std: tSHORT m_int  */
-#line 1008 "tools/widl/parser.y"
+#line 1010 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_INT16, 0); }
-#line 5494 "tools/widl/parser.tab.c"
+#line 5496 "tools/widl/parser.tab.c"
     break;
 
   case 327: /* int_std: tSMALL  */
-#line 1009 "tools/widl/parser.y"
+#line 1011 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_INT8, 0); }
-#line 5500 "tools/widl/parser.tab.c"
+#line 5502 "tools/widl/parser.tab.c"
     break;
 
   case 328: /* int_std: tLONG m_int  */
-#line 1010 "tools/widl/parser.y"
+#line 1012 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_LONG, 0); }
-#line 5506 "tools/widl/parser.tab.c"
+#line 5508 "tools/widl/parser.tab.c"
     break;
 
   case 329: /* int_std: tHYPER m_int  */
-#line 1011 "tools/widl/parser.y"
+#line 1013 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_HYPER, 0); }
-#line 5512 "tools/widl/parser.tab.c"
+#line 5514 "tools/widl/parser.tab.c"
     break;
 
   case 330: /* int_std: tINT64  */
-#line 1012 "tools/widl/parser.y"
+#line 1014 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_INT64, 0); }
-#line 5518 "tools/widl/parser.tab.c"
+#line 5520 "tools/widl/parser.tab.c"
     break;
 
   case 331: /* int_std: tCHAR  */
-#line 1013 "tools/widl/parser.y"
+#line 1015 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_CHAR, 0); }
-#line 5524 "tools/widl/parser.tab.c"
+#line 5526 "tools/widl/parser.tab.c"
     break;
 
   case 332: /* int_std: tINT32  */
-#line 1014 "tools/widl/parser.y"
+#line 1016 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_INT32, 0); }
-#line 5530 "tools/widl/parser.tab.c"
+#line 5532 "tools/widl/parser.tab.c"
     break;
 
   case 333: /* int_std: tINT3264  */
-#line 1015 "tools/widl/parser.y"
+#line 1017 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_int(TYPE_BASIC_INT3264, 0); }
-#line 5536 "tools/widl/parser.tab.c"
+#line 5538 "tools/widl/parser.tab.c"
     break;
 
   case 334: /* namespace_pfx: aIDENTIFIER '.'  */
-#line 1019 "tools/widl/parser.y"
+#line 1021 "tools/widl/parser.y"
                                                 { (yyval.namespace) = find_namespace_or_error(&global_namespace, (yyvsp[-1].str)); }
-#line 5542 "tools/widl/parser.tab.c"
+#line 5544 "tools/widl/parser.tab.c"
     break;
 
   case 335: /* namespace_pfx: namespace_pfx aIDENTIFIER '.'  */
-#line 1020 "tools/widl/parser.y"
+#line 1022 "tools/widl/parser.y"
                                                 { (yyval.namespace) = find_namespace_or_error((yyvsp[-2].namespace), (yyvsp[-1].str)); }
-#line 5548 "tools/widl/parser.tab.c"
+#line 5550 "tools/widl/parser.tab.c"
     break;
 
   case 336: /* qualified_type: typename  */
-#line 1024 "tools/widl/parser.y"
+#line 1026 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error(current_namespace, (yyvsp[0].str)); }
-#line 5554 "tools/widl/parser.tab.c"
+#line 5556 "tools/widl/parser.tab.c"
     break;
 
   case 337: /* qualified_type: namespace_pfx typename  */
-#line 1025 "tools/widl/parser.y"
+#line 1027 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error((yyvsp[-1].namespace), (yyvsp[0].str)); }
-#line 5560 "tools/widl/parser.tab.c"
+#line 5562 "tools/widl/parser.tab.c"
     break;
 
   case 338: /* parameterized_type: qualified_type '<' parameterized_type_args '>'  */
-#line 1029 "tools/widl/parser.y"
+#line 1031 "tools/widl/parser.y"
                                                 { (yyval.type) = find_parameterized_type((yyvsp[-3].type), (yyvsp[-1].typeref_list)); }
-#line 5566 "tools/widl/parser.tab.c"
+#line 5568 "tools/widl/parser.tab.c"
     break;
 
   case 339: /* parameterized_type_arg: base_type  */
-#line 1033 "tools/widl/parser.y"
+#line 1035 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 5572 "tools/widl/parser.tab.c"
+#line 5574 "tools/widl/parser.tab.c"
     break;
 
   case 340: /* parameterized_type_arg: qualified_type  */
-#line 1034 "tools/widl/parser.y"
+#line 1036 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 5578 "tools/widl/parser.tab.c"
+#line 5580 "tools/widl/parser.tab.c"
     break;
 
   case 341: /* parameterized_type_arg: qualified_type '*'  */
-#line 1035 "tools/widl/parser.y"
+#line 1037 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_pointer((yyvsp[-1].type)); }
-#line 5584 "tools/widl/parser.tab.c"
+#line 5586 "tools/widl/parser.tab.c"
     break;
 
   case 342: /* parameterized_type_arg: parameterized_type  */
-#line 1036 "tools/widl/parser.y"
+#line 1038 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 5590 "tools/widl/parser.tab.c"
+#line 5592 "tools/widl/parser.tab.c"
     break;
 
   case 343: /* parameterized_type_arg: parameterized_type '*'  */
-#line 1037 "tools/widl/parser.y"
+#line 1039 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_pointer((yyvsp[-1].type)); }
-#line 5596 "tools/widl/parser.tab.c"
+#line 5598 "tools/widl/parser.tab.c"
     break;
 
   case 344: /* parameterized_type_args: parameterized_type_arg  */
-#line 1041 "tools/widl/parser.y"
+#line 1043 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref(NULL, make_typeref((yyvsp[0].type))); }
-#line 5602 "tools/widl/parser.tab.c"
+#line 5604 "tools/widl/parser.tab.c"
     break;
 
   case 345: /* parameterized_type_args: parameterized_type_args ',' parameterized_type_arg  */
-#line 1043 "tools/widl/parser.y"
+#line 1045 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref((yyvsp[-2].typeref_list), make_typeref((yyvsp[0].type))); }
-#line 5608 "tools/widl/parser.tab.c"
+#line 5610 "tools/widl/parser.tab.c"
     break;
 
   case 346: /* coclass: tCOCLASS typename  */
-#line 1046 "tools/widl/parser.y"
+#line 1048 "tools/widl/parser.y"
                                                 { (yyval.type) = type_coclass_declare((yyvsp[0].str)); }
-#line 5614 "tools/widl/parser.tab.c"
+#line 5616 "tools/widl/parser.tab.c"
     break;
 
   case 347: /* coclassdef: attributes coclass '{' class_interfaces '}' semicolon_opt  */
-#line 1050 "tools/widl/parser.y"
+#line 1052 "tools/widl/parser.y"
                                                 { (yyval.type) = type_coclass_define((yyvsp[-4].type), (yyvsp[-5].attr_list), (yyvsp[-2].typeref_list), &(yylsp[-4])); }
-#line 5620 "tools/widl/parser.tab.c"
+#line 5622 "tools/widl/parser.tab.c"
     break;
 
   case 348: /* runtimeclass: tRUNTIMECLASS typename  */
-#line 1053 "tools/widl/parser.y"
+#line 1055 "tools/widl/parser.y"
                                                 { (yyval.type) = type_runtimeclass_declare((yyvsp[0].str), current_namespace); }
-#line 5626 "tools/widl/parser.tab.c"
+#line 5628 "tools/widl/parser.tab.c"
     break;
 
   case 349: /* runtimeclass_def: attributes runtimeclass inherit '{' class_interfaces '}' semicolon_opt  */
-#line 1057 "tools/widl/parser.y"
+#line 1059 "tools/widl/parser.y"
                                                 { if ((yyvsp[-4].type) && type_get_type((yyvsp[-4].type)) != TYPE_RUNTIMECLASS) error_loc("%s is not a runtimeclass\n", (yyvsp[-4].type)->name);
 						  (yyval.type) = type_runtimeclass_define((yyvsp[-5].type), (yyvsp[-6].attr_list), (yyvsp[-2].typeref_list), &(yylsp[-5])); }
-#line 5633 "tools/widl/parser.tab.c"
+#line 5635 "tools/widl/parser.tab.c"
     break;
 
   case 350: /* apicontract: tAPICONTRACT typename  */
-#line 1061 "tools/widl/parser.y"
+#line 1063 "tools/widl/parser.y"
                                                 { (yyval.type) = type_apicontract_declare((yyvsp[0].str), current_namespace); }
-#line 5639 "tools/widl/parser.tab.c"
+#line 5641 "tools/widl/parser.tab.c"
     break;
 
   case 351: /* apicontract_def: attributes apicontract '{' '}' semicolon_opt  */
-#line 1065 "tools/widl/parser.y"
+#line 1067 "tools/widl/parser.y"
                                                 { (yyval.type) = type_apicontract_define((yyvsp[-3].type), (yyvsp[-4].attr_list), &(yylsp[-3])); }
-#line 5645 "tools/widl/parser.tab.c"
+#line 5647 "tools/widl/parser.tab.c"
     break;
 
   case 352: /* namespacedef: tNAMESPACE aIDENTIFIER  */
-#line 1068 "tools/widl/parser.y"
+#line 1070 "tools/widl/parser.y"
                                                 { (yyval.str_list) = append_str( NULL, (yyvsp[0].str) ); }
-#line 5651 "tools/widl/parser.tab.c"
+#line 5653 "tools/widl/parser.tab.c"
     break;
 
   case 353: /* namespacedef: namespacedef '.' aIDENTIFIER  */
-#line 1069 "tools/widl/parser.y"
+#line 1071 "tools/widl/parser.y"
                                                 { (yyval.str_list) = append_str( (yyvsp[-2].str_list), (yyvsp[0].str) ); }
-#line 5657 "tools/widl/parser.tab.c"
+#line 5659 "tools/widl/parser.tab.c"
     break;
 
   case 354: /* class_interfaces: %empty  */
-#line 1073 "tools/widl/parser.y"
+#line 1075 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = NULL; }
-#line 5663 "tools/widl/parser.tab.c"
+#line 5665 "tools/widl/parser.tab.c"
     break;
 
   case 355: /* class_interfaces: class_interfaces class_interface  */
-#line 1074 "tools/widl/parser.y"
+#line 1076 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref( (yyvsp[-1].typeref_list), (yyvsp[0].typeref) ); }
-#line 5669 "tools/widl/parser.tab.c"
+#line 5671 "tools/widl/parser.tab.c"
     break;
 
   case 356: /* class_interface: m_attributes interfaceref ';'  */
-#line 1078 "tools/widl/parser.y"
+#line 1080 "tools/widl/parser.y"
                                                 { (yyval.typeref) = make_typeref((yyvsp[-1].type)); (yyval.typeref)->attrs = (yyvsp[-2].attr_list); }
-#line 5675 "tools/widl/parser.tab.c"
+#line 5677 "tools/widl/parser.tab.c"
     break;
 
   case 357: /* class_interface: m_attributes dispinterfaceref ';'  */
-#line 1079 "tools/widl/parser.y"
+#line 1081 "tools/widl/parser.y"
                                                 { (yyval.typeref) = make_typeref((yyvsp[-1].type)); (yyval.typeref)->attrs = (yyvsp[-2].attr_list); }
-#line 5681 "tools/widl/parser.tab.c"
+#line 5683 "tools/widl/parser.tab.c"
     break;
 
   case 358: /* dispinterface: tDISPINTERFACE typename  */
-#line 1082 "tools/widl/parser.y"
+#line 1084 "tools/widl/parser.y"
                                                 { (yyval.type) = type_dispinterface_declare((yyvsp[0].str)); }
-#line 5687 "tools/widl/parser.tab.c"
+#line 5689 "tools/widl/parser.tab.c"
     break;
 
   case 359: /* dispattributes: attributes  */
-#line 1085 "tools/widl/parser.y"
+#line 1087 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = append_attr( (yyvsp[0].attr_list), attr_int( (yyloc), ATTR_DISPINTERFACE, 0 ) ); }
-#line 5693 "tools/widl/parser.tab.c"
+#line 5695 "tools/widl/parser.tab.c"
     break;
 
   case 360: /* dispint_props: tPROPERTIES ':'  */
-#line 1088 "tools/widl/parser.y"
+#line 1090 "tools/widl/parser.y"
                                                 { (yyval.var_list) = NULL; }
-#line 5699 "tools/widl/parser.tab.c"
+#line 5701 "tools/widl/parser.tab.c"
     break;
 
   case 361: /* dispint_props: dispint_props s_field ';'  */
-#line 1089 "tools/widl/parser.y"
+#line 1091 "tools/widl/parser.y"
                                                 { (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[-1].var) ); }
-#line 5705 "tools/widl/parser.tab.c"
+#line 5707 "tools/widl/parser.tab.c"
     break;
 
   case 362: /* dispint_meths: tMETHODS ':'  */
-#line 1092 "tools/widl/parser.y"
+#line 1094 "tools/widl/parser.y"
                                                 { (yyval.var_list) = NULL; }
-#line 5711 "tools/widl/parser.tab.c"
+#line 5713 "tools/widl/parser.tab.c"
     break;
 
   case 363: /* dispint_meths: dispint_meths funcdef ';'  */
-#line 1093 "tools/widl/parser.y"
+#line 1095 "tools/widl/parser.y"
                                                 { (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[-1].var) ); }
-#line 5717 "tools/widl/parser.tab.c"
+#line 5719 "tools/widl/parser.tab.c"
     break;
 
   case 364: /* dispinterfacedef: dispattributes dispinterface '{' dispint_props dispint_meths '}'  */
-#line 1098 "tools/widl/parser.y"
+#line 1100 "tools/widl/parser.y"
                                                 { (yyval.type) = type_dispinterface_define((yyvsp[-4].type), (yyvsp[-5].attr_list), (yyvsp[-2].var_list), (yyvsp[-1].var_list), &(yylsp[-4])); }
-#line 5723 "tools/widl/parser.tab.c"
+#line 5725 "tools/widl/parser.tab.c"
     break;
 
   case 365: /* dispinterfacedef: dispattributes dispinterface '{' interface ';' '}'  */
-#line 1100 "tools/widl/parser.y"
+#line 1102 "tools/widl/parser.y"
                                                 { (yyval.type) = type_dispinterface_define_from_iface((yyvsp[-4].type), (yyvsp[-5].attr_list), (yyvsp[-2].type), &(yylsp[-4])); }
-#line 5729 "tools/widl/parser.tab.c"
+#line 5731 "tools/widl/parser.tab.c"
     break;
 
   case 366: /* inherit: %empty  */
-#line 1104 "tools/widl/parser.y"
+#line 1106 "tools/widl/parser.y"
                                                 { (yyval.type) = NULL; }
-#line 5735 "tools/widl/parser.tab.c"
+#line 5737 "tools/widl/parser.tab.c"
     break;
 
   case 367: /* inherit: ':' qualified_type  */
-#line 1105 "tools/widl/parser.y"
+#line 1107 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 5741 "tools/widl/parser.tab.c"
+#line 5743 "tools/widl/parser.tab.c"
     break;
 
   case 368: /* inherit: ':' parameterized_type  */
-#line 1106 "tools/widl/parser.y"
+#line 1108 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 5747 "tools/widl/parser.tab.c"
+#line 5749 "tools/widl/parser.tab.c"
     break;
 
   case 369: /* type_parameter: typename  */
-#line 1109 "tools/widl/parser.y"
+#line 1111 "tools/widl/parser.y"
                                                 { (yyval.type) = get_type(TYPE_PARAMETER, (yyvsp[0].str), parameters_namespace, 0); }
-#line 5753 "tools/widl/parser.tab.c"
+#line 5755 "tools/widl/parser.tab.c"
     break;
 
   case 370: /* type_parameters: type_parameter  */
-#line 1113 "tools/widl/parser.y"
+#line 1115 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref(NULL, make_typeref((yyvsp[0].type))); }
-#line 5759 "tools/widl/parser.tab.c"
+#line 5761 "tools/widl/parser.tab.c"
     break;
 
   case 371: /* type_parameters: type_parameters ',' type_parameter  */
-#line 1114 "tools/widl/parser.y"
+#line 1116 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref((yyvsp[-2].typeref_list), make_typeref((yyvsp[0].type))); }
-#line 5765 "tools/widl/parser.tab.c"
+#line 5767 "tools/widl/parser.tab.c"
     break;
 
   case 372: /* interface: tINTERFACE typename  */
-#line 1118 "tools/widl/parser.y"
+#line 1120 "tools/widl/parser.y"
                                                 { (yyval.type) = type_interface_declare((yyvsp[0].str), current_namespace); }
-#line 5771 "tools/widl/parser.tab.c"
+#line 5773 "tools/widl/parser.tab.c"
     break;
 
   case 373: /* $@3: %empty  */
-#line 1119 "tools/widl/parser.y"
+#line 1121 "tools/widl/parser.y"
                                   { push_parameters_namespace((yyvsp[-1].str)); }
-#line 5777 "tools/widl/parser.tab.c"
+#line 5779 "tools/widl/parser.tab.c"
     break;
 
   case 374: /* $@4: %empty  */
-#line 1119 "tools/widl/parser.y"
+#line 1121 "tools/widl/parser.y"
                                                                                      { pop_parameters_namespace((yyvsp[-3].str)); }
-#line 5783 "tools/widl/parser.tab.c"
+#line 5785 "tools/widl/parser.tab.c"
     break;
 
   case 375: /* interface: tINTERFACE typename '<' $@3 type_parameters $@4 '>'  */
-#line 1120 "tools/widl/parser.y"
+#line 1122 "tools/widl/parser.y"
                                                 { (yyval.type) = type_parameterized_interface_declare((yyvsp[-5].str), current_namespace, (yyvsp[-2].typeref_list)); }
-#line 5789 "tools/widl/parser.tab.c"
+#line 5791 "tools/widl/parser.tab.c"
     break;
 
   case 376: /* delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt  */
-#line 1124 "tools/widl/parser.y"
+#line 1126 "tools/widl/parser.y"
                                                 { (yyval.type) = type_delegate_declare((yyvsp[-4].var)->name, current_namespace);
 						  (yyval.type) = type_delegate_define((yyval.type), (yyvsp[-7].attr_list), append_statement(NULL, make_statement_delegate((yyvsp[-5].type), (yyvsp[-2].var_list))), &(yylsp[-4]));
 						}
-#line 5797 "tools/widl/parser.tab.c"
+#line 5799 "tools/widl/parser.tab.c"
     break;
 
   case 377: /* $@5: %empty  */
-#line 1128 "tools/widl/parser.y"
+#line 1130 "tools/widl/parser.y"
               { push_parameters_namespace((yyvsp[-1].var)->name); }
-#line 5803 "tools/widl/parser.tab.c"
+#line 5805 "tools/widl/parser.tab.c"
     break;
 
   case 378: /* $@6: %empty  */
-#line 1129 "tools/widl/parser.y"
+#line 1131 "tools/widl/parser.y"
                          { pop_parameters_namespace((yyvsp[-7].var)->name); }
-#line 5809 "tools/widl/parser.tab.c"
+#line 5811 "tools/widl/parser.tab.c"
     break;
 
   case 379: /* delegatedef: m_attributes tDELEGATE type ident '<' $@5 type_parameters '>' '(' m_args ')' $@6 semicolon_opt  */
-#line 1130 "tools/widl/parser.y"
+#line 1132 "tools/widl/parser.y"
                                                 { (yyval.type) = type_parameterized_delegate_declare((yyvsp[-9].var)->name, current_namespace, (yyvsp[-6].typeref_list));
 						  (yyval.type) = type_parameterized_delegate_define((yyval.type), (yyvsp[-12].attr_list), append_statement(NULL, make_statement_delegate((yyvsp[-10].type), (yyvsp[-3].var_list))), &(yylsp[-9]));
 						}
-#line 5817 "tools/widl/parser.tab.c"
+#line 5819 "tools/widl/parser.tab.c"
     break;
 
   case 380: /* required_types: qualified_type  */
-#line 1136 "tools/widl/parser.y"
+#line 1138 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref(NULL, make_typeref((yyvsp[0].type))); }
-#line 5823 "tools/widl/parser.tab.c"
+#line 5825 "tools/widl/parser.tab.c"
     break;
 
   case 381: /* required_types: parameterized_type  */
-#line 1137 "tools/widl/parser.y"
+#line 1139 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref(NULL, make_typeref((yyvsp[0].type))); }
-#line 5829 "tools/widl/parser.tab.c"
+#line 5831 "tools/widl/parser.tab.c"
     break;
 
   case 382: /* required_types: required_types ',' qualified_type  */
-#line 1138 "tools/widl/parser.y"
+#line 1140 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref((yyvsp[-2].typeref_list), make_typeref((yyvsp[0].type))); }
-#line 5835 "tools/widl/parser.tab.c"
+#line 5837 "tools/widl/parser.tab.c"
     break;
 
   case 383: /* required_types: required_types ',' parameterized_type  */
-#line 1139 "tools/widl/parser.y"
+#line 1141 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = append_typeref((yyvsp[-2].typeref_list), make_typeref((yyvsp[0].type))); }
-#line 5841 "tools/widl/parser.tab.c"
+#line 5843 "tools/widl/parser.tab.c"
     break;
 
   case 384: /* requires: %empty  */
-#line 1143 "tools/widl/parser.y"
+#line 1145 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = NULL; }
-#line 5847 "tools/widl/parser.tab.c"
+#line 5849 "tools/widl/parser.tab.c"
     break;
 
   case 385: /* requires: tREQUIRES required_types  */
-#line 1144 "tools/widl/parser.y"
+#line 1146 "tools/widl/parser.y"
                                                 { (yyval.typeref_list) = (yyvsp[0].typeref_list); }
-#line 5853 "tools/widl/parser.tab.c"
+#line 5855 "tools/widl/parser.tab.c"
     break;
 
   case 386: /* $@7: %empty  */
-#line 1147 "tools/widl/parser.y"
+#line 1149 "tools/widl/parser.y"
                                                 { if ((yyvsp[0].type)->type_type == TYPE_PARAMETERIZED_TYPE) push_parameters_namespace((yyvsp[0].type)->name); }
-#line 5859 "tools/widl/parser.tab.c"
+#line 5861 "tools/widl/parser.tab.c"
     break;
 
   case 387: /* interfacedef: attributes interface $@7 inherit requires '{' int_statements '}' semicolon_opt  */
-#line 1149 "tools/widl/parser.y"
+#line 1151 "tools/widl/parser.y"
                                                 { if ((yyvsp[-7].type)->type_type == TYPE_PARAMETERIZED_TYPE)
 						  {
 						      (yyval.type) = type_parameterized_interface_define((yyvsp[-7].type), (yyvsp[-8].attr_list), (yyvsp[-5].type), (yyvsp[-2].stmt_list), (yyvsp[-4].typeref_list), &(yylsp[-7]));
@@ -5871,643 +5873,643 @@
 						      check_async_uuid((yyval.type));
 						  }
 						}
-#line 5875 "tools/widl/parser.tab.c"
+#line 5877 "tools/widl/parser.tab.c"
     break;
 
   case 388: /* interfacedef: dispinterfacedef semicolon_opt  */
-#line 1160 "tools/widl/parser.y"
+#line 1162 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[-1].type); }
-#line 5881 "tools/widl/parser.tab.c"
+#line 5883 "tools/widl/parser.tab.c"
     break;
 
   case 389: /* interfaceref: tINTERFACE typename  */
-#line 1164 "tools/widl/parser.y"
+#line 1166 "tools/widl/parser.y"
                                                 { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); }
-#line 5887 "tools/widl/parser.tab.c"
+#line 5889 "tools/widl/parser.tab.c"
     break;
 
   case 390: /* interfaceref: tINTERFACE namespace_pfx typename  */
-#line 1165 "tools/widl/parser.y"
+#line 1167 "tools/widl/parser.y"
                                                 { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), (yyvsp[-1].namespace), 0); }
-#line 5893 "tools/widl/parser.tab.c"
+#line 5895 "tools/widl/parser.tab.c"
     break;
 
   case 391: /* interfaceref: tINTERFACE parameterized_type  */
-#line 1166 "tools/widl/parser.y"
+#line 1168 "tools/widl/parser.y"
                                                 { if (type_get_type(((yyval.type) = (yyvsp[0].type))) != TYPE_INTERFACE) error_loc("%s is not an interface\n", (yyval.type)->name); }
-#line 5899 "tools/widl/parser.tab.c"
+#line 5901 "tools/widl/parser.tab.c"
     break;
 
   case 392: /* dispinterfaceref: tDISPINTERFACE typename  */
-#line 1170 "tools/widl/parser.y"
+#line 1172 "tools/widl/parser.y"
                                                 { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); }
-#line 5905 "tools/widl/parser.tab.c"
+#line 5907 "tools/widl/parser.tab.c"
     break;
 
   case 393: /* module: tMODULE typename  */
-#line 1173 "tools/widl/parser.y"
+#line 1175 "tools/widl/parser.y"
                                                 { (yyval.type) = type_module_declare((yyvsp[0].str)); }
-#line 5911 "tools/widl/parser.tab.c"
+#line 5913 "tools/widl/parser.tab.c"
     break;
 
   case 394: /* moduledef: m_attributes module '{' int_statements '}' semicolon_opt  */
-#line 1177 "tools/widl/parser.y"
+#line 1179 "tools/widl/parser.y"
                                                 { (yyval.type) = type_module_define((yyvsp[-4].type), (yyvsp[-5].attr_list), (yyvsp[-2].stmt_list), &(yylsp[-4])); }
-#line 5917 "tools/widl/parser.tab.c"
+#line 5919 "tools/widl/parser.tab.c"
     break;
 
   case 395: /* storage_cls_spec: tEXTERN  */
-#line 1181 "tools/widl/parser.y"
+#line 1183 "tools/widl/parser.y"
                                                 { (yyval.stgclass) = STG_EXTERN; }
-#line 5923 "tools/widl/parser.tab.c"
+#line 5925 "tools/widl/parser.tab.c"
     break;
 
   case 396: /* storage_cls_spec: tSTATIC  */
-#line 1182 "tools/widl/parser.y"
+#line 1184 "tools/widl/parser.y"
                                                 { (yyval.stgclass) = STG_STATIC; }
-#line 5929 "tools/widl/parser.tab.c"
+#line 5931 "tools/widl/parser.tab.c"
     break;
 
   case 397: /* storage_cls_spec: tREGISTER  */
-#line 1183 "tools/widl/parser.y"
+#line 1185 "tools/widl/parser.y"
                                                 { (yyval.stgclass) = STG_REGISTER; }
-#line 5935 "tools/widl/parser.tab.c"
+#line 5937 "tools/widl/parser.tab.c"
     break;
 
   case 398: /* function_specifier: tINLINE  */
-#line 1187 "tools/widl/parser.y"
+#line 1189 "tools/widl/parser.y"
                                                 { (yyval.function_specifier) = FUNCTION_SPECIFIER_INLINE; }
-#line 5941 "tools/widl/parser.tab.c"
+#line 5943 "tools/widl/parser.tab.c"
     break;
 
   case 399: /* type_qualifier: tCONST  */
-#line 1191 "tools/widl/parser.y"
+#line 1193 "tools/widl/parser.y"
                                                 { (yyval.type_qualifier) = TYPE_QUALIFIER_CONST; }
-#line 5947 "tools/widl/parser.tab.c"
+#line 5949 "tools/widl/parser.tab.c"
     break;
 
   case 400: /* m_type_qual_list: %empty  */
-#line 1195 "tools/widl/parser.y"
+#line 1197 "tools/widl/parser.y"
                                                 { (yyval.type_qualifier) = 0; }
-#line 5953 "tools/widl/parser.tab.c"
+#line 5955 "tools/widl/parser.tab.c"
     break;
 
   case 401: /* m_type_qual_list: m_type_qual_list type_qualifier  */
-#line 1196 "tools/widl/parser.y"
+#line 1198 "tools/widl/parser.y"
                                                 { (yyval.type_qualifier) = (yyvsp[-1].type_qualifier) | (yyvsp[0].type_qualifier); }
-#line 5959 "tools/widl/parser.tab.c"
+#line 5961 "tools/widl/parser.tab.c"
     break;
 
   case 402: /* decl_spec: type m_decl_spec_no_type  */
-#line 1199 "tools/widl/parser.y"
+#line 1201 "tools/widl/parser.y"
                                                 { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[0].declspec), NULL, STG_NONE, 0, 0); }
-#line 5965 "tools/widl/parser.tab.c"
+#line 5967 "tools/widl/parser.tab.c"
     break;
 
   case 403: /* decl_spec: decl_spec_no_type type m_decl_spec_no_type  */
-#line 1201 "tools/widl/parser.y"
+#line 1203 "tools/widl/parser.y"
                                                 { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[-2].declspec), (yyvsp[0].declspec), STG_NONE, 0, 0); }
-#line 5971 "tools/widl/parser.tab.c"
+#line 5973 "tools/widl/parser.tab.c"
     break;
 
   case 404: /* unqualified_decl_spec: unqualified_type m_decl_spec_no_type  */
-#line 1205 "tools/widl/parser.y"
+#line 1207 "tools/widl/parser.y"
                                                 { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[0].declspec), NULL, STG_NONE, 0, 0); }
-#line 5977 "tools/widl/parser.tab.c"
+#line 5979 "tools/widl/parser.tab.c"
     break;
 
   case 405: /* unqualified_decl_spec: decl_spec_no_type unqualified_type m_decl_spec_no_type  */
-#line 1207 "tools/widl/parser.y"
+#line 1209 "tools/widl/parser.y"
                                                 { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[-2].declspec), (yyvsp[0].declspec), STG_NONE, 0, 0); }
-#line 5983 "tools/widl/parser.tab.c"
+#line 5985 "tools/widl/parser.tab.c"
     break;
 
   case 406: /* m_decl_spec_no_type: %empty  */
-#line 1211 "tools/widl/parser.y"
+#line 1213 "tools/widl/parser.y"
                                                 { (yyval.declspec) = NULL; }
-#line 5989 "tools/widl/parser.tab.c"
+#line 5991 "tools/widl/parser.tab.c"
     break;
 
   case 408: /* decl_spec_no_type: type_qualifier m_decl_spec_no_type  */
-#line 1216 "tools/widl/parser.y"
+#line 1218 "tools/widl/parser.y"
                                                 { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, STG_NONE, (yyvsp[-1].type_qualifier), 0); }
-#line 5995 "tools/widl/parser.tab.c"
+#line 5997 "tools/widl/parser.tab.c"
     break;
 
   case 409: /* decl_spec_no_type: function_specifier m_decl_spec_no_type  */
-#line 1217 "tools/widl/parser.y"
+#line 1219 "tools/widl/parser.y"
                                                   { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, STG_NONE, 0, (yyvsp[-1].function_specifier)); }
-#line 6001 "tools/widl/parser.tab.c"
+#line 6003 "tools/widl/parser.tab.c"
     break;
 
   case 410: /* decl_spec_no_type: storage_cls_spec m_decl_spec_no_type  */
-#line 1218 "tools/widl/parser.y"
+#line 1220 "tools/widl/parser.y"
                                                 { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, (yyvsp[-1].stgclass), 0, 0); }
-#line 6007 "tools/widl/parser.tab.c"
+#line 6009 "tools/widl/parser.tab.c"
     break;
 
   case 411: /* declarator: '*' m_type_qual_list declarator  */
-#line 1223 "tools/widl/parser.y"
+#line 1225 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_type((yyval.declarator), type_new_pointer(NULL), (yyvsp[-1].type_qualifier)); }
-#line 6013 "tools/widl/parser.tab.c"
+#line 6015 "tools/widl/parser.tab.c"
     break;
 
   case 412: /* declarator: callconv declarator  */
-#line 1224 "tools/widl/parser.y"
+#line 1226 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_callconv( (yyloc), (yyval.declarator)->type, (yyvsp[-1].str) ); }
-#line 6019 "tools/widl/parser.tab.c"
+#line 6021 "tools/widl/parser.tab.c"
     break;
 
   case 414: /* direct_declarator: ident  */
-#line 1229 "tools/widl/parser.y"
+#line 1231 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator((yyvsp[0].var)); }
-#line 6025 "tools/widl/parser.tab.c"
+#line 6027 "tools/widl/parser.tab.c"
     break;
 
   case 415: /* direct_declarator: '(' declarator ')'  */
-#line 1230 "tools/widl/parser.y"
+#line 1232 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-1].declarator); }
-#line 6031 "tools/widl/parser.tab.c"
+#line 6033 "tools/widl/parser.tab.c"
     break;
 
   case 416: /* direct_declarator: direct_declarator array  */
-#line 1231 "tools/widl/parser.y"
+#line 1233 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-1].declarator); append_array((yyval.declarator), (yyvsp[0].expr)); }
-#line 6037 "tools/widl/parser.tab.c"
+#line 6039 "tools/widl/parser.tab.c"
     break;
 
   case 417: /* direct_declarator: direct_declarator '(' m_args ')'  */
-#line 1232 "tools/widl/parser.y"
+#line 1234 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-3].declarator); append_chain_type((yyval.declarator), type_new_function((yyvsp[-1].var_list)), 0); }
-#line 6043 "tools/widl/parser.tab.c"
+#line 6045 "tools/widl/parser.tab.c"
     break;
 
   case 418: /* abstract_declarator: '*' m_type_qual_list m_abstract_declarator  */
-#line 1238 "tools/widl/parser.y"
+#line 1240 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_type((yyval.declarator), type_new_pointer(NULL), (yyvsp[-1].type_qualifier)); }
-#line 6049 "tools/widl/parser.tab.c"
+#line 6051 "tools/widl/parser.tab.c"
     break;
 
   case 419: /* abstract_declarator: callconv m_abstract_declarator  */
-#line 1239 "tools/widl/parser.y"
+#line 1241 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_callconv( (yyloc), (yyval.declarator)->type, (yyvsp[-1].str) ); }
-#line 6055 "tools/widl/parser.tab.c"
+#line 6057 "tools/widl/parser.tab.c"
     break;
 
   case 421: /* abstract_declarator_no_direct: '*' m_type_qual_list m_any_declarator  */
-#line 1246 "tools/widl/parser.y"
+#line 1248 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_type((yyval.declarator), type_new_pointer(NULL), (yyvsp[-1].type_qualifier)); }
-#line 6061 "tools/widl/parser.tab.c"
+#line 6063 "tools/widl/parser.tab.c"
     break;
 
   case 422: /* abstract_declarator_no_direct: callconv m_any_declarator  */
-#line 1247 "tools/widl/parser.y"
+#line 1249 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_callconv( (yyloc), (yyval.declarator)->type, (yyvsp[-1].str) ); }
-#line 6067 "tools/widl/parser.tab.c"
+#line 6069 "tools/widl/parser.tab.c"
     break;
 
   case 423: /* m_abstract_declarator: %empty  */
-#line 1252 "tools/widl/parser.y"
+#line 1254 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator(NULL); }
-#line 6073 "tools/widl/parser.tab.c"
+#line 6075 "tools/widl/parser.tab.c"
     break;
 
   case 425: /* abstract_direct_declarator: '(' abstract_declarator_no_direct ')'  */
-#line 1258 "tools/widl/parser.y"
+#line 1260 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-1].declarator); }
-#line 6079 "tools/widl/parser.tab.c"
+#line 6081 "tools/widl/parser.tab.c"
     break;
 
   case 426: /* abstract_direct_declarator: abstract_direct_declarator array  */
-#line 1259 "tools/widl/parser.y"
+#line 1261 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-1].declarator); append_array((yyval.declarator), (yyvsp[0].expr)); }
-#line 6085 "tools/widl/parser.tab.c"
+#line 6087 "tools/widl/parser.tab.c"
     break;
 
   case 427: /* abstract_direct_declarator: array  */
-#line 1260 "tools/widl/parser.y"
+#line 1262 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator(NULL); append_array((yyval.declarator), (yyvsp[0].expr)); }
-#line 6091 "tools/widl/parser.tab.c"
+#line 6093 "tools/widl/parser.tab.c"
     break;
 
   case 428: /* abstract_direct_declarator: '(' m_args ')'  */
-#line 1262 "tools/widl/parser.y"
+#line 1264 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator(NULL);
 						  append_chain_type((yyval.declarator), type_new_function((yyvsp[-1].var_list)), 0);
 						}
-#line 6099 "tools/widl/parser.tab.c"
+#line 6101 "tools/widl/parser.tab.c"
     break;
 
   case 429: /* abstract_direct_declarator: abstract_direct_declarator '(' m_args ')'  */
-#line 1266 "tools/widl/parser.y"
+#line 1268 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-3].declarator);
 						  append_chain_type((yyval.declarator), type_new_function((yyvsp[-1].var_list)), 0);
 						}
-#line 6107 "tools/widl/parser.tab.c"
+#line 6109 "tools/widl/parser.tab.c"
     break;
 
   case 430: /* any_declarator: '*' m_type_qual_list m_any_declarator  */
-#line 1274 "tools/widl/parser.y"
+#line 1276 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_type((yyval.declarator), type_new_pointer(NULL), (yyvsp[-1].type_qualifier)); }
-#line 6113 "tools/widl/parser.tab.c"
+#line 6115 "tools/widl/parser.tab.c"
     break;
 
   case 431: /* any_declarator: callconv m_any_declarator  */
-#line 1275 "tools/widl/parser.y"
+#line 1277 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_callconv( (yyloc), (yyval.declarator)->type, (yyvsp[-1].str) ); }
-#line 6119 "tools/widl/parser.tab.c"
+#line 6121 "tools/widl/parser.tab.c"
     break;
 
   case 433: /* any_declarator_no_direct: '*' m_type_qual_list m_any_declarator  */
-#line 1282 "tools/widl/parser.y"
+#line 1284 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_type((yyval.declarator), type_new_pointer(NULL), (yyvsp[-1].type_qualifier)); }
-#line 6125 "tools/widl/parser.tab.c"
+#line 6127 "tools/widl/parser.tab.c"
     break;
 
   case 434: /* any_declarator_no_direct: callconv m_any_declarator  */
-#line 1283 "tools/widl/parser.y"
+#line 1285 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); append_chain_callconv( (yyloc), (yyval.declarator)->type, (yyvsp[-1].str) ); }
-#line 6131 "tools/widl/parser.tab.c"
+#line 6133 "tools/widl/parser.tab.c"
     break;
 
   case 435: /* m_any_declarator: %empty  */
-#line 1288 "tools/widl/parser.y"
+#line 1290 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator(NULL); }
-#line 6137 "tools/widl/parser.tab.c"
+#line 6139 "tools/widl/parser.tab.c"
     break;
 
   case 437: /* any_direct_declarator: ident  */
-#line 1296 "tools/widl/parser.y"
+#line 1298 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator((yyvsp[0].var)); }
-#line 6143 "tools/widl/parser.tab.c"
+#line 6145 "tools/widl/parser.tab.c"
     break;
 
   case 438: /* any_direct_declarator: '(' any_declarator_no_direct ')'  */
-#line 1297 "tools/widl/parser.y"
+#line 1299 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-1].declarator); }
-#line 6149 "tools/widl/parser.tab.c"
+#line 6151 "tools/widl/parser.tab.c"
     break;
 
   case 439: /* any_direct_declarator: any_direct_declarator array  */
-#line 1298 "tools/widl/parser.y"
+#line 1300 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-1].declarator); append_array((yyval.declarator), (yyvsp[0].expr)); }
-#line 6155 "tools/widl/parser.tab.c"
+#line 6157 "tools/widl/parser.tab.c"
     break;
 
   case 440: /* any_direct_declarator: array  */
-#line 1299 "tools/widl/parser.y"
+#line 1301 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator(NULL); append_array((yyval.declarator), (yyvsp[0].expr)); }
-#line 6161 "tools/widl/parser.tab.c"
+#line 6163 "tools/widl/parser.tab.c"
     break;
 
   case 441: /* any_direct_declarator: '(' m_args ')'  */
-#line 1301 "tools/widl/parser.y"
+#line 1303 "tools/widl/parser.y"
                                                 { (yyval.declarator) = make_declarator(NULL);
 						  append_chain_type((yyval.declarator), type_new_function((yyvsp[-1].var_list)), 0);
 						}
-#line 6169 "tools/widl/parser.tab.c"
+#line 6171 "tools/widl/parser.tab.c"
     break;
 
   case 442: /* any_direct_declarator: any_direct_declarator '(' m_args ')'  */
-#line 1305 "tools/widl/parser.y"
+#line 1307 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-3].declarator);
 						  append_chain_type((yyval.declarator), type_new_function((yyvsp[-1].var_list)), 0);
 						}
-#line 6177 "tools/widl/parser.tab.c"
+#line 6179 "tools/widl/parser.tab.c"
     break;
 
   case 443: /* declarator_list: declarator  */
-#line 1311 "tools/widl/parser.y"
+#line 1313 "tools/widl/parser.y"
                                                 { (yyval.declarator_list) = append_declarator( NULL, (yyvsp[0].declarator) ); }
-#line 6183 "tools/widl/parser.tab.c"
+#line 6185 "tools/widl/parser.tab.c"
     break;
 
   case 444: /* declarator_list: declarator_list ',' declarator  */
-#line 1312 "tools/widl/parser.y"
+#line 1314 "tools/widl/parser.y"
                                                 { (yyval.declarator_list) = append_declarator( (yyvsp[-2].declarator_list), (yyvsp[0].declarator) ); }
-#line 6189 "tools/widl/parser.tab.c"
+#line 6191 "tools/widl/parser.tab.c"
     break;
 
   case 445: /* m_bitfield: %empty  */
-#line 1316 "tools/widl/parser.y"
+#line 1318 "tools/widl/parser.y"
                                                 { (yyval.expr) = NULL; }
-#line 6195 "tools/widl/parser.tab.c"
+#line 6197 "tools/widl/parser.tab.c"
     break;
 
   case 446: /* m_bitfield: ':' expr_const  */
-#line 1317 "tools/widl/parser.y"
+#line 1319 "tools/widl/parser.y"
                                                 { (yyval.expr) = (yyvsp[0].expr); }
-#line 6201 "tools/widl/parser.tab.c"
+#line 6203 "tools/widl/parser.tab.c"
     break;
 
   case 447: /* struct_declarator: any_declarator m_bitfield  */
-#line 1320 "tools/widl/parser.y"
+#line 1322 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->bits = (yyvsp[0].expr);
 						  if (!(yyval.declarator)->bits && !(yyval.declarator)->var->name)
 						    error_loc("unnamed fields are not allowed\n");
 						}
-#line 6210 "tools/widl/parser.tab.c"
+#line 6212 "tools/widl/parser.tab.c"
     break;
 
   case 448: /* struct_declarator_list: struct_declarator  */
-#line 1327 "tools/widl/parser.y"
+#line 1329 "tools/widl/parser.y"
                                                 { (yyval.declarator_list) = append_declarator( NULL, (yyvsp[0].declarator) ); }
-#line 6216 "tools/widl/parser.tab.c"
+#line 6218 "tools/widl/parser.tab.c"
     break;
 
   case 449: /* struct_declarator_list: struct_declarator_list ',' struct_declarator  */
-#line 1329 "tools/widl/parser.y"
+#line 1331 "tools/widl/parser.y"
                                                 { (yyval.declarator_list) = append_declarator( (yyvsp[-2].declarator_list), (yyvsp[0].declarator) ); }
-#line 6222 "tools/widl/parser.tab.c"
+#line 6224 "tools/widl/parser.tab.c"
     break;
 
   case 450: /* init_declarator: declarator  */
-#line 1333 "tools/widl/parser.y"
+#line 1335 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[0].declarator); }
-#line 6228 "tools/widl/parser.tab.c"
+#line 6230 "tools/widl/parser.tab.c"
     break;
 
   case 451: /* init_declarator: declarator '=' expr_const  */
-#line 1334 "tools/widl/parser.y"
+#line 1336 "tools/widl/parser.y"
                                                 { (yyval.declarator) = (yyvsp[-2].declarator); (yyvsp[-2].declarator)->var->eval = (yyvsp[0].expr); }
-#line 6234 "tools/widl/parser.tab.c"
+#line 6236 "tools/widl/parser.tab.c"
     break;
 
   case 452: /* threading_type: tAPARTMENT  */
-#line 1338 "tools/widl/parser.y"
+#line 1340 "tools/widl/parser.y"
                                                 { (yyval.num) = THREADING_APARTMENT; }
-#line 6240 "tools/widl/parser.tab.c"
+#line 6242 "tools/widl/parser.tab.c"
     break;
 
   case 453: /* threading_type: tNEUTRAL  */
-#line 1339 "tools/widl/parser.y"
+#line 1341 "tools/widl/parser.y"
                                                 { (yyval.num) = THREADING_NEUTRAL; }
-#line 6246 "tools/widl/parser.tab.c"
+#line 6248 "tools/widl/parser.tab.c"
     break;
 
   case 454: /* threading_type: tSINGLE  */
-#line 1340 "tools/widl/parser.y"
+#line 1342 "tools/widl/parser.y"
                                                 { (yyval.num) = THREADING_SINGLE; }
-#line 6252 "tools/widl/parser.tab.c"
+#line 6254 "tools/widl/parser.tab.c"
     break;
 
   case 455: /* threading_type: tFREE  */
-#line 1341 "tools/widl/parser.y"
+#line 1343 "tools/widl/parser.y"
                                                 { (yyval.num) = THREADING_FREE; }
-#line 6258 "tools/widl/parser.tab.c"
+#line 6260 "tools/widl/parser.tab.c"
     break;
 
   case 456: /* threading_type: tBOTH  */
-#line 1342 "tools/widl/parser.y"
+#line 1344 "tools/widl/parser.y"
                                                 { (yyval.num) = THREADING_BOTH; }
-#line 6264 "tools/widl/parser.tab.c"
+#line 6266 "tools/widl/parser.tab.c"
     break;
 
   case 457: /* threading_type: tMTA  */
-#line 1343 "tools/widl/parser.y"
+#line 1345 "tools/widl/parser.y"
                                                 { (yyval.num) = THREADING_FREE; }
-#line 6270 "tools/widl/parser.tab.c"
+#line 6272 "tools/widl/parser.tab.c"
     break;
 
   case 458: /* pointer_type: tREF  */
-#line 1347 "tools/widl/parser.y"
+#line 1349 "tools/widl/parser.y"
                                                 { (yyval.num) = FC_RP; }
-#line 6276 "tools/widl/parser.tab.c"
+#line 6278 "tools/widl/parser.tab.c"
     break;
 
   case 459: /* pointer_type: tUNIQUE  */
-#line 1348 "tools/widl/parser.y"
+#line 1350 "tools/widl/parser.y"
                                                 { (yyval.num) = FC_UP; }
-#line 6282 "tools/widl/parser.tab.c"
+#line 6284 "tools/widl/parser.tab.c"
     break;
 
   case 460: /* pointer_type: tPTR  */
-#line 1349 "tools/widl/parser.y"
+#line 1351 "tools/widl/parser.y"
                                                 { (yyval.num) = FC_FP; }
-#line 6288 "tools/widl/parser.tab.c"
+#line 6290 "tools/widl/parser.tab.c"
     break;
 
   case 461: /* structdef: tSTRUCT m_typename '{' fields '}'  */
-#line 1352 "tools/widl/parser.y"
+#line 1354 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_struct((yyvsp[-3].str), current_namespace, TRUE, (yyvsp[-1].var_list), &(yylsp[-3])); }
-#line 6294 "tools/widl/parser.tab.c"
+#line 6296 "tools/widl/parser.tab.c"
     break;
 
   case 462: /* unqualified_type: tVOID  */
-#line 1356 "tools/widl/parser.y"
+#line 1358 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_void(); }
-#line 6300 "tools/widl/parser.tab.c"
+#line 6302 "tools/widl/parser.tab.c"
     break;
 
   case 463: /* unqualified_type: base_type  */
-#line 1357 "tools/widl/parser.y"
+#line 1359 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 6306 "tools/widl/parser.tab.c"
+#line 6308 "tools/widl/parser.tab.c"
     break;
 
   case 464: /* unqualified_type: enumdef  */
-#line 1358 "tools/widl/parser.y"
+#line 1360 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 6312 "tools/widl/parser.tab.c"
+#line 6314 "tools/widl/parser.tab.c"
     break;
 
   case 465: /* unqualified_type: tENUM typename  */
-#line 1359 "tools/widl/parser.y"
+#line 1361 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_enum((yyvsp[0].str), current_namespace, FALSE, NULL, &(yyloc)); }
-#line 6318 "tools/widl/parser.tab.c"
+#line 6320 "tools/widl/parser.tab.c"
     break;
 
   case 466: /* unqualified_type: structdef  */
-#line 1360 "tools/widl/parser.y"
+#line 1362 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 6324 "tools/widl/parser.tab.c"
+#line 6326 "tools/widl/parser.tab.c"
     break;
 
   case 467: /* unqualified_type: tSTRUCT typename  */
-#line 1361 "tools/widl/parser.y"
+#line 1363 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_struct((yyvsp[0].str), current_namespace, FALSE, NULL, &(yyloc)); }
-#line 6330 "tools/widl/parser.tab.c"
+#line 6332 "tools/widl/parser.tab.c"
     break;
 
   case 468: /* unqualified_type: uniondef  */
-#line 1362 "tools/widl/parser.y"
+#line 1364 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 6336 "tools/widl/parser.tab.c"
+#line 6338 "tools/widl/parser.tab.c"
     break;
 
   case 469: /* unqualified_type: tUNION typename  */
-#line 1363 "tools/widl/parser.y"
+#line 1365 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_nonencapsulated_union((yyvsp[0].str), current_namespace, FALSE, NULL, &(yyloc)); }
-#line 6342 "tools/widl/parser.tab.c"
+#line 6344 "tools/widl/parser.tab.c"
     break;
 
   case 470: /* unqualified_type: tSAFEARRAY '(' type ')'  */
-#line 1364 "tools/widl/parser.y"
+#line 1366 "tools/widl/parser.y"
                                                 { (yyval.type) = make_safearray((yyvsp[-1].type)); }
-#line 6348 "tools/widl/parser.tab.c"
+#line 6350 "tools/widl/parser.tab.c"
     break;
 
   case 471: /* unqualified_type: aKNOWNTYPE  */
-#line 1365 "tools/widl/parser.y"
+#line 1367 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error(current_namespace, (yyvsp[0].str)); }
-#line 6354 "tools/widl/parser.tab.c"
+#line 6356 "tools/widl/parser.tab.c"
     break;
 
   case 473: /* type: namespace_pfx typename  */
-#line 1370 "tools/widl/parser.y"
+#line 1372 "tools/widl/parser.y"
                                                 { (yyval.type) = find_type_or_error((yyvsp[-1].namespace), (yyvsp[0].str)); }
-#line 6360 "tools/widl/parser.tab.c"
+#line 6362 "tools/widl/parser.tab.c"
     break;
 
   case 474: /* type: parameterized_type  */
-#line 1371 "tools/widl/parser.y"
+#line 1373 "tools/widl/parser.y"
                                                 { (yyval.type) = (yyvsp[0].type); }
-#line 6366 "tools/widl/parser.tab.c"
+#line 6368 "tools/widl/parser.tab.c"
     break;
 
   case 475: /* typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list  */
-#line 1375 "tools/widl/parser.y"
+#line 1377 "tools/widl/parser.y"
                                                 { (yyvsp[-4].attr_list) = append_attribs((yyvsp[-4].attr_list), (yyvsp[-2].attr_list));
 						  reg_typedefs( (yyloc), (yyvsp[-1].declspec), (yyvsp[0].declarator_list), check_typedef_attrs( (yyvsp[-4].attr_list) ) );
 						  (yyval.statement) = make_statement_typedef((yyvsp[0].declarator_list), (yyvsp[-1].declspec)->type->defined && !(yyvsp[-1].declspec)->type->defined_in_import);
 						}
-#line 6375 "tools/widl/parser.tab.c"
+#line 6377 "tools/widl/parser.tab.c"
     break;
 
   case 476: /* uniondef: tUNION m_typename '{' ne_union_fields '}'  */
-#line 1382 "tools/widl/parser.y"
+#line 1384 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_nonencapsulated_union((yyvsp[-3].str), current_namespace, TRUE, (yyvsp[-1].var_list), &(yylsp[-3])); }
-#line 6381 "tools/widl/parser.tab.c"
+#line 6383 "tools/widl/parser.tab.c"
     break;
 
   case 477: /* uniondef: tUNION m_typename tSWITCH '(' s_field ')' m_ident '{' cases '}'  */
-#line 1385 "tools/widl/parser.y"
+#line 1387 "tools/widl/parser.y"
                                                 { (yyval.type) = type_new_encapsulated_union((yyvsp[-8].str), (yyvsp[-5].var), (yyvsp[-3].var), (yyvsp[-1].var_list), &(yylsp[-8])); }
-#line 6387 "tools/widl/parser.tab.c"
+#line 6389 "tools/widl/parser.tab.c"
     break;
 
   case 478: /* version: aNUM  */
-#line 1389 "tools/widl/parser.y"
-                                                { (yyval.num) = MAKEVERSION((yyvsp[0].integer).value, 0); }
-#line 6393 "tools/widl/parser.tab.c"
+#line 1391 "tools/widl/parser.y"
+                                                { (yyval.version) = make_version( (yyvsp[0].integer).value, 0 ); }
+#line 6395 "tools/widl/parser.tab.c"
     break;
 
   case 479: /* version: aNUM '.' aNUM  */
-#line 1390 "tools/widl/parser.y"
-                                                { (yyval.num) = MAKEVERSION((yyvsp[-2].integer).value, (yyvsp[0].integer).value); }
-#line 6399 "tools/widl/parser.tab.c"
+#line 1392 "tools/widl/parser.y"
+                                                { (yyval.version) = make_version( (yyvsp[-2].integer).value, (yyvsp[0].integer).value ); }
+#line 6401 "tools/widl/parser.tab.c"
     break;
 
   case 480: /* version: aHEXNUM  */
-#line 1391 "tools/widl/parser.y"
-                                                { (yyval.num) = (yyvsp[0].integer).value; }
-#line 6405 "tools/widl/parser.tab.c"
+#line 1393 "tools/widl/parser.y"
+                                                { (yyval.version) = make_version( (yyvsp[0].integer).value >> 16, (yyvsp[0].integer).value & 0xffff ); }
+#line 6407 "tools/widl/parser.tab.c"
     break;
 
   case 485: /* acf_int_statement: tTYPEDEF acf_attributes aKNOWNTYPE ';'  */
-#line 1406 "tools/widl/parser.y"
+#line 1408 "tools/widl/parser.y"
                                                 { type_t *type = find_type_or_error(current_namespace, (yyvsp[-1].str));
                                                   type->attrs = append_attr_list(type->attrs, (yyvsp[-2].attr_list));
                                                 }
-#line 6413 "tools/widl/parser.tab.c"
+#line 6415 "tools/widl/parser.tab.c"
     break;
 
   case 486: /* acf_interface: acf_attributes tINTERFACE aKNOWNTYPE '{' acf_int_statements '}'  */
-#line 1413 "tools/widl/parser.y"
+#line 1415 "tools/widl/parser.y"
                                                 {  type_t *iface = find_type_or_error(current_namespace, (yyvsp[-3].str));
                                                    if (type_get_type(iface) != TYPE_INTERFACE)
                                                        error_loc("%s is not an interface\n", iface->name);
                                                    iface->attrs = append_attr_list(iface->attrs, (yyvsp[-5].attr_list));
                                                 }
-#line 6423 "tools/widl/parser.tab.c"
+#line 6425 "tools/widl/parser.tab.c"
     break;
 
   case 487: /* acf_attributes: %empty  */
-#line 1421 "tools/widl/parser.y"
+#line 1423 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = NULL; }
-#line 6429 "tools/widl/parser.tab.c"
+#line 6431 "tools/widl/parser.tab.c"
     break;
 
   case 488: /* acf_attributes: '[' acf_attribute_list ']'  */
-#line 1422 "tools/widl/parser.y"
+#line 1424 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = (yyvsp[-1].attr_list); }
-#line 6435 "tools/widl/parser.tab.c"
+#line 6437 "tools/widl/parser.tab.c"
     break;
 
   case 489: /* acf_attribute_list: acf_attribute  */
-#line 1426 "tools/widl/parser.y"
+#line 1428 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = append_attr(NULL, (yyvsp[0].attr)); }
-#line 6441 "tools/widl/parser.tab.c"
+#line 6443 "tools/widl/parser.tab.c"
     break;
 
   case 490: /* acf_attribute_list: acf_attribute_list ',' acf_attribute  */
-#line 1427 "tools/widl/parser.y"
+#line 1429 "tools/widl/parser.y"
                                                 { (yyval.attr_list) = append_attr((yyvsp[-2].attr_list), (yyvsp[0].attr)); }
-#line 6447 "tools/widl/parser.tab.c"
+#line 6449 "tools/widl/parser.tab.c"
     break;
 
   case 491: /* acf_attribute: tALLOCATE '(' allocate_option_list ')'  */
-#line 1432 "tools/widl/parser.y"
+#line 1434 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_ALLOCATE, (yyvsp[-1].num) ); }
-#line 6453 "tools/widl/parser.tab.c"
+#line 6455 "tools/widl/parser.tab.c"
     break;
 
   case 492: /* acf_attribute: tENCODE  */
-#line 1433 "tools/widl/parser.y"
+#line 1435 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_ENCODE, 0 ); }
-#line 6459 "tools/widl/parser.tab.c"
+#line 6461 "tools/widl/parser.tab.c"
     break;
 
   case 493: /* acf_attribute: tDECODE  */
-#line 1434 "tools/widl/parser.y"
+#line 1436 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_DECODE, 0 ); }
-#line 6465 "tools/widl/parser.tab.c"
+#line 6467 "tools/widl/parser.tab.c"
     break;
 
   case 494: /* acf_attribute: tEXPLICITHANDLE  */
-#line 1435 "tools/widl/parser.y"
+#line 1437 "tools/widl/parser.y"
                                                 { (yyval.attr) = attr_int( (yyloc), ATTR_EXPLICIT_HANDLE, 0 ); }
-#line 6471 "tools/widl/parser.tab.c"
+#line 6473 "tools/widl/parser.tab.c"
     break;
 
   case 495: /* allocate_option_list: allocate_option  */
-#line 1439 "tools/widl/parser.y"
+#line 1441 "tools/widl/parser.y"
                                                 { (yyval.num) = (yyvsp[0].num); }
-#line 6477 "tools/widl/parser.tab.c"
+#line 6479 "tools/widl/parser.tab.c"
     break;
 
   case 496: /* allocate_option_list: allocate_option_list ',' allocate_option  */
-#line 1441 "tools/widl/parser.y"
+#line 1443 "tools/widl/parser.y"
                                                 { (yyval.num) = (yyvsp[-2].num) | (yyvsp[0].num); }
-#line 6483 "tools/widl/parser.tab.c"
+#line 6485 "tools/widl/parser.tab.c"
     break;
 
   case 497: /* allocate_option: tDONTFREE  */
-#line 1445 "tools/widl/parser.y"
+#line 1447 "tools/widl/parser.y"
                                                 { (yyval.num) = FC_DONT_FREE; }
-#line 6489 "tools/widl/parser.tab.c"
+#line 6491 "tools/widl/parser.tab.c"
     break;
 
   case 498: /* allocate_option: tFREE  */
-#line 1446 "tools/widl/parser.y"
+#line 1448 "tools/widl/parser.y"
                                                 { (yyval.num) = 0; }
-#line 6495 "tools/widl/parser.tab.c"
+#line 6497 "tools/widl/parser.tab.c"
     break;
 
   case 499: /* allocate_option: tALLNODES  */
-#line 1447 "tools/widl/parser.y"
+#line 1449 "tools/widl/parser.y"
                                                 { (yyval.num) = FC_ALLOCATE_ALL_NODES; }
-#line 6501 "tools/widl/parser.tab.c"
+#line 6503 "tools/widl/parser.tab.c"
     break;
 
   case 500: /* allocate_option: tSINGLENODE  */
-#line 1448 "tools/widl/parser.y"
+#line 1450 "tools/widl/parser.y"
                                                 { (yyval.num) = 0; }
-#line 6507 "tools/widl/parser.tab.c"
+#line 6509 "tools/widl/parser.tab.c"
     break;
 
 
-#line 6511 "tools/widl/parser.tab.c"
+#line 6513 "tools/widl/parser.tab.c"
 
       default: break;
     }
@@ -6736,7 +6738,7 @@
   return yyresult;
 }
 
-#line 1451 "tools/widl/parser.y"
+#line 1453 "tools/widl/parser.y"
 
 
 static void decl_builtin_basic(const char *name, enum type_basic_type type)
@@ -7279,6 +7281,14 @@
     return typelib;
 }
 
+static version_t *make_version( unsigned short major, unsigned short minor )
+{
+    version_t *version = xmalloc( sizeof(*version) );
+    version->major = major;
+    version->minor = minor;
+    return version;
+}
+
 static int hash_ident(const char *name)
 {
   const char *p = name;
@@ -7390,6 +7400,11 @@
     type->c_name = name;
     type->qualified_name = name;
   }
+  else if (type->type_type == TYPE_PARAMETER)
+  {
+    type->c_name = strmake( "%s_abi", type->name );
+    type->qualified_name = strmake( "%s_abi", type->name );
+  }
   else
   {
     type->c_name = format_namespace(namespace, "__x_", "_C", name, use_abi_namespace ? "ABI" : NULL);
@@ -7851,6 +7866,108 @@
         if (field->declspec.type) check_field_common(type, type->name, field);
 }
 
+static void check_eventadd_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+    {
+        const type_t *type = arg->declspec.type;
+        const type_t *ref_type = is_ptr( type ) ? type_pointer_get_ref_type( type ) : NULL;
+
+        count++;
+        if (count == 1 && (!ref_type || ref_type->type_type != TYPE_DELEGATE))
+            error_at( &arg->where, "first parameter '%s' of function '%s' must be a delegate pointer\n",
+                      arg->name, func->name );
+
+        if (count == 2 && (!ref_type || !ref_type->name || strcmp( ref_type->name, "EventRegistrationToken" ) ||
+            !is_attr( arg->attrs, ATTR_RETVAL )))
+            error_at( &arg->where, "second parameter '%s' of function '%s' must be an [out, retval] EventRegistrationToken pointer\n",
+                      arg->name, func->name );
+
+        if (count > 2) error_at( &arg->where, "eventadd function '%s' has too many parameters\n", func->name );
+    }
+}
+
+static void check_eventremove_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+    {
+        const type_t *type = arg->declspec.type;
+
+        count++;
+        if (count == 1 && (!type->name || strcmp( type->name, "EventRegistrationToken" )))
+            error_at( &arg->where, "first parameter '%s' of function '%s' must be an EventRegistrationToken\n",
+                      arg->name, func->name );
+
+        if (count > 1) error_at( &arg->where, "eventremove function '%s' has too many parameters\n", func->name );
+    }
+}
+
+bool is_size_param( const var_t *param, const var_list_t *args )
+{
+    const var_t *arg;
+
+    LIST_FOR_EACH_ENTRY( arg, args, const 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 true;
+    }
+    return false;
+}
+
+static void check_propget_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY_REV( arg, args, const var_t, entry )
+    {
+        const type_t *type = arg->declspec.type;
+        bool is_size = is_size_param( arg, args );
+
+        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 );
+    }
+}
+
+static void check_propput_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY_REV( arg, args, const var_t, entry )
+    {
+        bool is_size = is_size_param( arg, args );
+
+        count++;
+        if (is_attr( arg->attrs, ATTR_OUT ))
+            error_at( &arg->where, "parameter '%s' of function '%s' must be an [in] parameter\n", arg->name, func->name );
+
+        if ((is_size && count > 2) || (!is_size && count > 1))
+            error_at( &arg->where, "propput 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)
 {
@@ -7901,6 +8018,8 @@
                 break;
             }
         }
+        else if (is_attr( arg->attrs, ATTR_RETVAL ))
+            error_at( &arg->where, "retval parameter \'%s\' of function \'%s\' must have out attribute\n", arg->name, funcname );
 
         check_field_common(func->declspec.type, funcname, arg);
     }
@@ -7974,6 +8093,19 @@
                 check_remoting_args(func);
         }
     }
+    if (winrt_mode)
+    {
+        STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) )
+        {
+            const var_t *func = stmt->u.var;
+            const var_list_t *args = type_function_get_args( func->declspec.type );
+
+            if (args && is_attr( func->attrs, ATTR_EVENTADD )) check_eventadd_args( func, args );
+            if (args && is_attr( func->attrs, ATTR_EVENTREMOVE )) check_eventremove_args( func, args );
+            if (args && is_attr( func->attrs, ATTR_PROPGET )) check_propget_args( func, args );
+            if (args && is_attr( func->attrs, ATTR_PROPPUT )) check_propput_args( func, args );
+        }
+    }
 }
 
 static int async_iface_attrs(attr_list_t *attrs, const attr_t *attr)
@@ -8073,6 +8205,103 @@
     return stmts;
 }
 
+static void check_activation_interface( const type_t *iface )
+{
+    const statement_t *stmt;
+
+    STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) )
+    {
+        const var_t *arg, *func = stmt->u.var;
+        const var_list_t *arg_list = type_function_get_args( func->declspec.type );
+        unsigned int count = 0;
+
+        if (arg_list) LIST_FOR_EACH_ENTRY_REV( arg, arg_list, const var_t, entry )
+        {
+            const type_t *type = arg->declspec.type;
+
+            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 > 1 && is_attr( arg->attrs, ATTR_OUT ))
+                error_at( &arg->where, "parameter '%s' of function '%s' must be an IN parameter\n",
+                          arg->name, func->name );
+        }
+        if (count < 2)
+            error_at( &func->where, "activation function '%s' must have at least 2 parameters\n", func->name );
+    }
+}
+
+static void check_composition_interface( const type_t *iface )
+{
+    const statement_t *stmt;
+
+    STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) )
+    {
+        const var_t *arg, *func = stmt->u.var;
+        const var_list_t *arg_list = type_function_get_args( func->declspec.type );
+        unsigned int count = 0;
+
+        if (arg_list) LIST_FOR_EACH_ENTRY_REV( arg, arg_list, const var_t, entry )
+        {
+            const type_t *type = arg->declspec.type;
+
+            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_attr( arg->attrs, ATTR_OUT ))
+                error_at( &arg->where, "parameter '%s' of function '%s' must be an OUT parameter\n",
+                          arg->name, func->name );
+
+            if (count > 2 && is_attr( arg->attrs, ATTR_OUT ))
+                error_at( &arg->where, "parameter '%s' of function '%s' must be an IN parameter\n",
+                          arg->name, func->name );
+        }
+        if (count < 3)
+            error_at( &func->where, "composition function '%s' must have at least 3 parameters\n", func->name );
+    }
+}
+
+static void check_runtimeclass( const type_t *runtimeclass )
+{
+    const attr_t *attr;
+
+    LIST_FOR_EACH_ENTRY( attr, runtimeclass->attrs, const attr_t, entry )
+    {
+        const expr_t *value = attr->u.pval;
+
+        if (attr->type == ATTR_ACTIVATABLE)
+        {
+            if (value->type != EXPR_MEMBER) continue;
+
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "activation interface %s is undefined\n", value->u.var->declspec.type->name );
+
+            check_activation_interface( value->u.var->declspec.type );
+        }
+        else if (attr->type == ATTR_COMPOSABLE)
+        {
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "composition interface %s is undefined\n", value->u.var->declspec.type->name );
+
+            check_composition_interface( value->u.var->declspec.type );
+        }
+        else if (attr->type == ATTR_STATIC)
+        {
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "static interface %s is undefined\n", value->u.var->declspec.type->name );
+        }
+        else if (attr->type == ATTR_CONTRACT)
+        {
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "apicontract %s is undefined\n", value->u.var->declspec.type->name );
+        }
+    }
+}
+
 static void check_statements(const statement_list_t *stmts, int is_inside_library)
 {
     const statement_t *stmt;
@@ -8092,6 +8321,8 @@
                 if(winrt_mode)
                     error_loc("coclass is not allowed in Windows Runtime mode\n");
                 break;
+            case TYPE_RUNTIMECLASS:
+                check_runtimeclass( stmt->u.type );
             default:
                 break;
             }
diff --git a/mingw-w64-tools/widl/src/parser.tab.h b/mingw-w64-tools/widl/src/parser.tab.h
index 8d455c4..b34dbf7 100644
--- a/mingw-w64-tools/widl/src/parser.tab.h
+++ b/mingw-w64-tools/widl/src/parser.tab.h
@@ -53,7 +53,7 @@
 extern int parser_debug;
 #endif
 /* "%code requires" blocks.  */
-#line 110 "tools/widl/parser.y"
+#line 111 "tools/widl/parser.y"
 
 
 #define PARSER_LTYPE struct location
@@ -290,7 +290,7 @@
 #if ! defined PARSER_STYPE && ! defined PARSER_STYPE_IS_DECLARED
 union PARSER_STYPE
 {
-#line 134 "tools/widl/parser.y"
+#line 135 "tools/widl/parser.y"
 
 	attr_t *attr;
 	attr_list_t *attr_list;
@@ -308,6 +308,7 @@
 	warning_list_t *warning_list;
 	typeref_t *typeref;
 	typeref_list_t *typeref_list;
+	version_t *version;
 	char *str;
 	struct uuid *uuid;
 	unsigned int num;
@@ -321,7 +322,7 @@
 	enum function_specifier function_specifier;
 	struct namespace *namespace;
 
-#line 325 "tools/widl/parser.tab.h"
+#line 326 "tools/widl/parser.tab.h"
 
 };
 typedef union PARSER_STYPE PARSER_STYPE;
@@ -349,7 +350,7 @@
 int parser_parse (void);
 
 /* "%code provides" blocks.  */
-#line 117 "tools/widl/parser.y"
+#line 118 "tools/widl/parser.y"
 
 
 int parser_lex( PARSER_STYPE *yylval, PARSER_LTYPE *yylloc );
@@ -361,6 +362,6 @@
              else init_location( &(cur), &YYRHSLOC( rhs, 0 ), NULL ); } while(0)
 
 
-#line 365 "tools/widl/parser.tab.h"
+#line 366 "tools/widl/parser.tab.h"
 
 #endif /* !YY_PARSER_TOOLS_WIDL_PARSER_TAB_H_INCLUDED  */
diff --git a/mingw-w64-tools/widl/src/parser.y b/mingw-w64-tools/widl/src/parser.y
index 5185615..91ac325 100644
--- a/mingw-w64-tools/widl/src/parser.y
+++ b/mingw-w64-tools/widl/src/parser.y
@@ -59,6 +59,7 @@
 static void append_chain_type(declarator_t *decl, type_t *type, enum type_qualifier qual);
 static void append_chain_callconv( struct location where, type_t *chain, char *callconv );
 static warning_list_t *append_warning(warning_list_t *, int);
+static version_t *make_version( unsigned short major, unsigned short minor );
 
 static type_t *reg_typedefs( struct location where, decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs );
 static type_t *find_type_or_error(struct namespace *parent, const char *name);
@@ -148,6 +149,7 @@
 	warning_list_t *warning_list;
 	typeref_t *typeref;
 	typeref_list_t *typeref_list;
+	version_t *version;
 	char *str;
 	struct uuid *uuid;
 	unsigned int num;
@@ -336,8 +338,7 @@
 %type <type> coclass coclassdef
 %type <type> runtimeclass runtimeclass_def
 %type <type> apicontract apicontract_def
-%type <num> contract_ver
-%type <num> pointer_type threading_type marshaling_behavior version
+%type <num> pointer_type threading_type marshaling_behavior
 %type <str> libraryhdr callconv cppquote importlib import
 %type <str> typename m_typename
 %type <str> import_start
@@ -349,6 +350,7 @@
 %type <warning_list> warnings
 %type <num> allocate_option_list allocate_option
 %type <namespace> namespace_pfx
+%type <version> version contract_ver
 
 %left ','
 %right '?' ':'
@@ -594,13 +596,13 @@
 	;
 
 contract_ver:
-	  aNUM					{ $$ = MAKEVERSION(0, $1.value); }
-	| aNUM '.' aNUM				{ $$ = MAKEVERSION($3.value, $1.value); }
+	  aNUM					{ $$ = make_version( $1.value, 0 ); }
+	| aNUM '.' aNUM				{ $$ = make_version( $1.value, $3.value ); }
 	;
 
 contract_req
         : decl_spec ',' contract_ver            {
-                                                  struct integer integer = {.value = $3};
+                                                  struct integer integer = {.value = ($3->major << 16) | $3->minor };
                                                   if ($1->type->type_type != TYPE_APICONTRACT)
                                                     error_loc("type %s is not an apicontract\n", $1->type->name);
                                                   $$ = make_exprl(EXPR_NUM, &integer);
@@ -660,7 +662,7 @@
         | tCONTEXTHANDLENOSERIALIZE             { $$ = attr_int( @$, ATTR_CONTEXTHANDLE, 0 ); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
         | tCONTEXTHANDLESERIALIZE               { $$ = attr_int( @$, ATTR_CONTEXTHANDLE, 0 ); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
         | tCONTRACT '(' contract_req ')'        { $$ = attr_ptr( @$, ATTR_CONTRACT, $3 ); }
-        | tCONTRACTVERSION '(' contract_ver ')' { $$ = attr_int( @$, ATTR_CONTRACTVERSION, $3 ); }
+        | tCONTRACTVERSION '(' contract_ver ')' { $$ = attr_ptr( @$, ATTR_CONTRACTVERSION, $3 ); }
         | tCONTROL                              { $$ = attr_int( @$, ATTR_CONTROL, 0 ); }
         | tCUSTOM '(' aUUID ',' expr_const ')'  { attr_custdata_t *data = xmalloc( sizeof(*data) );
                                                   data->id = *$3; data->pval = $5;
@@ -765,7 +767,7 @@
         | tASYNCUUID '(' aUUID ')'              { $$ = attr_ptr( @$, ATTR_ASYNCUUID, $3 ); }
         | tV1ENUM                               { $$ = attr_int( @$, ATTR_V1ENUM, 0 ); }
         | tVARARG                               { $$ = attr_int( @$, ATTR_VARARG, 0 ); }
-        | tVERSION '(' version ')'              { $$ = attr_int( @$, ATTR_VERSION, $3 ); }
+        | tVERSION '(' version ')'              { $$ = attr_ptr( @$, ATTR_VERSION, $3 ); }
         | tVIPROGID '(' aSTRING ')'             { $$ = attr_ptr( @$, ATTR_VIPROGID, $3 ); }
         | tWIREMARSHAL '(' type ')'             { $$ = attr_ptr( @$, ATTR_WIREMARSHAL, $3 ); }
         | pointer_type                          { $$ = attr_int( @$, ATTR_POINTERTYPE, $1 ); }
@@ -1386,9 +1388,9 @@
 	;
 
 version:
-	  aNUM					{ $$ = MAKEVERSION($1.value, 0); }
-	| aNUM '.' aNUM				{ $$ = MAKEVERSION($1.value, $3.value); }
-	| aHEXNUM				{ $$ = $1.value; }
+	  aNUM					{ $$ = make_version( $1.value, 0 ); }
+	| aNUM '.' aNUM				{ $$ = make_version( $1.value, $3.value ); }
+	| aHEXNUM				{ $$ = make_version( $1.value >> 16, $1.value & 0xffff ); }
 	;
 
 acf_statements
@@ -1990,6 +1992,14 @@
     return typelib;
 }
 
+static version_t *make_version( unsigned short major, unsigned short minor )
+{
+    version_t *version = xmalloc( sizeof(*version) );
+    version->major = major;
+    version->minor = minor;
+    return version;
+}
+
 static int hash_ident(const char *name)
 {
   const char *p = name;
@@ -2101,6 +2111,11 @@
     type->c_name = name;
     type->qualified_name = name;
   }
+  else if (type->type_type == TYPE_PARAMETER)
+  {
+    type->c_name = strmake( "%s_abi", type->name );
+    type->qualified_name = strmake( "%s_abi", type->name );
+  }
   else
   {
     type->c_name = format_namespace(namespace, "__x_", "_C", name, use_abi_namespace ? "ABI" : NULL);
@@ -2562,6 +2577,108 @@
         if (field->declspec.type) check_field_common(type, type->name, field);
 }
 
+static void check_eventadd_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+    {
+        const type_t *type = arg->declspec.type;
+        const type_t *ref_type = is_ptr( type ) ? type_pointer_get_ref_type( type ) : NULL;
+
+        count++;
+        if (count == 1 && (!ref_type || ref_type->type_type != TYPE_DELEGATE))
+            error_at( &arg->where, "first parameter '%s' of function '%s' must be a delegate pointer\n",
+                      arg->name, func->name );
+
+        if (count == 2 && (!ref_type || !ref_type->name || strcmp( ref_type->name, "EventRegistrationToken" ) ||
+            !is_attr( arg->attrs, ATTR_RETVAL )))
+            error_at( &arg->where, "second parameter '%s' of function '%s' must be an [out, retval] EventRegistrationToken pointer\n",
+                      arg->name, func->name );
+
+        if (count > 2) error_at( &arg->where, "eventadd function '%s' has too many parameters\n", func->name );
+    }
+}
+
+static void check_eventremove_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+    {
+        const type_t *type = arg->declspec.type;
+
+        count++;
+        if (count == 1 && (!type->name || strcmp( type->name, "EventRegistrationToken" )))
+            error_at( &arg->where, "first parameter '%s' of function '%s' must be an EventRegistrationToken\n",
+                      arg->name, func->name );
+
+        if (count > 1) error_at( &arg->where, "eventremove function '%s' has too many parameters\n", func->name );
+    }
+}
+
+bool is_size_param( const var_t *param, const var_list_t *args )
+{
+    const var_t *arg;
+
+    LIST_FOR_EACH_ENTRY( arg, args, const 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 true;
+    }
+    return false;
+}
+
+static void check_propget_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY_REV( arg, args, const var_t, entry )
+    {
+        const type_t *type = arg->declspec.type;
+        bool is_size = is_size_param( arg, args );
+
+        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 );
+    }
+}
+
+static void check_propput_args( const var_t *func, const var_list_t *args )
+{
+    const var_t *arg;
+    unsigned int count = 0;
+
+    LIST_FOR_EACH_ENTRY_REV( arg, args, const var_t, entry )
+    {
+        bool is_size = is_size_param( arg, args );
+
+        count++;
+        if (is_attr( arg->attrs, ATTR_OUT ))
+            error_at( &arg->where, "parameter '%s' of function '%s' must be an [in] parameter\n", arg->name, func->name );
+
+        if ((is_size && count > 2) || (!is_size && count > 1))
+            error_at( &arg->where, "propput 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)
 {
@@ -2612,6 +2729,8 @@
                 break;
             }
         }
+        else if (is_attr( arg->attrs, ATTR_RETVAL ))
+            error_at( &arg->where, "retval parameter \'%s\' of function \'%s\' must have out attribute\n", arg->name, funcname );
 
         check_field_common(func->declspec.type, funcname, arg);
     }
@@ -2685,6 +2804,19 @@
                 check_remoting_args(func);
         }
     }
+    if (winrt_mode)
+    {
+        STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) )
+        {
+            const var_t *func = stmt->u.var;
+            const var_list_t *args = type_function_get_args( func->declspec.type );
+
+            if (args && is_attr( func->attrs, ATTR_EVENTADD )) check_eventadd_args( func, args );
+            if (args && is_attr( func->attrs, ATTR_EVENTREMOVE )) check_eventremove_args( func, args );
+            if (args && is_attr( func->attrs, ATTR_PROPGET )) check_propget_args( func, args );
+            if (args && is_attr( func->attrs, ATTR_PROPPUT )) check_propput_args( func, args );
+        }
+    }
 }
 
 static int async_iface_attrs(attr_list_t *attrs, const attr_t *attr)
@@ -2784,6 +2916,103 @@
     return stmts;
 }
 
+static void check_activation_interface( const type_t *iface )
+{
+    const statement_t *stmt;
+
+    STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) )
+    {
+        const var_t *arg, *func = stmt->u.var;
+        const var_list_t *arg_list = type_function_get_args( func->declspec.type );
+        unsigned int count = 0;
+
+        if (arg_list) LIST_FOR_EACH_ENTRY_REV( arg, arg_list, const var_t, entry )
+        {
+            const type_t *type = arg->declspec.type;
+
+            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 > 1 && is_attr( arg->attrs, ATTR_OUT ))
+                error_at( &arg->where, "parameter '%s' of function '%s' must be an IN parameter\n",
+                          arg->name, func->name );
+        }
+        if (count < 2)
+            error_at( &func->where, "activation function '%s' must have at least 2 parameters\n", func->name );
+    }
+}
+
+static void check_composition_interface( const type_t *iface )
+{
+    const statement_t *stmt;
+
+    STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts( iface ) )
+    {
+        const var_t *arg, *func = stmt->u.var;
+        const var_list_t *arg_list = type_function_get_args( func->declspec.type );
+        unsigned int count = 0;
+
+        if (arg_list) LIST_FOR_EACH_ENTRY_REV( arg, arg_list, const var_t, entry )
+        {
+            const type_t *type = arg->declspec.type;
+
+            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_attr( arg->attrs, ATTR_OUT ))
+                error_at( &arg->where, "parameter '%s' of function '%s' must be an OUT parameter\n",
+                          arg->name, func->name );
+
+            if (count > 2 && is_attr( arg->attrs, ATTR_OUT ))
+                error_at( &arg->where, "parameter '%s' of function '%s' must be an IN parameter\n",
+                          arg->name, func->name );
+        }
+        if (count < 3)
+            error_at( &func->where, "composition function '%s' must have at least 3 parameters\n", func->name );
+    }
+}
+
+static void check_runtimeclass( const type_t *runtimeclass )
+{
+    const attr_t *attr;
+
+    LIST_FOR_EACH_ENTRY( attr, runtimeclass->attrs, const attr_t, entry )
+    {
+        const expr_t *value = attr->u.pval;
+
+        if (attr->type == ATTR_ACTIVATABLE)
+        {
+            if (value->type != EXPR_MEMBER) continue;
+
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "activation interface %s is undefined\n", value->u.var->declspec.type->name );
+
+            check_activation_interface( value->u.var->declspec.type );
+        }
+        else if (attr->type == ATTR_COMPOSABLE)
+        {
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "composition interface %s is undefined\n", value->u.var->declspec.type->name );
+
+            check_composition_interface( value->u.var->declspec.type );
+        }
+        else if (attr->type == ATTR_STATIC)
+        {
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "static interface %s is undefined\n", value->u.var->declspec.type->name );
+        }
+        else if (attr->type == ATTR_CONTRACT)
+        {
+            if (!value->u.var->declspec.type->defined)
+                error_at( &attr->where, "apicontract %s is undefined\n", value->u.var->declspec.type->name );
+        }
+    }
+}
+
 static void check_statements(const statement_list_t *stmts, int is_inside_library)
 {
     const statement_t *stmt;
@@ -2803,6 +3032,8 @@
                 if(winrt_mode)
                     error_loc("coclass is not allowed in Windows Runtime mode\n");
                 break;
+            case TYPE_RUNTIMECLASS:
+                check_runtimeclass( stmt->u.type );
             default:
                 break;
             }
diff --git a/mingw-w64-tools/widl/src/parser.yy.c b/mingw-w64-tools/widl/src/parser.yy.c
index d50d25c..aaad3b3 100644
--- a/mingw-w64-tools/widl/src/parser.yy.c
+++ b/mingw-w64-tools/widl/src/parser.yy.c
@@ -1909,7 +1909,10 @@
 
 static int token_str( int token, const char *str, YYSTYPE *yylval )
 {
-    char *tmp = xstrdup( str );
+    int len = strlen( str );
+    char *tmp = xmalloc( len + 1 );
+
+    strcpy( tmp, str );
 
     if (token == aWSTRING || token == aSTRING || token == aSQSTRING)
     {
@@ -1922,6 +1925,14 @@
         }
         dst[-1] = 0; /* strip last quote */
     }
+    else if (token == aIDENTIFIER)
+    {
+        if (len > 255)
+        {
+            warning( "truncating identifier that exceeds 255 character limit\n" );
+            tmp[255] = 0;
+        }
+    }
 
     yylval->str = tmp;
     return token;
@@ -1955,13 +1966,13 @@
     winrt_mode = TRUE;
 }
 
-#line 1958 "tools/widl/parser.yy.c"
+#line 1969 "tools/widl/parser.yy.c"
 /*
  **************************************************************************
  * The flexer starts here
  **************************************************************************
  */
-#line 1964 "tools/widl/parser.yy.c"
+#line 1975 "tools/widl/parser.yy.c"
 
 #define INITIAL 0
 #define ATTR 1
@@ -2209,9 +2220,9 @@
 		}
 
 	{
-#line 192 "tools/widl/parser.l"
+#line 203 "tools/widl/parser.l"
 
-#line 2214 "tools/widl/parser.yy.c"
+#line 2225 "tools/widl/parser.yy.c"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -2270,7 +2281,7 @@
 (yy_c_buf_p) = yy_cp = yy_bp + 9;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 194 "tools/widl/parser.l"
+#line 205 "tools/widl/parser.l"
 {
                                                     yy_pop_state();
                                                     yylloc->first_line -= 1;
@@ -2279,7 +2290,7 @@
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 199 "tools/widl/parser.l"
+#line 210 "tools/widl/parser.l"
 {
                                                     yy_pop_state();
                                                     yylloc->first_line -= 1;
@@ -2288,7 +2299,7 @@
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 204 "tools/widl/parser.l"
+#line 215 "tools/widl/parser.l"
 {
                                                     yy_pop_state();
                                                     yylloc->first_line -= 1;
@@ -2297,7 +2308,7 @@
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 209 "tools/widl/parser.l"
+#line 220 "tools/widl/parser.l"
 {
                                                     yy_pop_state();
                                                     yylloc->first_line -= 1;
@@ -2307,7 +2318,7 @@
 
 case 5:
 YY_RULE_SETUP
-#line 215 "tools/widl/parser.l"
+#line 226 "tools/widl/parser.l"
 {
                                                     yylloc->first_line = strtoul( yytext, NULL, 10 ) - 1;
                                                     yylloc->last_line = yylloc->first_line;
@@ -2318,7 +2329,7 @@
 case 6:
 /* rule 6 can match eol */
 YY_RULE_SETUP
-#line 221 "tools/widl/parser.l"
+#line 232 "tools/widl/parser.l"
 {
                                                     input_name = xstrdup( yytext + 1 );
                                                     *strchr( input_name, '"' ) = 0;
@@ -2328,680 +2339,680 @@
 case 7:
 /* rule 7 can match eol */
 YY_RULE_SETUP
-#line 226 "tools/widl/parser.l"
+#line 237 "tools/widl/parser.l"
 { yy_pop_state(); }
 	YY_BREAK
 
 case 8:
 YY_RULE_SETUP
-#line 229 "tools/widl/parser.l"
+#line 240 "tools/widl/parser.l"
 { yy_pop_state(); return ']'; }
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 231 "tools/widl/parser.l"
+#line 242 "tools/widl/parser.l"
 { return token_uuid( yytext, yylval ); }
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 232 "tools/widl/parser.l"
+#line 243 "tools/widl/parser.l"
 { return token_winrt( tACTIVATABLE, yytext, yylval ); }
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 233 "tools/widl/parser.l"
+#line 244 "tools/widl/parser.l"
 { return tAGGREGATABLE; }
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 234 "tools/widl/parser.l"
+#line 245 "tools/widl/parser.l"
 { return token_winrt( tAGILE, yytext, yylval ); }
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 235 "tools/widl/parser.l"
+#line 246 "tools/widl/parser.l"
 { return tALLNODES; }
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 236 "tools/widl/parser.l"
+#line 247 "tools/widl/parser.l"
 { return tALLOCATE; }
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 237 "tools/widl/parser.l"
+#line 248 "tools/widl/parser.l"
 { return tANNOTATION; }
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 238 "tools/widl/parser.l"
+#line 249 "tools/widl/parser.l"
 { return tAPARTMENT; }
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 239 "tools/widl/parser.l"
+#line 250 "tools/widl/parser.l"
 { return tAPPOBJECT; }
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 240 "tools/widl/parser.l"
+#line 251 "tools/widl/parser.l"
 { return tASYNC; }
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 241 "tools/widl/parser.l"
+#line 252 "tools/widl/parser.l"
 { return tASYNCUUID; }
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 242 "tools/widl/parser.l"
+#line 253 "tools/widl/parser.l"
 { return tAUTOHANDLE; }
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 243 "tools/widl/parser.l"
+#line 254 "tools/widl/parser.l"
 { return tBINDABLE; }
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 244 "tools/widl/parser.l"
+#line 255 "tools/widl/parser.l"
 { return tBOTH; }
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 245 "tools/widl/parser.l"
+#line 256 "tools/widl/parser.l"
 { return tBROADCAST; }
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 246 "tools/widl/parser.l"
+#line 257 "tools/widl/parser.l"
 { return tBYTECOUNT; }
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 247 "tools/widl/parser.l"
+#line 258 "tools/widl/parser.l"
 { return tCALLAS; }
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 248 "tools/widl/parser.l"
+#line 259 "tools/widl/parser.l"
 { return tCALLBACK; }
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 249 "tools/widl/parser.l"
+#line 260 "tools/widl/parser.l"
 { return tCODE; }
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 250 "tools/widl/parser.l"
+#line 261 "tools/widl/parser.l"
 { return tCOMMSTATUS; }
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 251 "tools/widl/parser.l"
+#line 262 "tools/widl/parser.l"
 { return token_winrt( tCOMPOSABLE, yytext, yylval ); }
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 252 "tools/widl/parser.l"
+#line 263 "tools/widl/parser.l"
 { return tCONTEXTHANDLE; }
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 253 "tools/widl/parser.l"
+#line 264 "tools/widl/parser.l"
 { return tCONTEXTHANDLENOSERIALIZE; }
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 254 "tools/widl/parser.l"
+#line 265 "tools/widl/parser.l"
 { return tCONTEXTHANDLENOSERIALIZE; }
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 255 "tools/widl/parser.l"
+#line 266 "tools/widl/parser.l"
 { return token_winrt( tCONTRACT, yytext, yylval ); }
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 256 "tools/widl/parser.l"
+#line 267 "tools/widl/parser.l"
 { return token_winrt( tCONTRACTVERSION, yytext, yylval ); }
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 257 "tools/widl/parser.l"
+#line 268 "tools/widl/parser.l"
 { return tCONTROL; }
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 258 "tools/widl/parser.l"
+#line 269 "tools/widl/parser.l"
 { return tCUSTOM; }
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 259 "tools/widl/parser.l"
+#line 270 "tools/widl/parser.l"
 { return tDECODE; }
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 260 "tools/widl/parser.l"
+#line 271 "tools/widl/parser.l"
 { return tDEFAULT_OVERLOAD; }
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 261 "tools/widl/parser.l"
+#line 272 "tools/widl/parser.l"
 { return tDEFAULTBIND; }
 	YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 262 "tools/widl/parser.l"
+#line 273 "tools/widl/parser.l"
 { return tDEFAULTCOLLELEM; }
 	YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 263 "tools/widl/parser.l"
+#line 274 "tools/widl/parser.l"
 { return tDEFAULTVALUE; }
 	YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 264 "tools/widl/parser.l"
+#line 275 "tools/widl/parser.l"
 { return tDEFAULTVTABLE; }
 	YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 265 "tools/widl/parser.l"
+#line 276 "tools/widl/parser.l"
 { return token_winrt( tDEPRECATED, yytext, yylval ); }
 	YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 266 "tools/widl/parser.l"
+#line 277 "tools/widl/parser.l"
 { return tDISABLECONSISTENCYCHECK; }
 	YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 267 "tools/widl/parser.l"
+#line 278 "tools/widl/parser.l"
 { return tDISPLAYBIND; }
 	YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 268 "tools/widl/parser.l"
+#line 279 "tools/widl/parser.l"
 { return tDLLNAME; }
 	YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 269 "tools/widl/parser.l"
+#line 280 "tools/widl/parser.l"
 { return tDONTFREE; }
 	YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 270 "tools/widl/parser.l"
+#line 281 "tools/widl/parser.l"
 { return tDUAL; }
 	YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 271 "tools/widl/parser.l"
+#line 282 "tools/widl/parser.l"
 { return tENABLEALLOCATE; }
 	YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 272 "tools/widl/parser.l"
+#line 283 "tools/widl/parser.l"
 { return tENCODE; }
 	YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 273 "tools/widl/parser.l"
+#line 284 "tools/widl/parser.l"
 { return tENDPOINT; }
 	YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 274 "tools/widl/parser.l"
+#line 285 "tools/widl/parser.l"
 { return tENTRY; }
 	YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 275 "tools/widl/parser.l"
+#line 286 "tools/widl/parser.l"
 { return token_winrt( tEVENTADD, yytext, yylval ); }
 	YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 276 "tools/widl/parser.l"
+#line 287 "tools/widl/parser.l"
 { return token_winrt( tEVENTREMOVE, yytext, yylval ); }
 	YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 277 "tools/widl/parser.l"
+#line 288 "tools/widl/parser.l"
 { return token_winrt( tEXCLUSIVETO, yytext, yylval ); }
 	YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 278 "tools/widl/parser.l"
+#line 289 "tools/widl/parser.l"
 { return tEXPLICITHANDLE; }
 	YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 279 "tools/widl/parser.l"
+#line 290 "tools/widl/parser.l"
 { return tFAULTSTATUS; }
 	YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 280 "tools/widl/parser.l"
+#line 291 "tools/widl/parser.l"
 { return token_winrt( tFLAGS, yytext, yylval ); }
 	YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 281 "tools/widl/parser.l"
+#line 292 "tools/widl/parser.l"
 { return tFORCEALLOCATE; }
 	YY_BREAK
 case 60:
 YY_RULE_SETUP
-#line 282 "tools/widl/parser.l"
+#line 293 "tools/widl/parser.l"
 { return tFREE; }
 	YY_BREAK
 case 61:
 YY_RULE_SETUP
-#line 283 "tools/widl/parser.l"
+#line 294 "tools/widl/parser.l"
 { return tHANDLE; }
 	YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 284 "tools/widl/parser.l"
+#line 295 "tools/widl/parser.l"
 { return tHELPCONTEXT; }
 	YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 285 "tools/widl/parser.l"
+#line 296 "tools/widl/parser.l"
 { return tHELPFILE; }
 	YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 286 "tools/widl/parser.l"
+#line 297 "tools/widl/parser.l"
 { return tHELPSTRING; }
 	YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 287 "tools/widl/parser.l"
+#line 298 "tools/widl/parser.l"
 { return tHELPSTRINGCONTEXT; }
 	YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 288 "tools/widl/parser.l"
+#line 299 "tools/widl/parser.l"
 { return tHELPSTRINGDLL; }
 	YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 289 "tools/widl/parser.l"
+#line 300 "tools/widl/parser.l"
 { return tHIDDEN; }
 	YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 290 "tools/widl/parser.l"
+#line 301 "tools/widl/parser.l"
 { return tID; }
 	YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 291 "tools/widl/parser.l"
+#line 302 "tools/widl/parser.l"
 { return tIDEMPOTENT; }
 	YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 292 "tools/widl/parser.l"
+#line 303 "tools/widl/parser.l"
 { return tIGNORE; }
 	YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 293 "tools/widl/parser.l"
+#line 304 "tools/widl/parser.l"
 { return tIIDIS; }
 	YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 294 "tools/widl/parser.l"
+#line 305 "tools/widl/parser.l"
 { return tIMMEDIATEBIND; }
 	YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 295 "tools/widl/parser.l"
+#line 306 "tools/widl/parser.l"
 { return tIMPLICITHANDLE; }
 	YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 296 "tools/widl/parser.l"
+#line 307 "tools/widl/parser.l"
 { return tIN; }
 	YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 297 "tools/widl/parser.l"
+#line 308 "tools/widl/parser.l"
 { return tIN_LINE; }
 	YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 298 "tools/widl/parser.l"
+#line 309 "tools/widl/parser.l"
 { return tINPUTSYNC; }
 	YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 299 "tools/widl/parser.l"
+#line 310 "tools/widl/parser.l"
 { return tLCID; }
 	YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 300 "tools/widl/parser.l"
+#line 311 "tools/widl/parser.l"
 { return tLENGTHIS; }
 	YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 301 "tools/widl/parser.l"
+#line 312 "tools/widl/parser.l"
 { return tLICENSED; }
 	YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 302 "tools/widl/parser.l"
+#line 313 "tools/widl/parser.l"
 { return tLOCAL; }
 	YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 303 "tools/widl/parser.l"
+#line 314 "tools/widl/parser.l"
 { return token_winrt( tMARSHALINGBEHAVIOR, yytext, yylval ); }
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 304 "tools/widl/parser.l"
+#line 315 "tools/widl/parser.l"
 { return tMAYBE; }
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 305 "tools/widl/parser.l"
+#line 316 "tools/widl/parser.l"
 { return tMESSAGE; }
 	YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 306 "tools/widl/parser.l"
+#line 317 "tools/widl/parser.l"
 { return tMTA; }
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 307 "tools/widl/parser.l"
+#line 318 "tools/widl/parser.l"
 { return tNEUTRAL; }
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 308 "tools/widl/parser.l"
+#line 319 "tools/widl/parser.l"
 { return tNOCODE; }
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 309 "tools/widl/parser.l"
+#line 320 "tools/widl/parser.l"
 { return tNONBROWSABLE; }
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 310 "tools/widl/parser.l"
+#line 321 "tools/widl/parser.l"
 { return tNONCREATABLE; }
 	YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 311 "tools/widl/parser.l"
+#line 322 "tools/widl/parser.l"
 { return token_winrt( tNONE, yytext, yylval ); }
 	YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 312 "tools/widl/parser.l"
+#line 323 "tools/widl/parser.l"
 { return tNONEXTENSIBLE; }
 	YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 313 "tools/widl/parser.l"
+#line 324 "tools/widl/parser.l"
 { return tNOTIFY; }
 	YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 314 "tools/widl/parser.l"
+#line 325 "tools/widl/parser.l"
 { return tNOTIFYFLAG; }
 	YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 315 "tools/widl/parser.l"
+#line 326 "tools/widl/parser.l"
 { return tOBJECT; }
 	YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 316 "tools/widl/parser.l"
+#line 327 "tools/widl/parser.l"
 { return tODL; }
 	YY_BREAK
 case 95:
 YY_RULE_SETUP
-#line 317 "tools/widl/parser.l"
+#line 328 "tools/widl/parser.l"
 { return tOLEAUTOMATION; }
 	YY_BREAK
 case 96:
 YY_RULE_SETUP
-#line 318 "tools/widl/parser.l"
+#line 329 "tools/widl/parser.l"
 { return tOPTIMIZE; }
 	YY_BREAK
 case 97:
 YY_RULE_SETUP
-#line 319 "tools/widl/parser.l"
+#line 330 "tools/widl/parser.l"
 { return tOPTIONAL; }
 	YY_BREAK
 case 98:
 YY_RULE_SETUP
-#line 320 "tools/widl/parser.l"
+#line 331 "tools/widl/parser.l"
 { return tOUT; }
 	YY_BREAK
 case 99:
 YY_RULE_SETUP
-#line 321 "tools/widl/parser.l"
+#line 332 "tools/widl/parser.l"
 { return tOVERLOAD; }
 	YY_BREAK
 case 100:
 YY_RULE_SETUP
-#line 322 "tools/widl/parser.l"
+#line 333 "tools/widl/parser.l"
 { return tPARTIALIGNORE; }
 	YY_BREAK
 case 101:
 YY_RULE_SETUP
-#line 323 "tools/widl/parser.l"
+#line 334 "tools/widl/parser.l"
 { return tPOINTERDEFAULT; }
 	YY_BREAK
 case 102:
 YY_RULE_SETUP
-#line 324 "tools/widl/parser.l"
+#line 335 "tools/widl/parser.l"
 { return tPROGID; }
 	YY_BREAK
 case 103:
 YY_RULE_SETUP
-#line 325 "tools/widl/parser.l"
+#line 336 "tools/widl/parser.l"
 { return tPROPGET; }
 	YY_BREAK
 case 104:
 YY_RULE_SETUP
-#line 326 "tools/widl/parser.l"
+#line 337 "tools/widl/parser.l"
 { return tPROPPUT; }
 	YY_BREAK
 case 105:
 YY_RULE_SETUP
-#line 327 "tools/widl/parser.l"
+#line 338 "tools/widl/parser.l"
 { return tPROPPUTREF; }
 	YY_BREAK
 case 106:
 YY_RULE_SETUP
-#line 328 "tools/widl/parser.l"
+#line 339 "tools/widl/parser.l"
 { return tPROTECTED; }
 	YY_BREAK
 case 107:
 YY_RULE_SETUP
-#line 329 "tools/widl/parser.l"
+#line 340 "tools/widl/parser.l"
 { return tPROXY; }
 	YY_BREAK
 case 108:
 YY_RULE_SETUP
-#line 330 "tools/widl/parser.l"
+#line 341 "tools/widl/parser.l"
 { return tPTR; }
 	YY_BREAK
 case 109:
 YY_RULE_SETUP
-#line 331 "tools/widl/parser.l"
+#line 342 "tools/widl/parser.l"
 { return tPUBLIC; }
 	YY_BREAK
 case 110:
 YY_RULE_SETUP
-#line 332 "tools/widl/parser.l"
+#line 343 "tools/widl/parser.l"
 { return tRANGE; }
 	YY_BREAK
 case 111:
 YY_RULE_SETUP
-#line 333 "tools/widl/parser.l"
+#line 344 "tools/widl/parser.l"
 { return tREADONLY; }
 	YY_BREAK
 case 112:
 YY_RULE_SETUP
-#line 334 "tools/widl/parser.l"
+#line 345 "tools/widl/parser.l"
 { return tREF; }
 	YY_BREAK
 case 113:
 YY_RULE_SETUP
-#line 335 "tools/widl/parser.l"
+#line 346 "tools/widl/parser.l"
 { return tREPRESENTAS; }
 	YY_BREAK
 case 114:
 YY_RULE_SETUP
-#line 336 "tools/widl/parser.l"
+#line 347 "tools/widl/parser.l"
 { return tREQUESTEDIT; }
 	YY_BREAK
 case 115:
 YY_RULE_SETUP
-#line 337 "tools/widl/parser.l"
+#line 348 "tools/widl/parser.l"
 { return tRESTRICTED; }
 	YY_BREAK
 case 116:
 YY_RULE_SETUP
-#line 338 "tools/widl/parser.l"
+#line 349 "tools/widl/parser.l"
 { return tRETVAL; }
 	YY_BREAK
 case 117:
 YY_RULE_SETUP
-#line 339 "tools/widl/parser.l"
+#line 350 "tools/widl/parser.l"
 { return tSINGLE; }
 	YY_BREAK
 case 118:
 YY_RULE_SETUP
-#line 340 "tools/widl/parser.l"
+#line 351 "tools/widl/parser.l"
 { return tSINGLENODE; }
 	YY_BREAK
 case 119:
 YY_RULE_SETUP
-#line 341 "tools/widl/parser.l"
+#line 352 "tools/widl/parser.l"
 { return tSIZEIS; }
 	YY_BREAK
 case 120:
 YY_RULE_SETUP
-#line 342 "tools/widl/parser.l"
+#line 353 "tools/widl/parser.l"
 { return tSOURCE; }
 	YY_BREAK
 case 121:
 YY_RULE_SETUP
-#line 343 "tools/widl/parser.l"
+#line 354 "tools/widl/parser.l"
 { return token_winrt( tSTANDARD, yytext, yylval ); }
 	YY_BREAK
 case 122:
 YY_RULE_SETUP
-#line 344 "tools/widl/parser.l"
+#line 355 "tools/widl/parser.l"
 { return token_winrt( tSTATIC, yytext, yylval ); }
 	YY_BREAK
 case 123:
 YY_RULE_SETUP
-#line 345 "tools/widl/parser.l"
+#line 356 "tools/widl/parser.l"
 { return tSTRICTCONTEXTHANDLE; }
 	YY_BREAK
 case 124:
 YY_RULE_SETUP
-#line 346 "tools/widl/parser.l"
+#line 357 "tools/widl/parser.l"
 { return tSTRING; }
 	YY_BREAK
 case 125:
 YY_RULE_SETUP
-#line 347 "tools/widl/parser.l"
+#line 358 "tools/widl/parser.l"
 { return tSWITCHIS; }
 	YY_BREAK
 case 126:
 YY_RULE_SETUP
-#line 348 "tools/widl/parser.l"
+#line 359 "tools/widl/parser.l"
 { return tSWITCHTYPE; }
 	YY_BREAK
 case 127:
 YY_RULE_SETUP
-#line 349 "tools/widl/parser.l"
+#line 360 "tools/widl/parser.l"
 { return tTHREADING; }
 	YY_BREAK
 case 128:
 YY_RULE_SETUP
-#line 350 "tools/widl/parser.l"
+#line 361 "tools/widl/parser.l"
 { return tTRANSMITAS; }
 	YY_BREAK
 case 129:
 YY_RULE_SETUP
-#line 351 "tools/widl/parser.l"
+#line 362 "tools/widl/parser.l"
 { return tUIDEFAULT; }
 	YY_BREAK
 case 130:
 YY_RULE_SETUP
-#line 352 "tools/widl/parser.l"
+#line 363 "tools/widl/parser.l"
 { return tUNIQUE; }
 	YY_BREAK
 case 131:
 YY_RULE_SETUP
-#line 353 "tools/widl/parser.l"
+#line 364 "tools/widl/parser.l"
 { return tUSERMARSHAL; }
 	YY_BREAK
 case 132:
 YY_RULE_SETUP
-#line 354 "tools/widl/parser.l"
+#line 365 "tools/widl/parser.l"
 { return tUSESGETLASTERROR; }
 	YY_BREAK
 case 133:
 YY_RULE_SETUP
-#line 355 "tools/widl/parser.l"
+#line 366 "tools/widl/parser.l"
 { return tUUID; }
 	YY_BREAK
 case 134:
 YY_RULE_SETUP
-#line 356 "tools/widl/parser.l"
+#line 367 "tools/widl/parser.l"
 { return tV1ENUM; }
 	YY_BREAK
 case 135:
 YY_RULE_SETUP
-#line 357 "tools/widl/parser.l"
+#line 368 "tools/widl/parser.l"
 { return tVARARG; }
 	YY_BREAK
 case 136:
 YY_RULE_SETUP
-#line 358 "tools/widl/parser.l"
+#line 369 "tools/widl/parser.l"
 { return tVERSION; }
 	YY_BREAK
 case 137:
 YY_RULE_SETUP
-#line 359 "tools/widl/parser.l"
+#line 370 "tools/widl/parser.l"
 { return tVIPROGID; }
 	YY_BREAK
 case 138:
 YY_RULE_SETUP
-#line 360 "tools/widl/parser.l"
+#line 371 "tools/widl/parser.l"
 { return tWIREMARSHAL; }
 	YY_BREAK
 
 
 case 139:
 YY_RULE_SETUP
-#line 364 "tools/widl/parser.l"
+#line 375 "tools/widl/parser.l"
 { yy_push_state( PP_PRAGMA ); }
 	YY_BREAK
 case 140:
 YY_RULE_SETUP
-#line 365 "tools/widl/parser.l"
+#line 376 "tools/widl/parser.l"
 { return tPRAGMA_WARNING; }
 	YY_BREAK
 case 141:
 YY_RULE_SETUP
-#line 367 "tools/widl/parser.l"
+#line 378 "tools/widl/parser.l"
 {
                                                     yylval->dbl = strtod( yytext, NULL );
                                                     return aDOUBLE;
@@ -3013,392 +3024,392 @@
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 373 "tools/widl/parser.l"
+#line 384 "tools/widl/parser.l"
 return tSAFEARRAY;
 	YY_BREAK
 
 case 143:
 YY_RULE_SETUP
-#line 376 "tools/widl/parser.l"
+#line 387 "tools/widl/parser.l"
 { yy_push_state(PP_LINE); }
 	YY_BREAK
 case 144:
 YY_RULE_SETUP
-#line 377 "tools/widl/parser.l"
+#line 388 "tools/widl/parser.l"
 { yy_push_state(ATTR); return '['; }
 	YY_BREAK
 case 145:
 YY_RULE_SETUP
-#line 379 "tools/widl/parser.l"
+#line 390 "tools/widl/parser.l"
 { return tFALSE; }
 	YY_BREAK
 case 146:
 YY_RULE_SETUP
-#line 380 "tools/widl/parser.l"
+#line 391 "tools/widl/parser.l"
 { return tNULL; }
 	YY_BREAK
 case 147:
 YY_RULE_SETUP
-#line 381 "tools/widl/parser.l"
+#line 392 "tools/widl/parser.l"
 { return tTRUE; }
 	YY_BREAK
 case 148:
 YY_RULE_SETUP
-#line 382 "tools/widl/parser.l"
+#line 393 "tools/widl/parser.l"
 { return token_str( tCDECL, "__cdecl", yylval ); }
 	YY_BREAK
 case 149:
 YY_RULE_SETUP
-#line 383 "tools/widl/parser.l"
+#line 394 "tools/widl/parser.l"
 { return token_str( tPASCAL, "__pascal", yylval ); }
 	YY_BREAK
 case 150:
 YY_RULE_SETUP
-#line 384 "tools/widl/parser.l"
+#line 395 "tools/widl/parser.l"
 { return token_str( tSTDCALL, "__stdcall", yylval ); }
 	YY_BREAK
 case 151:
 YY_RULE_SETUP
-#line 385 "tools/widl/parser.l"
+#line 396 "tools/widl/parser.l"
 { return token_str( tFASTCALL, "__fastcall", yylval ); }
 	YY_BREAK
 case 152:
 YY_RULE_SETUP
-#line 386 "tools/widl/parser.l"
+#line 397 "tools/widl/parser.l"
 { return tINT32; }
 	YY_BREAK
 case 153:
 YY_RULE_SETUP
-#line 387 "tools/widl/parser.l"
+#line 398 "tools/widl/parser.l"
 { return tINT3264; }
 	YY_BREAK
 case 154:
 YY_RULE_SETUP
-#line 388 "tools/widl/parser.l"
+#line 399 "tools/widl/parser.l"
 { return tINT64; }
 	YY_BREAK
 case 155:
 YY_RULE_SETUP
-#line 389 "tools/widl/parser.l"
+#line 400 "tools/widl/parser.l"
 { return token_winrt( tAPICONTRACT, yytext, yylval ); }
 	YY_BREAK
 case 156:
 YY_RULE_SETUP
-#line 390 "tools/widl/parser.l"
+#line 401 "tools/widl/parser.l"
 { return tBOOLEAN; }
 	YY_BREAK
 case 157:
 YY_RULE_SETUP
-#line 391 "tools/widl/parser.l"
+#line 402 "tools/widl/parser.l"
 { return tBYTE; }
 	YY_BREAK
 case 158:
 YY_RULE_SETUP
-#line 392 "tools/widl/parser.l"
+#line 403 "tools/widl/parser.l"
 { return tCASE; }
 	YY_BREAK
 case 159:
 YY_RULE_SETUP
-#line 393 "tools/widl/parser.l"
+#line 404 "tools/widl/parser.l"
 { return tCHAR; }
 	YY_BREAK
 case 160:
 YY_RULE_SETUP
-#line 394 "tools/widl/parser.l"
+#line 405 "tools/widl/parser.l"
 { return tCOCLASS; }
 	YY_BREAK
 case 161:
 YY_RULE_SETUP
-#line 395 "tools/widl/parser.l"
+#line 406 "tools/widl/parser.l"
 { return tCONST; }
 	YY_BREAK
 case 162:
 YY_RULE_SETUP
-#line 396 "tools/widl/parser.l"
+#line 407 "tools/widl/parser.l"
 { return tCPPQUOTE; }
 	YY_BREAK
 case 163:
 YY_RULE_SETUP
-#line 397 "tools/widl/parser.l"
+#line 408 "tools/widl/parser.l"
 { return token_winrt( tDECLARE, yytext, yylval ); }
 	YY_BREAK
 case 164:
 YY_RULE_SETUP
-#line 398 "tools/widl/parser.l"
+#line 409 "tools/widl/parser.l"
 { return tDEFAULT; }
 	YY_BREAK
 case 165:
 YY_RULE_SETUP
-#line 399 "tools/widl/parser.l"
+#line 410 "tools/widl/parser.l"
 { return token_winrt( tDELEGATE, yytext, yylval ); }
 	YY_BREAK
 case 166:
 YY_RULE_SETUP
-#line 400 "tools/widl/parser.l"
+#line 411 "tools/widl/parser.l"
 { return tDISPINTERFACE; }
 	YY_BREAK
 case 167:
 YY_RULE_SETUP
-#line 401 "tools/widl/parser.l"
+#line 412 "tools/widl/parser.l"
 { return tDOUBLE; }
 	YY_BREAK
 case 168:
 YY_RULE_SETUP
-#line 402 "tools/widl/parser.l"
+#line 413 "tools/widl/parser.l"
 { return tENUM; }
 	YY_BREAK
 case 169:
 YY_RULE_SETUP
-#line 403 "tools/widl/parser.l"
+#line 414 "tools/widl/parser.l"
 { return tERRORSTATUST; }
 	YY_BREAK
 case 170:
 YY_RULE_SETUP
-#line 404 "tools/widl/parser.l"
+#line 415 "tools/widl/parser.l"
 { return tEXTERN; }
 	YY_BREAK
 case 171:
 YY_RULE_SETUP
-#line 405 "tools/widl/parser.l"
+#line 416 "tools/widl/parser.l"
 { return tFLOAT; }
 	YY_BREAK
 case 172:
 YY_RULE_SETUP
-#line 406 "tools/widl/parser.l"
+#line 417 "tools/widl/parser.l"
 { return tHANDLET; }
 	YY_BREAK
 case 173:
 YY_RULE_SETUP
-#line 407 "tools/widl/parser.l"
+#line 418 "tools/widl/parser.l"
 { return tHYPER; }
 	YY_BREAK
 case 174:
 YY_RULE_SETUP
-#line 408 "tools/widl/parser.l"
+#line 419 "tools/widl/parser.l"
 { return tIMPORT; }
 	YY_BREAK
 case 175:
 YY_RULE_SETUP
-#line 409 "tools/widl/parser.l"
+#line 420 "tools/widl/parser.l"
 { return tIMPORTLIB; }
 	YY_BREAK
 case 176:
 YY_RULE_SETUP
-#line 410 "tools/widl/parser.l"
+#line 421 "tools/widl/parser.l"
 { return tINLINE; }
 	YY_BREAK
 case 177:
 YY_RULE_SETUP
-#line 411 "tools/widl/parser.l"
+#line 422 "tools/widl/parser.l"
 { return tINT; }
 	YY_BREAK
 case 178:
 YY_RULE_SETUP
-#line 412 "tools/widl/parser.l"
+#line 423 "tools/widl/parser.l"
 { return tINTERFACE; }
 	YY_BREAK
 case 179:
 YY_RULE_SETUP
-#line 413 "tools/widl/parser.l"
+#line 424 "tools/widl/parser.l"
 { return tLIBRARY; }
 	YY_BREAK
 case 180:
 YY_RULE_SETUP
-#line 414 "tools/widl/parser.l"
+#line 425 "tools/widl/parser.l"
 { return tLONG; }
 	YY_BREAK
 case 181:
 YY_RULE_SETUP
-#line 415 "tools/widl/parser.l"
+#line 426 "tools/widl/parser.l"
 { return tMETHODS; }
 	YY_BREAK
 case 182:
 YY_RULE_SETUP
-#line 416 "tools/widl/parser.l"
+#line 427 "tools/widl/parser.l"
 { return tMODULE; }
 	YY_BREAK
 case 183:
 YY_RULE_SETUP
-#line 417 "tools/widl/parser.l"
+#line 428 "tools/widl/parser.l"
 { return token_winrt( tNAMESPACE, yytext, yylval ); }
 	YY_BREAK
 case 184:
 YY_RULE_SETUP
-#line 418 "tools/widl/parser.l"
+#line 429 "tools/widl/parser.l"
 { return tPROPERTIES; }
 	YY_BREAK
 case 185:
 YY_RULE_SETUP
-#line 419 "tools/widl/parser.l"
+#line 430 "tools/widl/parser.l"
 { return tREGISTER; }
 	YY_BREAK
 case 186:
 YY_RULE_SETUP
-#line 420 "tools/widl/parser.l"
+#line 431 "tools/widl/parser.l"
 { return token_winrt( tREQUIRES, yytext, yylval ); }
 	YY_BREAK
 case 187:
 YY_RULE_SETUP
-#line 421 "tools/widl/parser.l"
+#line 432 "tools/widl/parser.l"
 { return token_winrt( tRUNTIMECLASS, yytext, yylval ); }
 	YY_BREAK
 case 188:
 YY_RULE_SETUP
-#line 422 "tools/widl/parser.l"
+#line 433 "tools/widl/parser.l"
 { return tSHORT; }
 	YY_BREAK
 case 189:
 YY_RULE_SETUP
-#line 423 "tools/widl/parser.l"
+#line 434 "tools/widl/parser.l"
 { return tSIGNED; }
 	YY_BREAK
 case 190:
 YY_RULE_SETUP
-#line 424 "tools/widl/parser.l"
+#line 435 "tools/widl/parser.l"
 { return tSIZEOF; }
 	YY_BREAK
 case 191:
 YY_RULE_SETUP
-#line 425 "tools/widl/parser.l"
+#line 436 "tools/widl/parser.l"
 { return tSMALL; }
 	YY_BREAK
 case 192:
 YY_RULE_SETUP
-#line 426 "tools/widl/parser.l"
+#line 437 "tools/widl/parser.l"
 { return tSTATIC; }
 	YY_BREAK
 case 193:
 YY_RULE_SETUP
-#line 427 "tools/widl/parser.l"
+#line 438 "tools/widl/parser.l"
 { return tSTRUCT; }
 	YY_BREAK
 case 194:
 YY_RULE_SETUP
-#line 428 "tools/widl/parser.l"
+#line 439 "tools/widl/parser.l"
 { return tSWITCH; }
 	YY_BREAK
 case 195:
 YY_RULE_SETUP
-#line 429 "tools/widl/parser.l"
+#line 440 "tools/widl/parser.l"
 { return tTYPEDEF; }
 	YY_BREAK
 case 196:
 YY_RULE_SETUP
-#line 430 "tools/widl/parser.l"
+#line 441 "tools/widl/parser.l"
 { return tUNION; }
 	YY_BREAK
 case 197:
 YY_RULE_SETUP
-#line 431 "tools/widl/parser.l"
+#line 442 "tools/widl/parser.l"
 { return tUNSIGNED; }
 	YY_BREAK
 case 198:
 YY_RULE_SETUP
-#line 432 "tools/widl/parser.l"
+#line 443 "tools/widl/parser.l"
 { return tVOID; }
 	YY_BREAK
 case 199:
 YY_RULE_SETUP
-#line 433 "tools/widl/parser.l"
+#line 444 "tools/widl/parser.l"
 { return tWCHAR; }
 	YY_BREAK
 case 200:
 YY_RULE_SETUP
-#line 435 "tools/widl/parser.l"
+#line 446 "tools/widl/parser.l"
 { return token_ident( yytext, yylval ); }
 	YY_BREAK
 case 201:
 YY_RULE_SETUP
-#line 437 "tools/widl/parser.l"
+#line 448 "tools/widl/parser.l"
 { return token_num( yytext, yylval, TRUE ); }
 	YY_BREAK
 case 202:
 YY_RULE_SETUP
-#line 438 "tools/widl/parser.l"
+#line 449 "tools/widl/parser.l"
 { return token_num( yytext, yylval, FALSE ); }
 	YY_BREAK
 case 203:
 /* rule 203 can match eol */
 YY_RULE_SETUP
-#line 440 "tools/widl/parser.l"
+#line 451 "tools/widl/parser.l"
 { return token_str( aWSTRING, yytext + 1, yylval ); }
 	YY_BREAK
 case 204:
 /* rule 204 can match eol */
 YY_RULE_SETUP
-#line 441 "tools/widl/parser.l"
+#line 452 "tools/widl/parser.l"
 { return token_str( aSTRING, yytext, yylval ); }
 	YY_BREAK
 case 205:
 /* rule 205 can match eol */
 YY_RULE_SETUP
-#line 442 "tools/widl/parser.l"
+#line 453 "tools/widl/parser.l"
 { return token_str( aSQSTRING, yytext, yylval ); }
 	YY_BREAK
 case 206:
 /* rule 206 can match eol */
 YY_RULE_SETUP
-#line 444 "tools/widl/parser.l"
+#line 455 "tools/widl/parser.l"
 { end_of_line( yylloc ); }
 	YY_BREAK
 case 207:
 YY_RULE_SETUP
-#line 445 "tools/widl/parser.l"
+#line 456 "tools/widl/parser.l"
 {}
 	YY_BREAK
 case 208:
 YY_RULE_SETUP
-#line 446 "tools/widl/parser.l"
+#line 457 "tools/widl/parser.l"
 { return SHL; }
 	YY_BREAK
 case 209:
 YY_RULE_SETUP
-#line 447 "tools/widl/parser.l"
+#line 458 "tools/widl/parser.l"
 { return SHR; }
 	YY_BREAK
 case 210:
 YY_RULE_SETUP
-#line 448 "tools/widl/parser.l"
+#line 459 "tools/widl/parser.l"
 { return MEMBERPTR; }
 	YY_BREAK
 case 211:
 YY_RULE_SETUP
-#line 449 "tools/widl/parser.l"
+#line 460 "tools/widl/parser.l"
 { return EQUALITY; }
 	YY_BREAK
 case 212:
 YY_RULE_SETUP
-#line 450 "tools/widl/parser.l"
+#line 461 "tools/widl/parser.l"
 { return INEQUALITY; }
 	YY_BREAK
 case 213:
 YY_RULE_SETUP
-#line 451 "tools/widl/parser.l"
+#line 462 "tools/widl/parser.l"
 { return GREATEREQUAL; }
 	YY_BREAK
 case 214:
 YY_RULE_SETUP
-#line 452 "tools/widl/parser.l"
+#line 463 "tools/widl/parser.l"
 { return LESSEQUAL; }
 	YY_BREAK
 case 215:
 YY_RULE_SETUP
-#line 453 "tools/widl/parser.l"
+#line 464 "tools/widl/parser.l"
 { return LOGICALOR; }
 	YY_BREAK
 case 216:
 YY_RULE_SETUP
-#line 454 "tools/widl/parser.l"
+#line 465 "tools/widl/parser.l"
 { return LOGICALAND; }
 	YY_BREAK
 case 217:
 YY_RULE_SETUP
-#line 455 "tools/widl/parser.l"
+#line 466 "tools/widl/parser.l"
 { return ELLIPSIS; }
 	YY_BREAK
 case 218:
 YY_RULE_SETUP
-#line 456 "tools/widl/parser.l"
+#line 467 "tools/widl/parser.l"
 { return yytext[0]; }
 	YY_BREAK
 
@@ -3407,7 +3418,7 @@
 case YY_STATE_EOF(PP_LINE):
 case YY_STATE_EOF(PP_FILE):
 case YY_STATE_EOF(PP_PRAGMA):
-#line 459 "tools/widl/parser.l"
+#line 470 "tools/widl/parser.l"
 {
                             if (!list_empty( &import_stack ))
                                 return aEOF;
@@ -3421,10 +3432,10 @@
 	YY_BREAK
 case 219:
 YY_RULE_SETUP
-#line 469 "tools/widl/parser.l"
+#line 480 "tools/widl/parser.l"
 ECHO;
 	YY_BREAK
-#line 3427 "tools/widl/parser.yy.c"
+#line 3438 "tools/widl/parser.yy.c"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -4435,7 +4446,7 @@
 
 #define YYTABLES_NAME "yytables"
 
-#line 469 "tools/widl/parser.l"
+#line 480 "tools/widl/parser.l"
 
 
 static void print_imports(void)
diff --git a/mingw-w64-tools/widl/src/register.c b/mingw-w64-tools/widl/src/register.c
index c5600c9..9ad0314 100644
--- a/mingw-w64-tools/widl/src/register.c
+++ b/mingw-w64-tools/widl/src/register.c
@@ -112,7 +112,9 @@
 {
     const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID );
     const struct uuid *uuid = get_attrp( iface->attrs, ATTR_UUID );
-    unsigned int version = get_attrv( typelib->attrs, ATTR_VERSION );
+    unsigned short major, minor;
+
+    get_version( typelib->attrs, &major, &minor );
 
     if (!uuid) return;
     if (!is_object( iface )) return;
@@ -121,9 +123,9 @@
     indent++;
     put_str( indent, "ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'\n" );
     put_str( indent, "ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'\n" );
-    if (version)
+    if (major || minor)
         put_str( indent, "TypeLib = s '%s' { val Version = s '%u.%u' }\n",
-                 format_uuid( typelib_uuid ), MAJORVERSION(version), MINORVERSION(version) );
+                 format_uuid( typelib_uuid ), major, minor );
     else
         put_str( indent, "TypeLib = s '%s'", format_uuid( typelib_uuid ));
     indent--;
@@ -145,7 +147,9 @@
     const char *progid = get_attrp( class->attrs, ATTR_PROGID );
     const char *vi_progid = get_attrp( class->attrs, ATTR_VIPROGID );
     const char *threading = get_coclass_threading( class );
-    unsigned int version = get_attrv( class->attrs, ATTR_VERSION );
+    unsigned short major, minor;
+
+    get_version( class->attrs, &major, &minor );
 
     if (!uuid) return 0;
     if (typelib && !threading && !progid) return 0;
@@ -160,9 +164,10 @@
     {
         const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID );
         put_str( indent, "TypeLib = s '%s'\n", format_uuid( typelib_uuid ));
-        if (!version) version = get_attrv( typelib->attrs, ATTR_VERSION );
+        if (!(major && minor))
+            get_version( typelib->attrs, &major, &minor );
     }
-    if (version) put_str( indent, "Version = s '%u.%u'\n", MAJORVERSION(version), MINORVERSION(version) );
+    if (major || minor) put_str( indent, "Version = s '%u.%u'\n", major, minor );
     if (vi_progid) put_str( indent, "VersionIndependentProgId = s '%s'\n", vi_progid );
     put_str( --indent, "}\n" );
     return 1;
@@ -336,12 +341,14 @@
     const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID );
     const char *descr = get_attrp( typelib->attrs, ATTR_HELPSTRING );
     const expr_t *lcid_expr = get_attrp( typelib->attrs, ATTR_LIBLCID );
-    unsigned int version = get_attrv( typelib->attrs, ATTR_VERSION );
+    unsigned short major, minor;
     unsigned int flags = 0;
     char id_part[12] = "";
     char *resname = typelib_name;
     expr_t *expr;
 
+    get_version( typelib->attrs, &major, &minor );
+
     if (is_attr( typelib->attrs, ATTR_RESTRICTED )) flags |= 1; /* LIBFLAG_FRESTRICTED */
     if (is_attr( typelib->attrs, ATTR_CONTROL )) flags |= 2; /* LIBFLAG_FCONTROL */
     if (is_attr( typelib->attrs, ATTR_HIDDEN )) flags |= 4; /* LIBFLAG_FHIDDEN */
@@ -353,8 +360,7 @@
     put_str( indent++, "{\n" );
     put_str( indent, "NoRemove '%s'\n", format_uuid( typelib_uuid ));
     put_str( indent++, "{\n" );
-    put_str( indent, "'%u.%u' = s '%s'\n",
-             MAJORVERSION(version), MINORVERSION(version), descr ? descr : typelib->name );
+    put_str( indent, "'%u.%u' = s '%s'\n", major, minor, descr ? descr : typelib->name );
     put_str( indent++, "{\n" );
     expr = get_attrp( typelib->attrs, ATTR_ID );
     if (expr)
diff --git a/mingw-w64-tools/widl/src/server.c b/mingw-w64-tools/widl/src/server.c
index 8bc179f..4c72b10 100644
--- a/mingw-w64-tools/widl/src/server.c
+++ b/mingw-w64-tools/widl/src/server.c
@@ -266,9 +266,11 @@
 
 static void write_dispatchtable(type_t *iface)
 {
-    unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
     unsigned int method_count = 0;
     const statement_t *stmt;
+    unsigned short major, minor;
+
+    get_version( iface->attrs, &major, &minor );
 
     print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name);
     print_server("{\n");
@@ -286,7 +288,7 @@
     print_server("0\n");
     indent--;
     print_server("};\n");
-    print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
+    print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, major, minor);
     print_server("{\n");
     indent++;
     print_server("%u,\n", method_count);
@@ -403,13 +405,15 @@
 
 static void write_serverinterfacedecl(type_t *iface)
 {
-    unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
     struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID);
     const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT);
+    unsigned short major, minor;
+
+    get_version( iface->attrs, &major, &minor );
 
     if (endpoints) write_endpoints( server, iface->name, endpoints );
 
-    print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
+    print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, major, minor);
     print_server( "static const MIDL_SERVER_INFO %s_ServerInfo;\n", iface->name );
     fprintf(server, "\n");
     print_server("static const RPC_SERVER_INTERFACE %s___RpcServerInterface =\n", iface->name );
@@ -419,9 +423,9 @@
     print_server("{{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n",
                  uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
                  uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
-                 uuid->Data4[7], MAJORVERSION(ver), MINORVERSION(ver));
+                 uuid->Data4[7], major, minor);
     print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
-    print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
+    print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, major, minor);
     if (endpoints)
     {
         print_server("%u,\n", list_count(endpoints));
@@ -442,7 +446,7 @@
                      iface->name, iface->name);
     else
         print_server("RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
-                     prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name);
+                     prefix_server, iface->name, major, minor, iface->name);
     fprintf(server, "\n");
 }
 
diff --git a/mingw-w64-tools/widl/src/typegen.c b/mingw-w64-tools/widl/src/typegen.c
index 6d7ccd3..76d7a2b 100644
--- a/mingw-w64-tools/widl/src/typegen.c
+++ b/mingw-w64-tools/widl/src/typegen.c
@@ -4909,7 +4909,7 @@
                 fprintf(file, "(*%s)", var->name);
             } else
                 fprintf(file, "%s", var->name);
-            write_type_right(file, var->declspec.type, FALSE);
+            write_type_right( file, var->declspec.type, false );
             fprintf(file, ";\n");
 
             if (decl_indirect(var->declspec.type))
@@ -5064,7 +5064,7 @@
     {
         print_file(file, 2, "%s", "");
         init_param_struct_declspec( &declspec, &arg->declspec );
-        write_type_left( file, &declspec, NAME_DEFAULT, false, TRUE );
+        write_type_left( file, &declspec, NAME_DEFAULT );
         if (needs_space_after( arg->declspec.type )) fputc( ' ', file );
         if (is_array( arg->declspec.type ) && !type_array_is_decl_as_ptr( arg->declspec.type )) fputc( '*', file );
 
@@ -5081,7 +5081,7 @@
     {
         print_file(file, 2, "%s", "");
         init_param_struct_declspec( &declspec, &retval->declspec );
-        write_type_left( file, &declspec, NAME_DEFAULT, false, TRUE );
+        write_type_left( file, &declspec, NAME_DEFAULT );
         if (needs_space_after( retval->declspec.type )) fputc( ' ', file );
         if (!is_array( retval->declspec.type ) && !is_ptr( retval->declspec.type ) &&
             type_memsize( retval->declspec.type ) != pointer_size)
@@ -5132,9 +5132,9 @@
         {
             decl_spec_t ds = {.type = (type_t *)eval->cont_type};
             print_file(file, 1, "%s", "");
-            write_type_left(file, &ds, NAME_DEFAULT, false, TRUE);
+            write_type_left( file, &ds, NAME_DEFAULT );
             fprintf(file, " *%s = (", var_name);
-            write_type_left(file, &ds, NAME_DEFAULT, false, TRUE);
+            write_type_left( file, &ds, NAME_DEFAULT );
             fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff);
         }
         print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
diff --git a/mingw-w64-tools/widl/src/typetree.c b/mingw-w64-tools/widl/src/typetree.c
index 441b6cd..c77efbc 100644
--- a/mingw-w64-tools/widl/src/typetree.c
+++ b/mingw-w64-tools/widl/src/typetree.c
@@ -96,71 +96,342 @@
     return NULL;
 }
 
-const char *type_get_name(const type_t *type, enum name_type name_type)
+const char *type_get_record_specifier( type_t *type )
 {
-    switch(name_type) {
-    case NAME_DEFAULT:
-        return type->qualified_name ? type->qualified_name : type->name;
-    case NAME_C:
-        return type->c_name ? type->c_name : type->name;
+    switch (type_get_type_detect_alias( type ))
+    {
+    case TYPE_ENUM:               return "enum";
+    case TYPE_STRUCT:             return "struct";
+    case TYPE_ENCAPSULATED_UNION: return "struct";
+    case TYPE_UNION:              return "union";
+    default: assert( 0 ); break; /* shouldn't be here */
     }
-
-    assert(0);
-    return NULL;
 }
 
-static size_t append_namespace(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *separator, const char *abi_prefix)
+const char *type_get_name( const type_t *type, enum name_type name_type, bool record )
+{
+    const char *name;
+    char *args;
+
+    switch (name_type)
+    {
+    case NAME_DEFAULT: name = type->qualified_name ? type->qualified_name : type->name; break;
+    case NAME_C: name = type->c_name ? type->c_name : type->name; break;
+    default: assert(0);
+    }
+
+    if (type_is_alias( type )) return name;
+    switch (type_get_type_detect_alias( type ))
+    {
+    case TYPE_ALIAS:              return NULL;
+    case TYPE_APICONTRACT:        return NULL;
+    case TYPE_BASIC:              return NULL;
+    case TYPE_BITFIELD:           return NULL;
+    case TYPE_FUNCTION:           return NULL;
+    case TYPE_POINTER:            return NULL;
+
+    case TYPE_ENCAPSULATED_UNION: return record ? name : NULL;
+    case TYPE_ENUM:               return record ? name : NULL;
+    case TYPE_STRUCT:             return record ? name : NULL;
+    case TYPE_UNION:              return record ? name : NULL;
+
+    case TYPE_COCLASS:            return name;
+    case TYPE_INTERFACE:          return name;
+    case TYPE_MODULE:             return name;
+    case TYPE_VOID:               return "void";
+    case TYPE_PARAMETER:          return name;
+
+    case TYPE_RUNTIMECLASS:
+        return type_get_name( type_runtimeclass_get_default_iface( type, TRUE ), name_type, false );
+    case TYPE_DELEGATE:
+        return type_get_name( type_delegate_get_iface( type ), name_type, false );
+
+    case TYPE_ARRAY:
+        if (type->name && type_array_is_decl_as_ptr( type )) return type->name;
+        return NULL;
+
+    case TYPE_PARAMETERIZED_TYPE:
+    {
+        type_t *iface = type_parameterized_type_get_real_type( type );
+        if (type_get_type( iface ) == TYPE_DELEGATE) iface = type_delegate_get_iface( iface );
+        args = format_parameterized_type_args( type, "", "_logical" );
+        name = strmake( "%s<%s>", iface->name, args );
+        free( args );
+        return name;
+    }
+    }
+
+    /* shouldn't be here */
+    assert(0);
+}
+
+void append_basic_type( struct strbuf *str, const type_t *type )
+{
+    int sign = type_basic_get_sign( type );
+    const char *prefix = sign > 0 ? "unsigned " : sign < 0 ? "signed " : "";
+
+    switch (type_basic_get_type( type ))
+    {
+    case TYPE_BASIC_INT8:            return strappend( str, "%ssmall", prefix );
+    case TYPE_BASIC_INT16:           return strappend( str, "%sshort", prefix );
+    case TYPE_BASIC_INT:             return strappend( str, "%sint", prefix );
+    case TYPE_BASIC_INT3264:         return strappend( str, "%s__int3264", prefix );
+    case TYPE_BASIC_BYTE:            return strappend( str, "%sbyte", prefix );
+    case TYPE_BASIC_CHAR:            return strappend( str, "%schar", prefix );
+    case TYPE_BASIC_WCHAR:           return strappend( str, "%swchar_t", prefix );
+    case TYPE_BASIC_FLOAT:           return strappend( str, "%sfloat", prefix );
+    case TYPE_BASIC_DOUBLE:          return strappend( str, "%sdouble", prefix );
+    case TYPE_BASIC_ERROR_STATUS_T:  return strappend( str, "%serror_status_t", prefix );
+    case TYPE_BASIC_HANDLE:          return strappend( str, "%shandle_t", prefix );
+    case TYPE_BASIC_INT32:           return strappend( str, sign > 0 ? "UINT32" : "INT32" );
+    case TYPE_BASIC_LONG:            return strappend( str, sign > 0 ? "ULONG" : "LONG" );
+    case TYPE_BASIC_INT64:           return strappend( str, sign > 0 ? "UINT64" : "INT64" );
+    case TYPE_BASIC_HYPER:           return strappend( str, sign > 0 ? "MIDL_uhyper" : "hyper" );
+    }
+}
+
+bool needs_space_after( const type_t *type )
+{
+    if (type_is_alias( type )) return true;
+    if (type_get_type( type ) == TYPE_POINTER) return false;
+    if (type_get_type( type ) != TYPE_ARRAY) return true;
+    if (!type_array_is_decl_as_ptr( type )) return true;
+    if (type->name) return true;
+    return false;
+}
+
+bool decl_needs_parens( const type_t *type )
+{
+    if (type_is_alias( type )) return false;
+    if (is_array( type ) && !type_array_is_decl_as_ptr( type )) return true;
+    if (type_get_type( type ) == TYPE_FUNCTION) return true;
+    return false;
+}
+
+void append_pointer_left( struct strbuf *str, const type_t *type, const char *callconv )
+{
+    if (needs_space_after( type )) strappend( str, " " );
+    if (decl_needs_parens( type )) strappend( str, "(" );
+    if (callconv && type_get_type_detect_alias( type ) == TYPE_FUNCTION)
+    {
+        const char *explicit_callconv = get_attrp( type->attrs, ATTR_CALLCONV );
+        if (explicit_callconv) callconv = explicit_callconv;
+        if (*callconv) strappend( str, "%s ", callconv );
+    }
+    strappend( str, "*" );
+}
+
+void append_type_left( struct strbuf *str, const decl_spec_t *decl_spec, enum name_type name_type,
+                       const char *callconv )
+{
+    bool is_const = !!(decl_spec->qualifier & TYPE_QUALIFIER_CONST);
+    type_t *type = decl_spec->type;
+    const char *name;
+
+    if (decl_spec->func_specifier & FUNCTION_SPECIFIER_INLINE) strappend( str, "inline " );
+    if (is_const && (type_is_alias( type ) || !is_ptr( type ))) strappend( str, "const " );
+
+    if ((name = type_get_name( type, name_type, false ))) return strappend( str, "%s", name );
+
+    switch (type_get_type_detect_alias( type ))
+    {
+    case TYPE_ENUM:
+    case TYPE_STRUCT:
+    case TYPE_ENCAPSULATED_UNION:
+    case TYPE_UNION:
+    {
+        const char *specifier = type_get_record_specifier( type ), *decl_name;
+        if (!(decl_name = type_get_decl_name( type, name_type ))) decl_name = "";
+        return strappend( str, "%s %s", specifier, decl_name );
+    }
+
+    case TYPE_POINTER:
+        append_type_left( str, type_pointer_get_ref( type ), name_type, NULL );
+        append_pointer_left( str, type_pointer_get_ref_type( type ), callconv );
+        if (is_const) strappend( str, "const " );
+        return;
+
+    case TYPE_ARRAY:
+    {
+        bool as_pointer = type_array_is_decl_as_ptr( type );
+        append_type_left( str, type_array_get_element( type ), name_type, as_pointer ? NULL : callconv );
+        if (as_pointer) append_pointer_left( str, type_array_get_element_type( type ), callconv );
+        return;
+    }
+
+    case TYPE_FUNCTION:
+        append_type_left( str, type_function_get_ret( type ), name_type, callconv );
+
+        /* A pointer to a function has to write the calling convention inside
+         * the parentheses. There's no way to handle that here, so we have to
+         * use an extra parameter to tell us whether to write the calling
+         * convention or not. */
+        if (callconv)
+        {
+            const char *explicit_callconv = get_attrp( type->attrs, ATTR_CALLCONV );
+            if (explicit_callconv) callconv = explicit_callconv;
+            if (*callconv) strappend( str, " %s ", callconv );
+        }
+        return;
+
+    case TYPE_BASIC:
+        return append_basic_type( str, type );
+
+    case TYPE_BITFIELD:
+        type = type_bitfield_get_field( type );
+        if (!type_is_alias( type )) return append_basic_type( str, type );
+        return strappend( str, "%s", type_get_name( type, name_type, false ) );
+
+    case TYPE_INTERFACE:
+    case TYPE_MODULE:
+    case TYPE_COCLASS:
+    case TYPE_RUNTIMECLASS:
+    case TYPE_DELEGATE:
+    case TYPE_VOID:
+    case TYPE_ALIAS:
+    case TYPE_PARAMETERIZED_TYPE:
+    case TYPE_PARAMETER:
+        /* handled elsewhere */
+        assert( 0 );
+        break;
+
+    case TYPE_APICONTRACT:
+        /* shouldn't be here */
+        assert( 0 );
+        break;
+    }
+}
+
+void append_type_right( struct strbuf *str, const type_t *type, const char *callconv, bool is_field )
+{
+    if (type_is_alias( type )) return;
+
+    switch (type_get_type( type ))
+    {
+    case TYPE_ARRAY:
+    {
+        type_t *elem = type_array_get_element_type( type );
+        if (type_array_is_decl_as_ptr( type ))
+        {
+            if (decl_needs_parens( elem )) strappend( str, ")" );
+        }
+        else
+        {
+            if (is_conformant_array( type )) strappend( str, "[%s]", is_field ? "1" : "" );
+            else strappend( str, "[%u]", type_array_get_dim( type ) );
+        }
+        append_type_right( str, elem, callconv, false );
+        break;
+    }
+
+    case TYPE_FUNCTION:
+    {
+        const var_list_t *args = type_function_get_args( type );
+        const var_t *arg;
+
+        strappend( str, "(" );
+        if (!args) strappend( str, "void" );
+        else LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+        {
+            append_declspec( str, &arg->declspec, NAME_DEFAULT, callconv, false, arg->name );
+            if (arg->entry.next != args) strappend( str, "," );
+        }
+        strappend( str, ")" );
+
+        append_type_right( str, type_function_get_rettype( type ), callconv, false );
+        break;
+    }
+
+    case TYPE_POINTER:
+    {
+        type_t *ref = type_pointer_get_ref_type( type );
+        if (decl_needs_parens( ref )) strappend( str, ")" );
+        append_type_right( str, ref, callconv, false );
+        break;
+    }
+
+    case TYPE_BITFIELD:
+        strappend( str, " : %u", type_bitfield_get_bits( type )->cval );
+        break;
+
+    case TYPE_VOID:
+    case TYPE_BASIC:
+    case TYPE_ENUM:
+    case TYPE_STRUCT:
+    case TYPE_ENCAPSULATED_UNION:
+    case TYPE_UNION:
+    case TYPE_ALIAS:
+    case TYPE_MODULE:
+    case TYPE_COCLASS:
+    case TYPE_INTERFACE:
+    case TYPE_RUNTIMECLASS:
+    case TYPE_DELEGATE:
+    case TYPE_PARAMETERIZED_TYPE:
+    case TYPE_PARAMETER: break;
+    case TYPE_APICONTRACT:
+        /* not supposed to be here */
+        assert( 0 );
+        break;
+    }
+}
+
+void append_declspec( struct strbuf *str, const decl_spec_t *decl_spec, enum name_type name_type,
+                      const char *callconv, bool is_field, const char *name )
+{
+    const type_t *type = decl_spec->type;
+    if (type) append_type_left( str, decl_spec, name_type, callconv );
+    if (name) strappend( str, "%s%s", !type || needs_space_after( type ) ? " " : "", name );
+    if (type) append_type_right( str, type, callconv, is_field );
+}
+
+static void append_namespace( struct strbuf *str, const struct namespace *namespace,
+                              const char *separator, const char *abi_prefix )
 {
     int nested = namespace && !is_global_namespace(namespace);
     const char *name = nested ? namespace->name : abi_prefix;
-    size_t n = 0;
-    if (!name) return 0;
-    if (nested) n += append_namespace(buf, len, pos + n, namespace->parent, separator, abi_prefix);
-    n += strappend(buf, len, pos + n, "%s%s", name, separator);
-    return n;
+    if (!name) return;
+    if (nested) append_namespace( str, namespace->parent, separator, abi_prefix );
+    strappend( str, "%s%s", name, separator );
 }
 
-static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *prefix,
-                                const char *separator, const char *suffix, const char *abi_prefix)
+static void append_namespaces( struct strbuf *str, const struct namespace *namespace, const char *prefix,
+                               const char *separator, const char *suffix, const char *abi_prefix )
 {
     int nested = namespace && !is_global_namespace(namespace);
-    size_t n = 0;
-    n += strappend(buf, len, pos + n, "%s", prefix);
-    if (nested) n += append_namespace(buf, len, pos + n, namespace, separator, abi_prefix);
-    if (suffix) n += strappend(buf, len, pos + n, "%s", suffix);
+    strappend( str, "%s", prefix );
+    if (nested) append_namespace( str, namespace, separator, abi_prefix );
+    if (suffix) strappend( str, "%s", suffix );
     else if (nested)
     {
-        n -= strlen(separator);
-        (*buf)[n] = 0;
+        str->pos -= strlen( separator );
+        str->buf[str->pos] = 0;
     }
-    return n;
 }
 
-static size_t append_pointer_stars(char **buf, size_t *len, size_t pos, type_t *type)
+static void append_pointer_stars( struct strbuf *str, type_t *type )
 {
-    size_t n = 0;
-    for (; type && type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) n += strappend(buf, len, pos + n, "*");
-    return n;
+    for (; type && type_is_ptr( type ); type = type_pointer_get_ref_type( type ))
+        strappend( str, "*" );
 }
 
-static size_t append_type_signature(char **buf, size_t *len, size_t pos, type_t *type);
+static size_t append_type_signature( struct strbuf *str, type_t *type );
 
-static size_t append_var_list_signature(char **buf, size_t *len, size_t pos, var_list_t *var_list)
+static size_t append_var_list_signature( struct strbuf *str, var_list_t *var_list )
 {
     var_t *var;
     size_t n = 0;
 
-    if (!var_list) n += strappend(buf, len, pos + n, ";");
+    if (!var_list) strappend( str, ";" );
     else LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry)
     {
-        n += strappend(buf, len, pos + n, ";");
-        n += append_type_signature(buf, len, pos + n, var->declspec.type);
+        strappend( str, ";" );
+        append_type_signature( str, var->declspec.type );
     }
 
     return n;
 }
 
-static size_t append_type_signature(char **buf, size_t *len, size_t pos, type_t *type)
+static size_t append_type_signature( struct strbuf *str, type_t *type )
 {
     const struct uuid *uuid;
     size_t n = 0;
@@ -169,72 +440,71 @@
     switch (type->type_type)
     {
     case TYPE_INTERFACE:
-        if (!strcmp(type->name, "IInspectable")) n += strappend(buf, len, pos + n, "cinterface(IInspectable)");
-        else if (type->signature) n += strappend(buf, len, pos + n, "%s", type->signature);
+        if (!strcmp( type->name, "IInspectable" )) strappend( str, "cinterface(IInspectable)" );
+        else if (type->signature) strappend( str, "%s", type->signature );
         else
         {
             if (!(uuid = get_attrp( type->attrs, ATTR_UUID )))
                 error_at( &type->where, "cannot compute type signature, no uuid found for type %s.\n", type->name );
 
-            n += strappend(buf, len, pos + n, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
-                           uuid->Data1, uuid->Data2, uuid->Data3,
-                           uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3],
-                           uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]);
+            strappend( str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", uuid->Data1,
+                       uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2],
+                       uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7] );
         }
         return n;
     case TYPE_DELEGATE:
-        n += strappend(buf, len, pos + n, "delegate(");
-        n += append_type_signature(buf, len, pos + n, type_delegate_get_iface(type));
-        n += strappend(buf, len, pos + n, ")");
+        strappend( str, "delegate(" );
+        append_type_signature( str, type_delegate_get_iface( type ) );
+        strappend( str, ")" );
         return n;
     case TYPE_RUNTIMECLASS:
-        n += strappend(buf, len, pos + n, "rc(");
-        n += append_namespaces(buf, len, pos + n, type->namespace, "", ".", type->name, NULL);
-        n += strappend(buf, len, pos + n, ";");
-        n += append_type_signature(buf, len, pos + n, type_runtimeclass_get_default_iface(type, TRUE));
-        n += strappend(buf, len, pos + n, ")");
+        strappend( str, "rc(" );
+        append_namespaces( str, type->namespace, "", ".", type->name, NULL );
+        strappend( str, ";" );
+        append_type_signature( str, type_runtimeclass_get_default_iface( type, TRUE ) );
+        strappend( str, ")" );
         return n;
     case TYPE_POINTER:
-        n += append_type_signature(buf, len, pos + n, type->details.pointer.ref.type);
+        append_type_signature( str, type->details.pointer.ref.type );
         return n;
     case TYPE_ALIAS:
-        if (!strcmp(type->name, "boolean")) n += strappend(buf, len, pos + n, "b1");
-        else if (!strcmp(type->name, "GUID")) n += strappend(buf, len, pos + n, "g16");
-        else if (!strcmp(type->name, "HSTRING")) n += strappend(buf, len, pos + n, "string");
-        else n += append_type_signature(buf, len, pos + n, type->details.alias.aliasee.type);
+        if (!strcmp( type->name, "boolean" )) strappend( str, "b1" );
+        else if (!strcmp( type->name, "GUID" )) strappend( str, "g16" );
+        else if (!strcmp( type->name, "HSTRING" )) strappend( str, "string" );
+        else append_type_signature( str, type->details.alias.aliasee.type );
         return n;
     case TYPE_STRUCT:
-        n += strappend(buf, len, pos + n, "struct(");
-        n += append_namespaces(buf, len, pos + n, type->namespace, "", ".", type->name, NULL);
-        n += append_var_list_signature(buf, len, pos + n, type->details.structure->fields);
-        n += strappend(buf, len, pos + n, ")");
+        strappend( str, "struct(" );
+        append_namespaces( str, type->namespace, "", ".", type->name, NULL );
+        append_var_list_signature( str, type->details.structure->fields );
+        strappend( str, ")" );
         return n;
     case TYPE_BASIC:
         switch (type_basic_get_type(type))
         {
         case TYPE_BASIC_INT16:
-            n += strappend(buf, len, pos + n, type_basic_get_sign(type) <= 0 ? "i2" : "u2");
+            strappend( str, type_basic_get_sign( type ) <= 0 ? "i2" : "u2" );
             return n;
         case TYPE_BASIC_INT:
         case TYPE_BASIC_INT32:
         case TYPE_BASIC_LONG:
-            n += strappend(buf, len, pos + n, type_basic_get_sign(type) <= 0 ? "i4" : "u4");
+            strappend( str, type_basic_get_sign( type ) <= 0 ? "i4" : "u4" );
             return n;
         case TYPE_BASIC_INT64:
-            n += strappend(buf, len, pos + n, type_basic_get_sign(type) <= 0 ? "i8" : "u8");
+            strappend( str, type_basic_get_sign( type ) <= 0 ? "i8" : "u8" );
             return n;
         case TYPE_BASIC_INT8:
             assert(type_basic_get_sign(type) > 0); /* signature string for signed char isn't specified */
-            n += strappend(buf, len, pos + n, "u1");
+            strappend( str, "u1" );
             return n;
         case TYPE_BASIC_FLOAT:
-            n += strappend(buf, len, pos + n, "f4");
+            strappend( str, "f4" );
             return n;
         case TYPE_BASIC_DOUBLE:
-            n += strappend(buf, len, pos + n, "f8");
+            strappend( str, "f8" );
             return n;
         case TYPE_BASIC_BYTE:
-            n += strappend(buf, len, pos + n, "u1");
+            strappend( str, "u1" );
             return n;
         case TYPE_BASIC_INT3264:
         case TYPE_BASIC_CHAR:
@@ -247,11 +517,11 @@
             break;
         }
     case TYPE_ENUM:
-        n += strappend(buf, len, pos + n, "enum(");
-        n += append_namespaces(buf, len, pos + n, type->namespace, "", ".", type->name, NULL);
-        if (is_attr(type->attrs, ATTR_FLAGS)) n += strappend(buf, len, pos + n, ";u4");
-        else n += strappend(buf, len, pos + n, ";i4");
-        n += strappend(buf, len, pos + n, ")");
+        strappend( str, "enum(" );
+        append_namespaces( str, type->namespace, "", ".", type->name, NULL );
+        if (is_attr( type->attrs, ATTR_FLAGS )) strappend( str, ";u4" );
+        else strappend( str, ";i4" );
+        strappend( str, ")" );
         return n;
     case TYPE_ARRAY:
     case TYPE_ENCAPSULATED_UNION:
@@ -274,31 +544,48 @@
     return n;
 }
 
-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
+char *format_namespace( const struct namespace *namespace, const char *prefix, const char *separator,
+                        const char *suffix, const char *abi_prefix )
 {
-    size_t len = 0;
-    char *buf = NULL;
-    append_namespaces(&buf, &len, 0, namespace, prefix, separator, suffix, abi_prefix);
-    return buf;
+    struct strbuf str = {0};
+    append_namespaces( &str, namespace, prefix, separator, suffix, abi_prefix );
+    return str.buf;
 }
 
-char *format_parameterized_type_name(type_t *type, typeref_list_t *params)
+char *format_parameterized_type_name( const type_t *type, const typeref_list_t *params )
 {
-    size_t len = 0, pos = 0;
-    char *buf = NULL;
+    struct strbuf str = {0};
     typeref_t *ref;
 
-    pos += strappend(&buf, &len, pos, "%s<", type->name);
+    strappend( &str, "%s<", type->name );
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
         type = type_pointer_get_root_type(ref->type);
-        pos += strappend(&buf, &len, pos, "%s", type->qualified_name);
-        pos += append_pointer_stars(&buf, &len, pos, ref->type);
-        if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ",");
+        strappend( &str, "%s", type->qualified_name );
+        append_pointer_stars( &str, ref->type );
+        if (list_next( params, &ref->entry )) strappend( &str, "," );
     }
-    pos += strappend(&buf, &len, pos, " >");
+    strappend( &str, " >" );
 
-    return buf;
+    return str.buf;
+}
+
+char *format_parameterized_type_args( const type_t *type, const char *prefix, const char *suffix )
+{
+    struct strbuf str = {0};
+    typeref_list_t *params;
+    typeref_t *ref;
+
+    params = type->details.parameterized.params;
+    if (params) LIST_FOR_EACH_ENTRY( ref, params, typeref_t, entry )
+    {
+        assert( ref->type->type_type != TYPE_POINTER );
+        strappend( &str, "%s%s%s", prefix, ref->type->name, suffix );
+        if (list_next( params, &ref->entry )) strappend( &str, ", " );
+    }
+
+    if (!str.buf) return xstrdup( "" );
+    return str.buf;
 }
 
 static char const *parameterized_type_shorthands[][2] = {
@@ -310,109 +597,104 @@
 
 static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *params, const char *prefix, const char *separator)
 {
+    struct strbuf str = {0};
     const char *tmp, *ns_prefix = "__x_", *abi_prefix = NULL;
-    size_t len = 0, pos = 0;
-    char *buf = NULL;
     int i, count = params ? list_count(params) : 0;
     typeref_t *ref;
 
     if (!strcmp(separator, "__C")) ns_prefix = "_C";
     else if (use_abi_namespace) abi_prefix = "ABI";
 
-    pos += append_namespaces(&buf, &len, pos, type->namespace, ns_prefix, separator, "", abi_prefix);
-    pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count);
+    append_namespaces( &str, type->namespace, ns_prefix, separator, "", abi_prefix );
+    strappend( &str, "%s%s_%d", prefix, type->name, count );
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
         type = type_pointer_get_root_type(ref->type);
-        if ((tmp = type->param_name)) pos += strappend(&buf, &len, pos, "_%s", tmp);
-        else pos += append_namespaces(&buf, &len, pos, type->namespace, "_", "__C", type->name, NULL);
+        if ((tmp = type->param_name)) strappend( &str, "_%s", tmp );
+        else append_namespaces( &str, type->namespace, "_", "__C", type->name, NULL );
     }
 
     for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i)
     {
-        if ((tmp = strstr(buf, parameterized_type_shorthands[i][0])) &&
-            (tmp - buf) == strlen(ns_prefix) + (abi_prefix ? 5 : 0))
+        if ((tmp = strstr( str.buf, parameterized_type_shorthands[i][0] )) &&
+            (tmp - str.buf) == strlen( ns_prefix ) + (abi_prefix ? 5 : 0))
         {
            tmp += strlen(parameterized_type_shorthands[i][0]);
-           strcpy(buf, parameterized_type_shorthands[i][1]);
-           memmove(buf + 3, tmp, len - (tmp - buf));
+           strcpy( str.buf, parameterized_type_shorthands[i][1] );
+           memmove( str.buf + 3, tmp, str.len - (tmp - str.buf) );
         }
     }
 
-    return buf;
+    return str.buf;
 }
 
 static char *format_parameterized_type_signature(type_t *type, typeref_list_t *params)
 {
-    size_t len = 0, pos = 0;
-    char *buf = NULL;
+    struct strbuf str = {0};
     typeref_t *ref;
     const struct uuid *uuid;
 
     if (!(uuid = get_attrp( type->attrs, ATTR_UUID )))
         error_at( &type->where, "cannot compute type signature, no uuid found for type %s.\n", type->name );
 
-    pos += strappend(&buf, &len, pos, "pinterface({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
-                     uuid->Data1, uuid->Data2, uuid->Data3,
-                     uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3],
-                     uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]);
+    strappend( &str, "pinterface({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", uuid->Data1,
+               uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2],
+               uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7] );
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
-        pos += strappend(&buf, &len, pos, ";");
-        pos += append_type_signature(&buf, &len, pos, ref->type);
+        strappend( &str, ";" );
+        append_type_signature( &str, ref->type );
     }
-    pos += strappend(&buf, &len, pos, ")");
+    strappend( &str, ")" );
 
-    return buf;
+    return str.buf;
 }
 
 static char *format_parameterized_type_short_name(type_t *type, typeref_list_t *params, const char *prefix)
 {
-    size_t len = 0, pos = 0;
-    char *buf = NULL;
+    struct strbuf str = {0};
     typeref_t *ref;
 
-    pos += strappend(&buf, &len, pos, "%s%s", prefix, type->name);
+    strappend( &str, "%s%s", prefix, type->name );
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
         type = type_pointer_get_root_type(ref->type);
-        if (type->short_name) pos += strappend(&buf, &len, pos, "_%s", type->short_name);
-        else pos += strappend(&buf, &len, pos, "_%s", type->name);
+        if (type->short_name) strappend( &str, "_%s", type->short_name );
+        else strappend( &str, "_%s", type->name );
     }
 
-    return buf;
+    return str.buf;
 }
 
 static char *format_parameterized_type_impl_name(type_t *type, typeref_list_t *params, const char *prefix)
 {
-    size_t len = 0, pos = 0;
-    char *buf = NULL;
+    struct strbuf str = {0};
     typeref_t *ref;
     type_t *iface;
 
-    pos += strappend(&buf, &len, pos, "%s%s_impl<", prefix, type->name);
+    strappend( &str, "%s%s_impl<", prefix, type->name );
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
         type = type_pointer_get_root_type(ref->type);
         if (type->type_type == TYPE_RUNTIMECLASS)
         {
-            pos += strappend(&buf, &len, pos, "ABI::Windows::Foundation::Internal::AggregateType<%s", type->qualified_name);
-            pos += append_pointer_stars(&buf, &len, pos, ref->type);
+            strappend( &str, "ABI::Windows::Foundation::Internal::AggregateType<%s", type->qualified_name );
+            append_pointer_stars( &str, ref->type );
             iface = type_runtimeclass_get_default_iface(type, TRUE);
-            pos += strappend(&buf, &len, pos, ", %s", iface->qualified_name);
-            pos += append_pointer_stars(&buf, &len, pos, ref->type);
-            pos += strappend(&buf, &len, pos, " >");
+            strappend( &str, ", %s", iface->qualified_name );
+            append_pointer_stars( &str, ref->type );
+            strappend( &str, " >" );
         }
         else
         {
-            pos += strappend(&buf, &len, pos, "%s", type->qualified_name);
-            pos += append_pointer_stars(&buf, &len, pos, ref->type);
+            strappend( &str, "%s", type->qualified_name );
+            append_pointer_stars( &str, ref->type );
         }
-        if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", ");
+        if (list_next( params, &ref->entry )) strappend( &str, ", " );
     }
-    pos += strappend(&buf, &len, pos, " >");
+    strappend( &str, " >" );
 
-    return buf;
+    return str.buf;
 }
 
 type_t *type_new_function(var_list_t *args)
@@ -913,6 +1195,7 @@
 type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs, const struct location *where)
 {
     apicontract->attrs = check_apicontract_attrs(apicontract->name, attrs);
+    apicontract->attrs = append_attr(apicontract->attrs, attr_int(*where, ATTR_APICONTRACT, 1));
     define_type(apicontract, where);
     return apicontract;
 }
@@ -1192,9 +1475,9 @@
         return type;
     case TYPE_ARRAY:
         t = replace_type_parameters_in_type(type->details.array.elem.type, orig, repl);
-        if (t == t->details.array.elem.type) return type;
+        if (t == type->details.array.elem.type) return type;
         type = duptype(type, 0);
-        t->details.array.elem.type = t;
+        type->details.array.elem.type = t;
         return type;
     case TYPE_FUNCTION:
         t = duptype(type, 0);
diff --git a/mingw-w64-tools/widl/src/typetree.h b/mingw-w64-tools/widl/src/typetree.h
index 6e5c606..d49d7fe 100644
--- a/mingw-w64-tools/widl/src/typetree.h
+++ b/mingw-w64-tools/widl/src/typetree.h
@@ -84,9 +84,26 @@
 type_t *type_parameterized_type_specialize_define(type_t *type);
 int type_is_equal(const type_t *type1, const type_t *type2);
 const char *type_get_decl_name(const type_t *type, enum name_type name_type);
-const char *type_get_name(const type_t *type, enum name_type name_type);
+extern const char *type_get_record_specifier( type_t *type );
+extern const char *type_get_name( const type_t *type, enum name_type name_type, bool record );
 char *gen_name(void);
 
+extern bool needs_space_after( const type_t *type );
+extern bool decl_needs_parens( const type_t *type );
+
+extern void append_basic_type( struct strbuf *str, const type_t *type );
+extern void append_pointer_left( struct strbuf *str, const type_t *type, const char *callconv );
+extern void append_type_left( struct strbuf *str, const decl_spec_t *decl_spec, enum name_type name_type,
+                              const char *callconv );
+extern void append_type_right( struct strbuf *str, const type_t *type, const char *callconv, bool is_field );
+extern void append_declspec( struct strbuf *str, const decl_spec_t *decl_spec, enum name_type name_type,
+                             const char *callconv, bool is_field, const char *name );
+
+extern char *format_namespace( const struct namespace *namespace, const char *prefix, const char *separator,
+                               const char *suffix, const char *abi_prefix );
+extern char *format_parameterized_type_name( const type_t *type, const typeref_list_t *params );
+extern char *format_parameterized_type_args( const type_t *type, const char *prefix, const char *suffix );
+
 typeref_t *make_typeref(type_t *type);
 typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref);
 
diff --git a/mingw-w64-tools/widl/src/utils.c b/mingw-w64-tools/widl/src/utils.c
index 4f2e9d3..8d2758d 100644
--- a/mingw-w64-tools/widl/src/utils.c
+++ b/mingw-w64-tools/widl/src/utils.c
@@ -117,41 +117,25 @@
     return n;
 }
 
-size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...)
+void strappend( struct strbuf *str, const char *fmt, ... )
 {
-    size_t size;
     va_list ap;
-    char *ptr;
     int n;
 
-    assert( buf && len );
-    assert( (*len == 0 && *buf == NULL) || (*len != 0 && *buf != NULL) );
-
-    if (*buf)
-    {
-        size = *len;
-        ptr = *buf;
-    }
-    else
-    {
-        size = 100;
-        ptr = xmalloc( size );
-    }
+    assert( (str->len == 0 && str->buf == NULL) ||
+            (str->len != 0 && str->buf != NULL) );
 
     for (;;)
     {
         va_start( ap, fmt );
-        n = vsnprintf( ptr + pos, size - pos, fmt, ap );
+        n = str->len ? vsnprintf( str->buf + str->pos, str->len - str->pos, fmt, ap ) : 128;
         va_end( ap );
-        if (n == -1) size *= 2;
-        else if (pos + (size_t)n >= size) size = pos + n + 1;
-        else break;
-        ptr = xrealloc( ptr, size );
+        if (n >= 0 && n <= str->len && str->pos + n < str->len) break;
+        str->len = max( str->pos + n, str->len * 3 / 2 );
+        str->buf = xrealloc( str->buf, str->len );
     }
 
-    *len = size;
-    *buf = ptr;
-    return n;
+    str->pos += n;
 }
 
 /*******************************************************************
diff --git a/mingw-w64-tools/widl/src/utils.h b/mingw-w64-tools/widl/src/utils.h
index 2a6bc7d..5381216 100644
--- a/mingw-w64-tools/widl/src/utils.h
+++ b/mingw-w64-tools/widl/src/utils.h
@@ -31,7 +31,14 @@
 void warning_at( const struct location *, const char *s, ... ) __attribute__((format( printf, 2, 3 )));
 #define warning_loc( ... ) warning_at( NULL, ## __VA_ARGS__ )
 void chat(const char *s, ...) __attribute__((format (printf, 1, 2)));
-size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...) __attribute__((__format__ (__printf__, 4, 5 )));
+
+struct strbuf
+{
+    char *buf;
+    size_t pos;
+    size_t len;
+};
+extern void strappend( struct strbuf *str, const char *fmt, ... ) __attribute__((__format__( __printf__, 2, 3 )));
 
 size_t widl_getline(char **linep, size_t *lenp, FILE *fp);
 
@@ -41,11 +48,4 @@
 extern void flush_output_resources( const char *name );
 extern void put_pword( unsigned int val );
 extern void put_str( int indent, const char *format, ... ) __attribute__((format (printf, 2, 3)));
-
-/* typelibs expect the minor version to be stored in the higher bits and
- * major to be stored in the lower bits */
-#define MAKEVERSION(major, minor) ((((minor) & 0xffff) << 16) | ((major) & 0xffff))
-#define MAJORVERSION(version) ((version) & 0xffff)
-#define MINORVERSION(version) (((version) >> 16) & 0xffff)
-
 #endif
diff --git a/mingw-w64-tools/widl/src/widl.h b/mingw-w64-tools/widl/src/widl.h
index 08071e8..2951a6c 100644
--- a/mingw-w64-tools/widl/src/widl.h
+++ b/mingw-w64-tools/widl/src/widl.h
@@ -93,6 +93,8 @@
 extern void start_cplusplus_guard(FILE *fp);
 extern void end_cplusplus_guard(FILE *fp);
 
+extern bool is_size_param( const var_t *param, const var_list_t *args );
+
 /* attribute.c */
 
 extern attr_t *attr_int( struct location where, enum attr_type attr_type, unsigned int val );
@@ -105,6 +107,7 @@
 extern unsigned int get_attrv( const attr_list_t *list, enum attr_type attr_type );
 extern void *get_attrp( const attr_list_t *list, enum attr_type attr_type );
 extern void *get_aliaschain_attrp( const type_t *type, enum attr_type attr_type );
+extern void get_version( const attr_list_t *list, unsigned short *major, unsigned short *minor );
 
 typedef int (*map_attrs_filter_t)( attr_list_t *, const attr_t * );
 extern attr_list_t *append_attr( attr_list_t *list, attr_t *attr );
diff --git a/mingw-w64-tools/widl/src/widltypes.h b/mingw-w64-tools/widl/src/widltypes.h
index 1706f39..35a9bba 100644
--- a/mingw-w64-tools/widl/src/widltypes.h
+++ b/mingw-w64-tools/widl/src/widltypes.h
@@ -55,6 +55,7 @@
 typedef struct _user_type_t generic_handle_t;
 typedef struct _statement_t statement_t;
 typedef struct _warning_t warning_t;
+typedef struct _version_t version_t;
 
 typedef struct list attr_list_t;
 typedef struct list str_list_t;
@@ -74,6 +75,7 @@
     ATTR_AGGREGATABLE,
     ATTR_ALLOCATE,
     ATTR_ANNOTATION,
+    ATTR_APICONTRACT, /* implicit attribute */
     ATTR_APPOBJECT,
     ATTR_ASYNC,
     ATTR_ASYNCUUID,
@@ -343,10 +345,11 @@
     unsigned int ival;
     void *pval;
   } u;
+  /* metadata */
+  unsigned int md_member;
   /* parser-internal */
   struct list entry;
   struct location where;
-  unsigned int md_member;
 };
 
 struct integer
@@ -498,30 +501,11 @@
     TYPE_DELEGATE,
 };
 
-enum
-{
-    MD_ATTR_CONTRACT,
-    MD_ATTR_FLAGS,
-    MD_ATTR_APICONTRACT,
-    MD_ATTR_CONTRACTVERSION,
-    MD_ATTR_VERSION,
-    MD_ATTR_UUID,
-    MD_ATTR_EXCLUSIVETO,
-    MD_ATTR_STATIC,
-    MD_ATTR_THREADING,
-    MD_ATTR_MARSHALINGBEHAVIOR,
-    MD_ATTR_OVERLOAD,
-    MD_ATTR_DEFAULT_OVERLOAD,
-    MD_ATTR_DEPRECATED,
-    MD_ATTR_MAX,
-};
-
 struct metadata
 {
     unsigned int ref;
     unsigned int def;
     unsigned int extends;
-    unsigned int member[MD_ATTR_MAX];
     /* get/put methods */
     unsigned int class_property;
     unsigned int iface_property;
@@ -674,6 +658,11 @@
     unsigned int is_defined : 1;
 };
 
+struct _version_t {
+    unsigned short major;
+    unsigned short minor;
+};
+
 struct _warning_t {
     int num;
     struct list entry;
@@ -709,10 +698,6 @@
 var_t *make_var(char *name);
 var_list_t *append_var(var_list_t *list, var_t *var);
 
-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix,
-                       const char *abi_prefix);
-char *format_parameterized_type_name(type_t *type, typeref_list_t *params);
-
 static inline enum type_type type_get_type_detect_alias(const type_t *type)
 {
     return type->type_type;
diff --git a/mingw-w64-tools/widl/src/write_msft.c b/mingw-w64-tools/widl/src/write_msft.c
index b0401d8..6c63e27 100644
--- a/mingw-w64-tools/widl/src/write_msft.c
+++ b/mingw-w64-tools/widl/src/write_msft.c
@@ -2006,9 +2006,13 @@
             break;
 
         case ATTR_VERSION:
-            typeinfo->version = attr->u.ival;
-            break;
+        {
+            const version_t *version = attr->u.pval;
+            unsigned short major = version ? version->major : 0, minor = version ? version->minor : 0;
 
+            typeinfo->version = (minor << 16) | major;
+            break;
+        }
         default:
             break;
         }
@@ -2507,7 +2511,10 @@
 
 static void set_version(msft_typelib_t *typelib)
 {
-    typelib->typelib_header.version = get_attrv( typelib->typelib->attrs, ATTR_VERSION );
+    unsigned short major, minor;
+
+    get_version( typelib->typelib->attrs, &major, &minor );
+    typelib->typelib_header.version = (minor << 16) | major;
 }
 
 static void set_guid(msft_typelib_t *typelib)
diff --git a/mingw-w64-tools/widl/src/write_sltg.c b/mingw-w64-tools/widl/src/write_sltg.c
index b4ec340..3c80e21 100644
--- a/mingw-w64-tools/widl/src/write_sltg.c
+++ b/mingw-w64-tools/widl/src/write_sltg.c
@@ -320,8 +320,13 @@
         switch (attr->type)
         {
         case ATTR_VERSION:
-            sltg->library.version = attr->u.ival;
+        {
+            const version_t *version = attr->u.pval;
+            unsigned short major = version ? version->major : 0, minor = version ? version->minor : 0;
+
+            sltg->library.version = (minor << 16) | major;
             break;
+        }
         case ATTR_HELPSTRING:
             sltg->library.helpstring = attr->u.pval;
             break;
@@ -522,12 +527,16 @@
 static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, short kind,
                           const struct sltg_hrefmap *hrefmap)
 {
+    unsigned short major, minor;
+
+    get_version( type->attrs, &major, &minor );
+
     ti->magic = 0x0501;
     ti->href_offset = -1;
     ti->res06 = -1;
     ti->member_offset = sizeof(*ti);
     ti->res0e = -1;
-    ti->version = get_attrv(type->attrs, ATTR_VERSION);
+    ti->version = minor << 16 | major;
     ti->res16 = 0xfffe0000;
     ti->misc.unknown1 = 0x02;
     ti->misc.flags = 0; /* FIXME */