commit 25aa6ad4eb02c98d17e9f8f714aab22b5ce3b31e Author: Richard Pospesel richard@torproject.org Date: Thu Jun 6 18:08:48 2019 -0700
Bug 27503: add patch for fixed widl to mingw and update build/config to apply it --- projects/mingw-w64/27503.patch | 10660 +++++++++++++++++++++++++++++++++++++++ projects/mingw-w64/build | 3 + projects/mingw-w64/config | 1 + 3 files changed, 10664 insertions(+)
diff --git a/projects/mingw-w64/27503.patch b/projects/mingw-w64/27503.patch new file mode 100644 index 0000000..f6bd197 --- /dev/null +++ b/projects/mingw-w64/27503.patch @@ -0,0 +1,10660 @@ +diff --git a/mingw-w64-tools/widl/src/client.c b/mingw-w64-tools/widl/src/client.c +index a3b2bbb6..d27c6cad 100644 +--- a/mingw-w64-tools/widl/src/client.c ++++ b/mingw-w64-tools/widl/src/client.c +@@ -20,7 +20,7 @@ + + #include "config.h" + #include "wine/port.h" +- ++ + #include <stdio.h> + #include <stdlib.h> + #ifdef HAVE_UNISTD_H +@@ -34,7 +34,7 @@ + #include "parser.h" + #include "header.h" + +-#include "widltypes.h" ++#include "typetree.h" + #include "typegen.h" + #include "expr.h" + +@@ -52,12 +52,13 @@ static void print_client( const char *format, ... ) + + static void write_client_func_decl( const type_t *iface, const var_t *func ) + { +- const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); +- const var_list_t *args = type_get_function_args(func->type); +- type_t *rettype = type_function_get_rettype(func->type); ++ const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); ++ const var_list_t *args = type_function_get_args(func->declspec.type); ++ const decl_spec_t *retdeclspec = type_function_get_retdeclspec(func->declspec.type); + + if (!callconv) callconv = "__cdecl"; +- write_type_decl_left(client, rettype); ++ write_declspec_decl_left(client, retdeclspec); ++ if (func->declspec.funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(client, " inline"); + fprintf(client, " %s ", callconv); + fprintf(client, "%s%s(\n", prefix_client, get_name(func)); + indent++; +@@ -74,9 +75,9 @@ static void write_function_stub( const type_t *iface, const var_t *func, + { + unsigned char explicit_fc, implicit_fc; + int has_full_pointer = is_full_pointer_function(func); +- var_t *retval = type_function_get_retval(func->type); ++ var_t *retval = type_function_get_retval(func->declspec.type); + const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); +- int has_ret = !is_void(retval->type); ++ int has_ret = !is_void(retval->declspec.type); + + if (is_interpreted_func( iface, func )) + { +@@ -97,7 +98,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, + print_client("RPC_BINDING_HANDLE _Handle;\n"); + } + +- if (has_ret && decl_indirect(retval->type)) ++ if (has_ret && decl_indirect(retval->declspec.type)) + { + print_client("void *_p_%s;\n", retval->name); + } +@@ -136,7 +137,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, + if (has_ret) + { + print_client("%s", ""); +- write_type_decl(client, retval->type, retval->name); ++ write_declspec_decl(client, &retval->declspec, retval->name); + fprintf(client, ";\n"); + } + print_client("RPC_MESSAGE _RpcMessage;\n"); +@@ -147,7 +148,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, + if (explicit_fc == FC_BIND_GENERIC) + print_client("__frame->%s = %s;\n", handle_var->name, handle_var->name ); + } +- if (has_ret && decl_indirect(retval->type)) ++ if (has_ret && decl_indirect(retval->declspec.type)) + { + print_client("__frame->_p_%s = &%s;\n", retval->name, retval->name); + } +@@ -194,7 +195,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, + /* if the context_handle attribute appears in the chain of types + * without pointers being followed, then the context handle must + * be direct, otherwise it is a pointer */ +- int is_ch_ptr = !is_aliaschain_attr(handle_var->type, ATTR_CONTEXTHANDLE); ++ int is_ch_ptr = !is_aliaschain_attr(handle_var->declspec.type, ATTR_CONTEXTHANDLE); + print_client("if (%s%s != 0)\n", is_ch_ptr ? "*" : "", handle_var->name); + indent++; + print_client("__frame->_Handle = NDRCContextBinding(%s%s);\n", +@@ -257,9 +258,9 @@ static void write_function_stub( const type_t *iface, const var_t *func, + /* unmarshal return value */ + if (has_ret) + { +- if (decl_indirect(retval->type)) ++ if (decl_indirect(retval->declspec.type)) + print_client("MIDL_memset(&%s, 0, sizeof(%s));\n", retval->name, retval->name); +- else if (is_ptr(retval->type) || is_array(retval->type)) ++ else if (is_ptr(retval->declspec.type) || is_array(retval->declspec.type)) + print_client("%s = 0;\n", retval->name); + write_remoting_arguments(client, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL); + } +@@ -291,7 +292,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_ + const char *func_name, const char *ret_type) + { + enum stub_mode mode = get_stub_mode(); +- static int emited_pickling_info; ++ static int emitted_pickling_info; + + if (iface && !type->typestring_offset) + { +@@ -301,7 +302,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_ + return; + } + +- if (!emited_pickling_info && iface && mode != MODE_Os) ++ if (!emitted_pickling_info && iface && mode != MODE_Os) + { + fprintf(file, "static const MIDL_TYPE_PICKLING_INFO __MIDL_TypePicklingInfo =\n"); + fprintf(file, "{\n"); +@@ -312,7 +313,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_ + fprintf(file, " 0\n"); + fprintf(file, "};\n"); + fprintf(file, "\n"); +- emited_pickling_info = 1; ++ emitted_pickling_info = 1; + } + + /* FIXME: Assuming explicit handle */ +@@ -365,8 +366,8 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) + case STMT_DECLARATION: + { + const var_t *func = stmt->u.var; +- if (stmt->u.var->stgclass != STG_NONE +- || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION) ++ if (stmt->u.var->declspec.stgclass != STG_NONE ++ || type_get_type_detect_alias(stmt->u.var->declspec.type) != TYPE_FUNCTION) + continue; + write_function_stub( iface, func, method_count++, *proc_offset ); + *proc_offset += get_size_procformatstring_func( iface, func ); +@@ -425,7 +426,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines) + print_client("1, /* -error bounds_check flag */\n"); + print_client("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); + print_client("0,\n"); +- print_client("0x50100a4, /* MIDL Version 5.1.164 */\n"); ++ print_client("0x50200ca, /* MIDL Version 5.2.202 */\n"); + print_client("0,\n"); + print_client("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); + print_client("0, /* notify & notify_flag routine table */\n"); +@@ -488,7 +489,7 @@ static void write_implicithandledecl(type_t *iface) + + if (implicit_handle) + { +- write_type_decl( client, implicit_handle->type, implicit_handle->name ); ++ write_declspec_decl( client, &implicit_handle->declspec, implicit_handle->name ); + fprintf(client, ";\n\n"); + } + } +@@ -532,8 +533,8 @@ static void write_client_ifaces(const statement_list_t *stmts, int expr_eval_rou + + LIST_FOR_EACH_ENTRY(stmt2, type_iface_get_stmts(iface), const statement_t, entry) + { +- if (stmt2->type == STMT_DECLARATION && stmt2->u.var->stgclass == STG_NONE && +- type_get_type_detect_alias(stmt2->u.var->type) == TYPE_FUNCTION) ++ if (stmt2->type == STMT_DECLARATION && stmt2->u.var->declspec.stgclass == STG_NONE && ++ type_get_type_detect_alias(stmt2->u.var->declspec.type) == TYPE_FUNCTION) + { + needs_stub = 1; + break; +@@ -627,26 +628,6 @@ void write_client(const statement_list_t *stmts) + if (!client) + return; + +- if (do_win32 && do_win64) +- { +- fprintf(client, "#ifndef _WIN64\n\n"); +- pointer_size = 4; +- write_client_routines( stmts ); +- fprintf(client, "\n#else /* _WIN64 */\n\n"); +- pointer_size = 8; +- write_client_routines( stmts ); +- fprintf(client, "\n#endif /* _WIN64 */\n"); +- } +- else if (do_win32) +- { +- pointer_size = 4; +- write_client_routines( stmts ); +- } +- else if (do_win64) +- { +- pointer_size = 8; +- write_client_routines( stmts ); +- } +- ++ write_client_routines( stmts ); + fclose(client); + } +diff --git a/mingw-w64-tools/widl/src/expr.c b/mingw-w64-tools/widl/src/expr.c +index 2ed4aff6..2f075816 100644 +--- a/mingw-w64-tools/widl/src/expr.c ++++ b/mingw-w64-tools/widl/src/expr.c +@@ -194,10 +194,10 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) + expr_t *e; + type_t *tref; + +- if (var->stgclass != STG_NONE && var->stgclass != STG_REGISTER) ++ if (var->declspec.stgclass != STG_NONE && var->declspec.stgclass != STG_REGISTER) + error_loc("invalid storage class for type expression\n"); + +- tref = var->type; ++ tref = var->declspec.type; + + e = xmalloc(sizeof(expr_t)); + e->type = type; +@@ -474,7 +474,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + if (field->name && !strcmp(identifier, field->name)) + { +- type = field->type; ++ type = field->declspec.type; + *found_in_cont_type = 1; + break; + } +@@ -482,7 +482,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, + if (!type) + { + var_t *const_var = find_const(identifier, 0); +- if (const_var) type = const_var->type; ++ if (const_var) type = const_var->declspec.type; + } + + return type; +@@ -521,11 +521,11 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc + break; + case EXPR_STRLIT: + result.is_temporary = TRUE; +- result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL); ++ result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_CHAR, 0)); + break; + case EXPR_WSTRLIT: + result.is_temporary = TRUE; +- result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL); ++ result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0)); + break; + case EXPR_CHARCONST: + result.is_temporary = TRUE; +@@ -575,15 +575,15 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc + expr_loc->attr ? expr_loc->attr : ""); + result.is_variable = FALSE; + result.is_temporary = TRUE; +- result.type = type_new_pointer(FC_UP, result.type, NULL); ++ result.type = type_new_pointer(FC_UP, result.type); + break; + case EXPR_PPTR: + result = resolve_expression(expr_loc, cont_type, e->ref); + if (result.type && is_ptr(result.type)) +- result.type = type_pointer_get_ref(result.type); ++ result.type = type_pointer_get_ref_type(result.type); + else if(result.type && is_array(result.type) + && type_array_is_decl_as_ptr(result.type)) +- result.type = type_array_get_element(result.type); ++ result.type = type_array_get_element_type(result.type); + else + error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", +@@ -665,7 +665,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc + if (result.type && is_array(result.type)) + { + struct expression_type index_result; +- result.type = type_array_get_element(result.type); ++ result.type = type_array_get_element_type(result.type); + index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext); + if (!index_result.type || !is_integer_type(index_result.type)) + error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n", +diff --git a/mingw-w64-tools/widl/src/header.c b/mingw-w64-tools/widl/src/header.c +index defc7f85..d0d0dc4b 100644 +--- a/mingw-w64-tools/widl/src/header.c ++++ b/mingw-w64-tools/widl/src/header.c +@@ -43,7 +43,7 @@ user_type_list_t user_type_list = LIST_INIT(user_type_list); + 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_def_or_decl(FILE *f, type_t *t, int field, const char *name); ++static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name); + + static void indent(FILE *h, int delta) + { +@@ -69,15 +69,15 @@ int is_ptrchain_attr(const var_t *var, enum attr_type t) + return 1; + else + { +- type_t *type = var->type; ++ type_t *type = var->declspec.type; + for (;;) + { + if (is_attr(type->attrs, t)) + return 1; + else if (type_is_alias(type)) +- type = type_alias_get_aliasee(type); ++ type = type_alias_get_aliasee_type(type); + else if (is_ptr(type)) +- type = type_pointer_get_ref(type); ++ type = type_pointer_get_ref_type(type); + else return 0; + } + } +@@ -91,7 +91,7 @@ int is_aliaschain_attr(const type_t *type, enum attr_type attr) + if (is_attr(t->attrs, attr)) + return 1; + else if (type_is_alias(t)) +- t = type_alias_get_aliasee(t); ++ t = type_alias_get_aliasee_type(t); + else return 0; + } + } +@@ -204,9 +204,9 @@ static void write_fields(FILE *h, var_list_t *fields) + if (!fields) return; + + LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { +- if (!v || !v->type) continue; ++ if (!v || !v->declspec.type) continue; + +- switch(type_get_type_detect_alias(v->type)) { ++ switch(type_get_type_detect_alias(v->declspec.type)) { + case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: + nameless_struct_cnt++; +@@ -220,12 +220,12 @@ static void write_fields(FILE *h, var_list_t *fields) + } + + LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { +- if (!v || !v->type) continue; ++ if (!v || !v->declspec.type) continue; + + indent(h, 0); + name = v->name; + +- switch(type_get_type_detect_alias(v->type)) { ++ switch(type_get_type_detect_alias(v->declspec.type)) { + case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: + if(!v->name) { +@@ -252,7 +252,7 @@ static void write_fields(FILE *h, var_list_t *fields) + default: + ; + } +- write_type_def_or_decl(h, v->type, TRUE, name); ++ write_type_v(h, &v->declspec, TRUE, v->declonly, name); + fprintf(h, ";\n"); + } + } +@@ -295,14 +295,21 @@ static void write_pointer_left(FILE *h, type_t *ref) + } + + void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) ++{ ++ decl_spec_t ds; ++ write_declspec_left(h, init_declspec(&ds, t), name_type, declonly); ++} ++ ++void write_declspec_left(FILE* h, const decl_spec_t *ds, enum name_type name_type, int declonly) + { + const char *name; ++ type_t *t = ds->type; + + if (!h) return; + + name = type_get_name(t, name_type); + +- if (is_attr(t->attrs, ATTR_CONST) && ++ if ((ds->typequalifier == TYPE_QUALIFIER_CONST) && + (type_is_alias(t) || !is_ptr(t))) + fprintf(h, "const "); + +@@ -310,7 +317,7 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) + else { + switch (type_get_type_detect_alias(t)) { + case TYPE_ENUM: +- if (!declonly && t->defined && !t->written) { ++ if (!declonly && type_is_defined(t) && !t->written) { + if (name) fprintf(h, "enum %s {\n", name); + else fprintf(h, "enum {\n"); + t->written = TRUE; +@@ -323,7 +330,7 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) + break; + case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: +- if (!declonly && t->defined && !t->written) { ++ if (!declonly && type_is_defined(t) && !t->written) { + if (name) fprintf(h, "struct %s {\n", name); + else fprintf(h, "struct {\n"); + t->written = TRUE; +@@ -338,7 +345,7 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) + else fprintf(h, "struct %s", name ? name : ""); + break; + case TYPE_UNION: +- if (!declonly && t->defined && !t->written) { ++ if (!declonly && type_is_defined(t) && !t->written) { + if (t->name) fprintf(h, "union %s {\n", t->name); + else fprintf(h, "union {\n"); + t->written = TRUE; +@@ -351,9 +358,9 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) + break; + case TYPE_POINTER: + { +- write_type_left(h, type_pointer_get_ref(t), name_type, declonly); +- write_pointer_left(h, type_pointer_get_ref(t)); +- if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const "); ++ write_declspec_left(h, type_pointer_get_ref(t), name_type, declonly); ++ write_pointer_left(h, type_pointer_get_ref_type(t)); ++ if (ds->typequalifier == TYPE_QUALIFIER_CONST) fprintf(h, "const "); + break; + } + case TYPE_ARRAY: +@@ -361,9 +368,9 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) + fprintf(h, "%s", t->name); + else + { +- write_type_left(h, type_array_get_element(t), name_type, declonly); ++ write_declspec_left(h, type_array_get_element(t), name_type, declonly); + if (type_array_is_decl_as_ptr(t)) +- write_pointer_left(h, type_array_get_element(t)); ++ write_pointer_left(h, type_array_get_element_type(t)); + } + break; + case TYPE_BASIC: +@@ -443,7 +450,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) + { + case TYPE_ARRAY: + { +- type_t *elem = type_array_get_element(t); ++ type_t *elem = type_array_get_element_type(t); + if (type_array_is_decl_as_ptr(t)) + { + if (!type_is_alias(elem) && is_array(elem) && !type_array_is_decl_as_ptr(elem)) +@@ -461,7 +468,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) + } + case TYPE_POINTER: + { +- type_t *ref = type_pointer_get_ref(t); ++ type_t *ref = type_pointer_get_ref_type(t); + if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref)) + fprintf(h, ")"); + write_type_right(h, ref, FALSE); +@@ -485,30 +492,33 @@ void write_type_right(FILE *h, type_t *t, int is_field) + } + } + +-static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name) ++static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name) + { ++ type_t *t = ds->type; + type_t *pt = NULL; + int ptr_level = 0; + + if (!h) return; + + if (t) { +- for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++) ++ const decl_spec_t *dpt = NULL; ++ for (dpt = ds; is_ptr(dpt->type); dpt = type_pointer_get_ref(dpt->type), ptr_level++) + ; ++ pt = dpt->type; + + if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { + int i; + const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV); + if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; +- if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline "); +- write_type_left(h, type_function_get_rettype(pt), NAME_DEFAULT, declonly); ++ if (!is_ptr(ds->type) && dpt->funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(h, "inline "); ++ write_declspec_left(h, type_function_get_retdeclspec(pt), NAME_DEFAULT, declonly); + fputc(' ', h); + if (ptr_level) fputc('(', h); + if (callconv) fprintf(h, "%s ", callconv); + for (i = 0; i < ptr_level; i++) + fputc('*', h); + } else +- write_type_left(h, t, NAME_DEFAULT, declonly); ++ write_declspec_left(h, ds, NAME_DEFAULT, declonly); + } + + if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); +@@ -529,12 +539,7 @@ static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const c + } + } + +-static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name) +-{ +- write_type_v(f, t, field, FALSE, name); +-} +- +-static void write_type_definition(FILE *f, type_t *t) ++static void write_type_definition(FILE *f, type_t *t, int declonly) + { + int in_namespace = t->namespace && !is_global_namespace(t->namespace); + int save_written = t->written; +@@ -545,14 +550,14 @@ static void write_type_definition(FILE *f, type_t *t) + write_namespace_start(f, t->namespace); + } + indent(f, 0); +- write_type_left(f, t, NAME_DEFAULT, FALSE); ++ write_type_left(f, t, NAME_DEFAULT, declonly); + fprintf(f, ";\n"); + if(in_namespace) { + t->written = save_written; + write_namespace_end(f, t->namespace); + fprintf(f, "extern "C" {\n"); + fprintf(f, "#else\n"); +- write_type_left(f, t, NAME_C, FALSE); ++ write_type_left(f, t, NAME_C, declonly); + fprintf(f, ";\n"); + fprintf(f, "#endif\n\n"); + } +@@ -560,12 +565,18 @@ static void write_type_definition(FILE *f, type_t *t) + + void write_type_decl(FILE *f, type_t *t, const char *name) + { +- write_type_v(f, t, FALSE, TRUE, name); ++ decl_spec_t ds; ++ write_declspec_decl(f, init_declspec(&ds, t), name); ++} ++ ++void write_declspec_decl(FILE *f, const decl_spec_t *ds, const char *name) ++{ ++ write_type_v(f, ds, FALSE, TRUE, name); + } + +-void write_type_decl_left(FILE *f, type_t *t) ++void write_declspec_decl_left(FILE *f, const decl_spec_t *ds) + { +- write_type_left(f, t, NAME_DEFAULT, TRUE); ++ write_declspec_left(f, ds, NAME_DEFAULT, TRUE); + } + + static int user_type_registered(const char *name) +@@ -602,8 +613,8 @@ unsigned int get_context_handle_offset( const type_t *type ) + + while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE )) + { +- if (type_is_alias( type )) type = type_alias_get_aliasee( type ); +- else if (is_ptr( type )) type = type_pointer_get_ref( type ); ++ if (type_is_alias( type )) type = type_alias_get_aliasee_type( type ); ++ else if (is_ptr( type )) type = type_pointer_get_ref_type( type ); + else error( "internal error: %s is not a context handle\n", type->name ); + } + LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry ) +@@ -622,8 +633,8 @@ unsigned int get_generic_handle_offset( const type_t *type ) + + while (!is_attr( type->attrs, ATTR_HANDLE )) + { +- if (type_is_alias( type )) type = type_alias_get_aliasee( type ); +- else if (is_ptr( type )) type = type_pointer_get_ref( type ); ++ if (type_is_alias( type )) type = type_alias_get_aliasee_type( type ); ++ else if (is_ptr( type )) type = type_pointer_get_ref_type( type ); + else error( "internal error: %s is not a generic handle\n", type->name ); + } + LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) +@@ -637,82 +648,77 @@ unsigned int get_generic_handle_offset( const type_t *type ) + + /* check for types which require additional prototypes to be generated in the + * header */ +-void check_for_additional_prototype_types(const var_list_t *list) +-{ +- const var_t *v; +- +- if (!list) return; +- LIST_FOR_EACH_ENTRY( v, list, const var_t, entry ) +- { +- type_t *type = v->type; +- if (!type) continue; +- for (;;) { +- const char *name = type->name; +- if (type->user_types_registered) break; +- type->user_types_registered = 1; +- if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { +- if (!context_handle_registered(name)) +- { +- context_handle_t *ch = xmalloc(sizeof(*ch)); +- ch->name = xstrdup(name); +- list_add_tail(&context_handle_list, &ch->entry); +- } +- /* don't carry on parsing fields within this type */ +- break; +- } +- if ((type_get_type(type) != TYPE_BASIC || +- type_basic_get_type(type) != TYPE_BASIC_HANDLE) && +- is_attr(type->attrs, ATTR_HANDLE)) { +- if (!generic_handle_registered(name)) +- { +- generic_handle_t *gh = xmalloc(sizeof(*gh)); +- gh->name = xstrdup(name); +- list_add_tail(&generic_handle_list, &gh->entry); +- } +- /* don't carry on parsing fields within this type */ +- break; ++void check_for_additional_prototype_types(type_t *type) ++{ ++ if (!type) return; ++ for (;;) { ++ const char *name = type->name; ++ if (type->user_types_registered) break; ++ type->user_types_registered = 1; ++ if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { ++ if (!context_handle_registered(name)) ++ { ++ context_handle_t *ch = xmalloc(sizeof(*ch)); ++ ch->name = xstrdup(name); ++ list_add_tail(&context_handle_list, &ch->entry); + } +- if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { +- if (!user_type_registered(name)) +- { +- user_type_t *ut = xmalloc(sizeof *ut); +- ut->name = xstrdup(name); +- list_add_tail(&user_type_list, &ut->entry); +- } +- /* don't carry on parsing fields within this type as we are already +- * using a wire marshaled type */ +- break; ++ /* don't carry on parsing fields within this type */ ++ break; ++ } ++ if ((type_get_type(type) != TYPE_BASIC || ++ type_basic_get_type(type) != TYPE_BASIC_HANDLE) && ++ is_attr(type->attrs, ATTR_HANDLE)) { ++ if (!generic_handle_registered(name)) ++ { ++ generic_handle_t *gh = xmalloc(sizeof(*gh)); ++ gh->name = xstrdup(name); ++ list_add_tail(&generic_handle_list, &gh->entry); + } +- else if (type_is_complete(type)) ++ /* don't carry on parsing fields within this type */ ++ break; ++ } ++ if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { ++ if (!user_type_registered(name)) + { +- var_list_t *vars; +- switch (type_get_type_detect_alias(type)) +- { +- case TYPE_ENUM: +- vars = type_enum_get_values(type); +- break; +- case TYPE_STRUCT: +- vars = type_struct_get_fields(type); +- break; +- case TYPE_UNION: +- vars = type_union_get_cases(type); +- break; +- default: +- vars = NULL; +- break; +- } +- check_for_additional_prototype_types(vars); ++ user_type_t *ut = xmalloc(sizeof *ut); ++ ut->name = xstrdup(name); ++ list_add_tail(&user_type_list, &ut->entry); + } +- +- if (type_is_alias(type)) +- type = type_alias_get_aliasee(type); +- else if (is_ptr(type)) +- type = type_pointer_get_ref(type); +- else if (is_array(type)) +- type = type_array_get_element(type); +- else ++ /* don't carry on parsing fields within this type as we are already ++ * using a wire marshaled type */ ++ break; ++ } ++ else if (type_is_complete(type)) ++ { ++ var_list_t *vars; ++ const var_t *v; ++ switch (type_get_type_detect_alias(type)) ++ { ++ case TYPE_ENUM: ++ vars = type_enum_get_values(type); ++ break; ++ case TYPE_STRUCT: ++ vars = type_struct_get_fields(type); + break; ++ case TYPE_UNION: ++ vars = type_union_get_cases(type); ++ break; ++ default: ++ vars = NULL; ++ break; ++ } ++ if (vars) LIST_FOR_EACH_ENTRY( v, vars, const var_t, entry ) ++ check_for_additional_prototype_types(v->declspec.type); + } ++ ++ if (type_is_alias(type)) ++ type = type_alias_get_aliasee_type(type); ++ else if (is_ptr(type)) ++ type = type_pointer_get_ref_type(type); ++ else if (is_array(type)) ++ type = type_array_get_element_type(type); ++ else ++ break; + } + } + +@@ -791,26 +797,26 @@ static void write_generic_handle_routines(FILE *header) + } + } + +-static void write_typedef(FILE *header, type_t *type) ++static void write_typedef(FILE *header, type_t *type, int declonly) + { + fprintf(header, "typedef "); +- write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name); ++ write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name); + fprintf(header, ";\n"); + } + + int is_const_decl(const var_t *var) + { +- const type_t *t; ++ const decl_spec_t *ds; + /* strangely, MIDL accepts a const attribute on any pointer in the + * declaration to mean that data isn't being instantiated. this appears + * to be a bug, but there is no benefit to being incompatible with MIDL, + * so we'll do the same thing */ +- for (t = var->type; ; ) ++ for (ds = &var->declspec; ;) + { +- if (is_attr(t->attrs, ATTR_CONST)) ++ if (ds->typequalifier == TYPE_QUALIFIER_CONST) + return TRUE; +- else if (is_ptr(t)) +- t = type_pointer_get_ref(t); ++ else if (is_ptr(ds->type)) ++ ds = type_pointer_get_ref(ds->type); + else break; + } + return FALSE; +@@ -826,7 +832,7 @@ static void write_declaration(FILE *header, const var_t *v) + } + else + { +- switch (v->stgclass) ++ switch (v->declspec.stgclass) + { + case STG_NONE: + case STG_REGISTER: /* ignored */ +@@ -838,7 +844,7 @@ static void write_declaration(FILE *header, const var_t *v) + fprintf(header, "extern "); + break; + } +- write_type_def_or_decl(header, v->type, FALSE, v->name); ++ write_type_v(header, &v->declspec, FALSE, FALSE, v->name); + fprintf(header, ";\n\n"); + } + } +@@ -855,9 +861,9 @@ static void write_library(FILE *header, const typelib_t *typelib) + const type_t* get_explicit_generic_handle_type(const var_t* var) + { + const type_t *t; +- for (t = var->type; ++ for (t = var->declspec.type; + is_ptr(t) || type_is_alias(t); +- t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) ++ t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t)) + if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) && + is_attr(t->attrs, ATTR_HANDLE)) + return t; +@@ -868,13 +874,13 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func, + unsigned char *explicit_fc, unsigned char *implicit_fc ) + { + const var_t *var; +- const var_list_t *args = type_get_function_args( func->type ); ++ const var_list_t *args = type_function_get_args( func->declspec.type ); + + *explicit_fc = *implicit_fc = 0; + if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) + { + if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue; +- if (type_get_type( var->type ) == TYPE_BASIC && type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) ++ if (type_get_type( var->declspec.type ) == TYPE_BASIC && type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE) + { + *explicit_fc = FC_BIND_PRIMITIVE; + return var; +@@ -884,7 +890,7 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func, + *explicit_fc = FC_BIND_GENERIC; + return var; + } +- if (is_context_handle( var->type )) ++ if (is_context_handle( var->declspec.type )) + { + *explicit_fc = FC_BIND_CONTEXT; + return var; +@@ -893,8 +899,8 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func, + + if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE ))) + { +- if (type_get_type( var->type ) == TYPE_BASIC && +- type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) ++ if (type_get_type( var->declspec.type ) == TYPE_BASIC && ++ type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE) + *implicit_fc = FC_BIND_PRIMITIVE; + else + *implicit_fc = FC_BIND_GENERIC; +@@ -909,13 +915,13 @@ int has_out_arg_or_return(const var_t *func) + { + const var_t *var; + +- if (!is_void(type_function_get_rettype(func->type))) ++ if (!is_void(type_function_get_rettype(func->declspec.type))) + return 1; + +- if (!type_get_function_args(func->type)) ++ if (!type_function_get_args(func->declspec.type)) + return 0; + +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + if (is_attr(var->attrs, ATTR_OUT)) + return 1; + +@@ -995,7 +1001,7 @@ static int is_override_method(const type_t *iface, const type_t *child, const va + + static int is_aggregate_return(const var_t *func) + { +- enum type_type type = type_get_type(type_function_get_rettype(func->type)); ++ enum type_type type = type_get_type(type_function_get_rettype(func->declspec.type)); + return type == TYPE_STRUCT || type == TYPE_UNION || + type == TYPE_COCLASS || type == TYPE_INTERFACE; + } +@@ -1035,8 +1041,8 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t * + const var_t *arg; + + fprintf(header, "#define %s_%s(This", name, get_name(func)); +- if (type_get_function_args(func->type)) +- LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) ++ if (type_function_get_args(func->declspec.type)) ++ LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) + fprintf(header, ",%s", arg->name); + fprintf(header, ") "); + +@@ -1047,8 +1053,8 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t * + } + + fprintf(header, "(This)->lpVtbl->%s(This", get_vtbl_entry_name(iface, func)); +- if (type_get_function_args(func->type)) +- LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) ++ if (type_function_get_args(func->declspec.type)) ++ LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) + fprintf(header, ",%s", arg->name); + fprintf(header, ")\n"); + } +@@ -1078,7 +1084,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i + } + else fprintf(h, ","); + } +- write_type_decl(h, arg->type, arg->name); ++ write_declspec_decl(h, &arg->declspec, arg->name); + if (method == 2) { + const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE); + if (expr) { +@@ -1090,7 +1096,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i + expr_t bstr; + + /* Fixup the expression type for a BSTR like midl does. */ +- if (get_type_vt(arg->type) == VT_BSTR && expr->type == EXPR_STRLIT) ++ if (get_type_vt(arg->declspec.type) == VT_BSTR && expr->type == EXPR_STRLIT) + { + bstr = *expr; + bstr.type = EXPR_WSTRLIT; +@@ -1119,8 +1125,8 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) + { + const var_t *func = stmt->u.var; + if (!is_callas(func->attrs)) { +- const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); +- const var_list_t *args = type_get_function_args(func->type); ++ const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); ++ const var_list_t *args = type_function_get_args(func->declspec.type); + const var_t *arg; + + if (!callconv) callconv = "STDMETHODCALLTYPE"; +@@ -1130,11 +1136,11 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) + + indent(header, 0); + fprintf(header, "virtual "); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, "* %s %s(\n", callconv, get_name(func)); + ++indentation; + indent(header, 0); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " *__ret"); + --indentation; + if (args) { +@@ -1144,7 +1150,7 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) + fprintf(header, ") = 0;\n"); + + indent(header, 0); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " %s %s(\n", callconv, get_name(func)); + write_args(header, args, iface->name, 2, TRUE); + fprintf(header, ")\n"); +@@ -1152,7 +1158,7 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) + fprintf(header, "{\n"); + ++indentation; + indent(header, 0); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " __ret;\n"); + indent(header, 0); + fprintf(header, "return *%s(&__ret", get_name(func)); +@@ -1169,7 +1175,7 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) + + indent(header, 0); + fprintf(header, "virtual "); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " %s %s(\n", callconv, get_name(func)); + write_args(header, args, iface->name, 2, TRUE); + fprintf(header, ") = 0;\n"); +@@ -1206,25 +1212,25 @@ static void write_inline_wrappers(FILE *header, const type_t *iface, const type_ + const var_t *arg; + + fprintf(header, "static FORCEINLINE "); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " %s_%s(", name, get_name(func)); +- write_args(header, type_get_function_args(func->type), name, 1, FALSE); ++ write_args(header, type_function_get_args(func->declspec.type), name, 1, FALSE); + fprintf(header, ") {\n"); + ++indentation; + if (!is_aggregate_return(func)) { + indent(header, 0); + fprintf(header, "%sThis->lpVtbl->%s(This", +- is_void(type_function_get_rettype(func->type)) ? "" : "return ", ++ is_void(type_function_get_rettype(func->declspec.type)) ? "" : "return ", + get_vtbl_entry_name(iface, func)); + } else { + indent(header, 0); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " __ret;\n"); + indent(header, 0); + fprintf(header, "return *This->lpVtbl->%s(This,&__ret", get_vtbl_entry_name(iface, func)); + } +- if (type_get_function_args(func->type)) +- LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) ++ if (type_function_get_args(func->declspec.type)) ++ LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) + fprintf(header, ",%s", arg->name); + fprintf(header, ");\n"); + --indentation; +@@ -1250,10 +1256,10 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char + first_iface = 0; + } + if (!is_callas(func->attrs)) { +- const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); ++ const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); + if (!callconv) callconv = "STDMETHODCALLTYPE"; + indent(header, 0); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + if (is_aggregate_return(func)) + fprintf(header, " *"); + if (is_inherited_method(iface, func)) +@@ -1266,13 +1272,13 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char + if (is_aggregate_return(func)) { + fprintf(header, ",\n"); + indent(header, 0); +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " *__ret"); + } + --indentation; +- if (type_get_function_args(func->type)) { ++ if (type_function_get_args(func->declspec.type)) { + fprintf(header, ",\n"); +- write_args(header, type_get_function_args(func->type), name, 0, TRUE); ++ write_args(header, type_function_get_args(func->declspec.type), name, 0, TRUE); + } + fprintf(header, ");\n"); + fprintf(header, "\n"); +@@ -1299,12 +1305,12 @@ static void write_method_proto(FILE *header, const type_t *iface) + const var_t *func = stmt->u.var; + + if (is_callas(func->attrs)) { +- const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); ++ const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); + if (!callconv) callconv = "STDMETHODCALLTYPE"; + /* proxy prototype */ +- write_type_decl_left(header, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type)); + fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); +- write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE); ++ write_args(header, type_function_get_args(func->declspec.type), iface->name, 1, TRUE); + fprintf(header, ");\n"); + /* stub prototype */ + fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func)); +@@ -1337,12 +1343,12 @@ static void write_locals(FILE *fp, const type_t *iface, int body) + if (&stmt2->entry != type_iface_get_stmts(iface)) { + const var_t *m = stmt2->u.var; + /* proxy prototype - use local prototype */ +- write_type_decl_left(fp, type_function_get_rettype(m->type)); ++ write_declspec_decl_left(fp, type_function_get_retdeclspec(m->declspec.type)); + fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m)); +- write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE); ++ write_args(fp, type_function_get_args(m->declspec.type), iface->name, 1, TRUE); + fprintf(fp, ")"); + if (body) { +- type_t *rt = type_function_get_rettype(m->type); ++ type_t *rt = type_function_get_rettype(m->declspec.type); + fprintf(fp, "\n{\n"); + fprintf(fp, " %s\n", comment); + if (rt->name && strcmp(rt->name, "HRESULT") == 0) +@@ -1359,9 +1365,9 @@ static void write_locals(FILE *fp, const type_t *iface, int body) + else + fprintf(fp, ";\n"); + /* stub prototype - use remotable prototype */ +- write_type_decl_left(fp, type_function_get_rettype(func->type)); ++ write_declspec_decl_left(fp, type_function_get_retdeclspec(func->declspec.type)); + fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m)); +- write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE); ++ write_args(fp, type_function_get_args(func->declspec.type), iface->name, 1, TRUE); + fprintf(fp, ")"); + if (body) + /* Remotable methods must all return HRESULTs. */ +@@ -1407,15 +1413,16 @@ void write_local_stubs(const statement_list_t *stmts) + + static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix) + { +- const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV); ++ const char *callconv = get_attrp(fun->declspec.type->attrs, ATTR_CALLCONV); + + if (!callconv) callconv = "__cdecl"; + /* FIXME: do we need to handle call_as? */ +- write_type_decl_left(header, type_function_get_rettype(fun->type)); ++ write_declspec_decl_left(header, type_function_get_retdeclspec(fun->declspec.type)); ++ if (fun->declspec.funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(header, " inline"); + fprintf(header, " %s ", callconv); + fprintf(header, "%s%s(\n", prefix, get_name(fun)); +- if (type_get_function_args(fun->type)) +- write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE); ++ if (type_function_get_args(fun->declspec.type)) ++ write_args(header, type_function_get_args(fun->declspec.type), iface->name, 0, TRUE); + else + fprintf(header, " void"); + fprintf(header, ");\n\n"); +@@ -1541,7 +1548,7 @@ static void write_rpc_interface_start(FILE *header, const type_t *iface) + if (var) + { + fprintf(header, "extern "); +- write_type_decl( header, var->type, var->name ); ++ write_declspec_decl( header, &var->declspec, var->name ); + fprintf(header, ";\n"); + } + if (old_names) +@@ -1653,6 +1660,7 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE) + { + type_t *iface = stmt->u.type; ++ assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE); + if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE)) + { + write_forward(header, iface); +@@ -1694,6 +1702,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + { + type_t *iface = stmt->u.type; + type_t *async_iface = iface->details.iface->async_iface; ++ assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE); + if (is_object(iface)) is_object_interface++; + if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) + { +@@ -1718,7 +1727,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + write_coclass(header, stmt->u.type); + else + { +- write_type_definition(header, stmt->u.type); ++ write_type_definition(header, stmt->u.type, stmt->declonly); + } + break; + case STMT_TYPEREF: +@@ -1739,7 +1748,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + { + const type_list_t *type_entry = stmt->u.type_list; + for (; type_entry; type_entry = type_entry->next) +- write_typedef(header, type_entry->type); ++ write_typedef(header, type_entry->type, stmt->declonly); + break; + } + case STMT_LIBRARY: +@@ -1750,7 +1759,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons + fprintf(header, "%s\n", stmt->u.str); + break; + case STMT_DECLARATION: +- if (iface && type_get_type(stmt->u.var->type) == TYPE_FUNCTION) ++ if (iface && type_get_type(stmt->u.var->declspec.type) == TYPE_FUNCTION) + { + if (!ignore_funcs) + { +@@ -1784,15 +1793,15 @@ void write_header(const statement_list_t *stmts) + } + fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name); + ++ fprintf(header, "#ifdef _WIN32\n"); + fprintf(header, "#ifndef __REQUIRED_RPCNDR_H_VERSION__\n"); + fprintf(header, "#define __REQUIRED_RPCNDR_H_VERSION__ 475\n"); +- fprintf(header, "#endif\n\n"); +- ++ fprintf(header, "#endif\n"); + fprintf(header, "#include <rpc.h>\n" ); + fprintf(header, "#include <rpcndr.h>\n" ); + if (!for_each_serializable(stmts, NULL, serializable_exists)) + fprintf(header, "#include <midles.h>\n" ); +- fprintf(header, "\n" ); ++ fprintf(header, "#endif\n\n"); + + fprintf(header, "#ifndef COM_NO_WINDOWS_H\n"); + fprintf(header, "#include <windows.h>\n"); +diff --git a/mingw-w64-tools/widl/src/header.h b/mingw-w64-tools/widl/src/header.h +index 0d44b403..0e62f77c 100644 +--- a/mingw-w64-tools/widl/src/header.h ++++ b/mingw-w64-tools/widl/src/header.h +@@ -29,10 +29,12 @@ extern int is_attr(const attr_list_t *list, enum attr_type t); + extern void *get_attrp(const attr_list_t *list, enum attr_type t); + extern unsigned int get_attrv(const attr_list_t *list, enum attr_type t); + extern const char* get_name(const var_t *v); ++extern void write_declspec_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly); + extern void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly); + extern void write_type_right(FILE *h, type_t *t, int is_field); + extern void write_type_decl(FILE *f, type_t *t, const char *name); +-extern void write_type_decl_left(FILE *f, type_t *t); ++extern void write_declspec_decl(FILE *f, const decl_spec_t *ds, const char *name); ++extern void write_declspec_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); +@@ -83,12 +85,12 @@ static inline int is_conformant_array(const type_t *t) + + static inline int last_ptr(const type_t *type) + { +- return is_ptr(type) && !is_declptr(type_pointer_get_ref(type)); ++ return is_ptr(type) && !is_declptr(type_pointer_get_ref_type(type)); + } + + static inline int last_array(const type_t *type) + { +- return is_array(type) && !is_array(type_array_get_element(type)); ++ return is_array(type) && !is_array(type_array_get_element_type(type)); + } + + static inline int is_string_type(const attr_list_t *attrs, const type_t *type) +@@ -102,7 +104,7 @@ static inline int is_context_handle(const type_t *type) + const type_t *t; + for (t = type; + is_ptr(t) || type_is_alias(t); +- t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) ++ t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t)) + if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) + return 1; + return 0; +diff --git a/mingw-w64-tools/widl/src/parser.tab.c b/mingw-w64-tools/widl/src/parser.tab.c +index 6266e054..d7053e79 100644 +--- a/mingw-w64-tools/widl/src/parser.tab.c ++++ b/mingw-w64-tools/widl/src/parser.tab.c +@@ -1,8 +1,8 @@ +-/* A Bison parser, made by GNU Bison 3.0.5. */ ++/* A Bison parser, made by GNU Bison 3.0.4. */ + + /* Bison implementation for Yacc-like parsers in C + +- Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc. ++ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -44,7 +44,7 @@ + #define YYBISON 1 + + /* Bison version. */ +-#define YYBISON_VERSION "3.0.5" ++#define YYBISON_VERSION "3.0.4" + + /* Skeleton name. */ + #define YYSKELETON_NAME "yacc.c" +@@ -125,13 +125,6 @@ struct _import_t + int import_performed; + }; + +-typedef struct _decl_spec_t +-{ +- type_t *type; +- attr_list_t *attrs; +- enum storage_class stgclass; +-} decl_spec_t; +- + typelist_t incomplete_types = LIST_INIT(incomplete_types); + + static void fix_incomplete(void); +@@ -140,7 +133,7 @@ static void fix_incomplete_types(type_t *complete_type); + static str_list_t *append_str(str_list_t *list, char *str); + static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); + static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list); +-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass); ++static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier); + static attr_t *make_attr(enum attr_type type); + static attr_t *make_attrv(enum attr_type type, unsigned int val); + static attr_t *make_attrp(enum attr_type type, void *val); +@@ -156,6 +149,7 @@ static declarator_t *make_declarator(var_t *var); + static type_t *make_safearray(type_t *type); + static typelib_t *make_library(const char *name, const attr_list_t *attrs); + static type_t *append_chain_type(type_t *chain, type_t *type); ++static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier); + static warning_list_t *append_warning(warning_list_t *, int); + + static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs); +@@ -212,7 +206,7 @@ static struct namespace *current_namespace = &global_namespace; + static typelib_t *current_typelib; + + +-#line 216 "parser.tab.c" /* yacc.c:339 */ ++#line 210 "parser.tab.c" /* yacc.c:339 */ + + # ifndef YY_NULLPTR + # if defined __cplusplus && 201103L <= __cplusplus +@@ -438,7 +432,7 @@ extern int parser_debug; + + union YYSTYPE + { +-#line 142 "parser.y" /* yacc.c:355 */ ++#line 136 "parser.y" /* yacc.c:355 */ + + attr_t *attr; + attr_list_t *attr_list; +@@ -465,8 +459,10 @@ union YYSTYPE + struct _import_t *import; + struct _decl_spec_t *declspec; + enum storage_class stgclass; ++ enum type_qualifier typequalifier; ++ enum function_specifier funcspecifier; + +-#line 470 "parser.tab.c" /* yacc.c:355 */ ++#line 466 "parser.tab.c" /* yacc.c:355 */ + }; + + typedef union YYSTYPE YYSTYPE; +@@ -483,7 +479,7 @@ int parser_parse (void); + + /* Copy the second part of user declarations. */ + +-#line 487 "parser.tab.c" /* yacc.c:358 */ ++#line 483 "parser.tab.c" /* yacc.c:358 */ + + #ifdef short + # undef short +@@ -799,48 +795,48 @@ static const yytype_uint8 yytranslate[] = + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ + static const yytype_uint16 yyrline[] = + { +- 0, 325, 325, 340, 340, 342, 343, 343, 345, 346, +- 347, 350, 353, 354, 355, 358, 359, 360, 360, 362, +- 363, 364, 367, 368, 369, 370, 373, 374, 377, 378, +- 382, 383, 384, 385, 386, 387, 388, 391, 402, 403, +- 407, 408, 409, 410, 411, 412, 413, 414, 415, 418, +- 420, 428, 434, 438, 439, 441, 445, 449, 450, 453, +- 454, 457, 458, 462, 467, 474, 478, 479, 482, 483, +- 487, 490, 491, 492, 495, 496, 499, 500, 501, 502, +- 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, +- 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, +- 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, +- 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, +- 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, +- 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, +- 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, +- 573, 574, 578, 579, 580, 581, 582, 583, 584, 585, +- 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, +- 596, 597, 598, 599, 600, 601, 605, 606, 611, 612, +- 613, 614, 617, 618, 621, 625, 631, 632, 633, 636, +- 640, 652, 656, 661, 664, 665, 668, 669, 672, 673, +- 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, +- 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, +- 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, +- 704, 705, 706, 707, 708, 709, 711, 713, 714, 717, +- 718, 721, 727, 733, 734, 737, 742, 749, 750, 753, +- 754, 758, 759, 762, 766, 772, 780, 784, 789, 790, +- 793, 794, 795, 798, 800, 803, 804, 805, 806, 807, +- 808, 809, 810, 811, 812, 813, 816, 817, 820, 821, +- 822, 823, 824, 825, 826, 827, 828, 831, 832, 840, +- 846, 850, 853, 854, 858, 861, 862, 865, 874, 875, +- 878, 879, 882, 888, 894, 895, 898, 899, 902, 912, +- 922, 928, 932, 933, 936, 937, 940, 945, 952, 953, +- 954, 958, 962, 965, 966, 969, 970, 974, 975, 979, +- 980, 981, 985, 987, 989, 993, 994, 995, 996, 1004, +- 1006, 1008, 1013, 1015, 1020, 1021, 1026, 1027, 1028, 1029, +- 1034, 1043, 1045, 1046, 1051, 1053, 1057, 1058, 1065, 1066, +- 1067, 1068, 1069, 1074, 1082, 1083, 1086, 1087, 1090, 1097, +- 1098, 1103, 1104, 1108, 1109, 1110, 1111, 1112, 1116, 1117, +- 1118, 1121, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, +- 1132, 1133, 1136, 1143, 1145, 1151, 1152, 1153, 1156, 1158, +- 1160, 1162, 1165, 1170, 1178, 1179, 1182, 1183, 1186, 1187, +- 1188 ++ 0, 323, 323, 338, 338, 340, 341, 341, 343, 344, ++ 345, 348, 351, 352, 353, 356, 357, 358, 358, 360, ++ 361, 362, 365, 366, 367, 368, 371, 372, 375, 376, ++ 380, 381, 382, 383, 384, 385, 386, 389, 400, 401, ++ 405, 406, 407, 408, 409, 410, 411, 412, 413, 416, ++ 418, 426, 432, 436, 437, 439, 443, 447, 448, 451, ++ 452, 455, 456, 460, 465, 472, 476, 477, 480, 481, ++ 485, 488, 489, 490, 493, 494, 497, 498, 499, 500, ++ 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, ++ 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, ++ 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, ++ 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, ++ 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, ++ 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, ++ 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, ++ 571, 572, 576, 577, 578, 579, 580, 581, 582, 583, ++ 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, ++ 594, 595, 596, 597, 598, 599, 603, 604, 609, 610, ++ 611, 612, 615, 616, 619, 623, 629, 630, 631, 634, ++ 638, 650, 654, 659, 662, 663, 666, 667, 670, 671, ++ 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, ++ 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, ++ 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, ++ 702, 703, 704, 705, 706, 707, 709, 711, 712, 715, ++ 716, 719, 725, 731, 732, 735, 740, 747, 748, 751, ++ 752, 756, 757, 760, 764, 770, 778, 782, 787, 788, ++ 791, 792, 793, 796, 798, 801, 802, 803, 804, 805, ++ 806, 807, 808, 809, 810, 811, 814, 815, 818, 819, ++ 820, 821, 822, 823, 824, 825, 826, 829, 830, 838, ++ 844, 848, 851, 852, 856, 859, 860, 863, 872, 873, ++ 876, 877, 880, 886, 892, 893, 896, 897, 900, 910, ++ 920, 926, 930, 931, 934, 935, 938, 943, 950, 951, ++ 952, 956, 960, 963, 964, 967, 968, 972, 973, 977, ++ 978, 979, 983, 985, 987, 991, 992, 993, 994, 1002, ++ 1004, 1006, 1011, 1013, 1018, 1019, 1024, 1025, 1026, 1027, ++ 1032, 1041, 1043, 1044, 1049, 1051, 1055, 1056, 1063, 1064, ++ 1065, 1066, 1067, 1072, 1080, 1081, 1084, 1085, 1088, 1095, ++ 1096, 1101, 1102, 1106, 1107, 1108, 1109, 1110, 1114, 1115, ++ 1116, 1119, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, ++ 1130, 1131, 1134, 1141, 1143, 1149, 1150, 1151, 1154, 1156, ++ 1158, 1160, 1163, 1168, 1176, 1177, 1180, 1181, 1184, 1185, ++ 1186 + }; + #endif + +@@ -903,7 +899,7 @@ static const char *const yytname[] = + "dispinterfacedef", "inherit", "interface", "interfacehdr", + "interfacedef", "interfacedec", "module", "modulehdr", "moduledef", + "storage_cls_spec", "function_specifier", "type_qualifier", +- "m_type_qual_list", "decl_spec", "m_decl_spec_no_type", ++ "m_type_qual_bits", "decl_spec", "m_decl_spec_no_type", + "decl_spec_no_type", "declarator", "direct_declarator", + "abstract_declarator", "abstract_declarator_no_direct", + "m_abstract_declarator", "abstract_direct_declarator", "any_declarator", +@@ -2298,7 +2294,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + case N: \ + yyformat = S; \ + break +- default: /* Avoid compiler warnings. */ + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); +@@ -2615,7 +2610,7 @@ yyreduce: + switch (yyn) + { + case 2: +-#line 325 "parser.y" /* yacc.c:1648 */ ++#line 323 "parser.y" /* yacc.c:1646 */ + { fix_incomplete(); + check_statements((yyvsp[-1].stmt_list), FALSE); + check_all_user_types((yyvsp[-1].stmt_list)); +@@ -2629,197 +2624,197 @@ yyreduce: + write_dlldata((yyvsp[-1].stmt_list)); + write_local_stubs((yyvsp[-1].stmt_list)); + } +-#line 2633 "parser.tab.c" /* yacc.c:1648 */ ++#line 2628 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 5: +-#line 342 "parser.y" /* yacc.c:1648 */ ++#line 340 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = NULL; } +-#line 2639 "parser.tab.c" /* yacc.c:1648 */ ++#line 2634 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 6: +-#line 343 "parser.y" /* yacc.c:1648 */ ++#line 341 "parser.y" /* yacc.c:1646 */ + { push_namespace((yyvsp[-1].str)); } +-#line 2645 "parser.tab.c" /* yacc.c:1648 */ ++#line 2640 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 7: +-#line 344 "parser.y" /* yacc.c:1648 */ ++#line 342 "parser.y" /* yacc.c:1646 */ + { pop_namespace((yyvsp[-4].str)); (yyval.stmt_list) = append_statements((yyvsp[-5].stmt_list), (yyvsp[-1].stmt_list)); } +-#line 2651 "parser.tab.c" /* yacc.c:1648 */ ++#line 2646 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 8: +-#line 345 "parser.y" /* yacc.c:1648 */ ++#line 343 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_reference((yyvsp[0].type))); } +-#line 2657 "parser.tab.c" /* yacc.c:1648 */ ++#line 2652 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 9: +-#line 346 "parser.y" /* yacc.c:1648 */ ++#line 344 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); } +-#line 2663 "parser.tab.c" /* yacc.c:1648 */ ++#line 2658 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 10: +-#line 347 "parser.y" /* yacc.c:1648 */ ++#line 345 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = (yyvsp[-2].stmt_list); + reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); + } +-#line 2671 "parser.tab.c" /* yacc.c:1648 */ ++#line 2666 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 11: +-#line 350 "parser.y" /* yacc.c:1648 */ ++#line 348 "parser.y" /* yacc.c:1646 */ + { (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 2679 "parser.tab.c" /* yacc.c:1648 */ ++#line 2674 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 12: +-#line 353 "parser.y" /* yacc.c:1648 */ ++#line 351 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_module((yyvsp[0].type))); } +-#line 2685 "parser.tab.c" /* yacc.c:1648 */ ++#line 2680 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 13: +-#line 354 "parser.y" /* yacc.c:1648 */ ++#line 352 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_library((yyvsp[0].typelib))); } +-#line 2691 "parser.tab.c" /* yacc.c:1648 */ ++#line 2686 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 14: +-#line 355 "parser.y" /* yacc.c:1648 */ ++#line 353 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); } +-#line 2697 "parser.tab.c" /* yacc.c:1648 */ ++#line 2692 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 15: +-#line 358 "parser.y" /* yacc.c:1648 */ ++#line 356 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = NULL; } +-#line 2703 "parser.tab.c" /* yacc.c:1648 */ ++#line 2698 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 16: +-#line 359 "parser.y" /* yacc.c:1648 */ ++#line 357 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_reference((yyvsp[0].type))); } +-#line 2709 "parser.tab.c" /* yacc.c:1648 */ ++#line 2704 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 17: +-#line 360 "parser.y" /* yacc.c:1648 */ ++#line 358 "parser.y" /* yacc.c:1646 */ + { push_namespace((yyvsp[-1].str)); } +-#line 2715 "parser.tab.c" /* yacc.c:1648 */ ++#line 2710 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 18: +-#line 361 "parser.y" /* yacc.c:1648 */ ++#line 359 "parser.y" /* yacc.c:1646 */ + { pop_namespace((yyvsp[-4].str)); (yyval.stmt_list) = append_statements((yyvsp[-5].stmt_list), (yyvsp[-1].stmt_list)); } +-#line 2721 "parser.tab.c" /* yacc.c:1648 */ ++#line 2716 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 19: +-#line 362 "parser.y" /* yacc.c:1648 */ ++#line 360 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); } +-#line 2727 "parser.tab.c" /* yacc.c:1648 */ ++#line 2722 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 20: +-#line 363 "parser.y" /* yacc.c:1648 */ ++#line 361 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = (yyvsp[-2].stmt_list); reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); } +-#line 2733 "parser.tab.c" /* yacc.c:1648 */ ++#line 2728 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 21: +-#line 364 "parser.y" /* yacc.c:1648 */ ++#line 362 "parser.y" /* yacc.c:1646 */ + { (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 2741 "parser.tab.c" /* yacc.c:1648 */ ++#line 2736 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 22: +-#line 367 "parser.y" /* yacc.c:1648 */ ++#line 365 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_module((yyvsp[0].type))); } +-#line 2747 "parser.tab.c" /* yacc.c:1648 */ ++#line 2742 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 23: +-#line 368 "parser.y" /* yacc.c:1648 */ ++#line 366 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); } +-#line 2753 "parser.tab.c" /* yacc.c:1648 */ ++#line 2748 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 24: +-#line 369 "parser.y" /* yacc.c:1648 */ ++#line 367 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_importlib((yyvsp[0].str))); } +-#line 2759 "parser.tab.c" /* yacc.c:1648 */ ++#line 2754 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 25: +-#line 370 "parser.y" /* yacc.c:1648 */ ++#line 368 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_library((yyvsp[0].typelib))); } +-#line 2765 "parser.tab.c" /* yacc.c:1648 */ ++#line 2760 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 26: +-#line 373 "parser.y" /* yacc.c:1648 */ ++#line 371 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = NULL; } +-#line 2771 "parser.tab.c" /* yacc.c:1648 */ ++#line 2766 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 27: +-#line 374 "parser.y" /* yacc.c:1648 */ ++#line 372 "parser.y" /* yacc.c:1646 */ + { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); } +-#line 2777 "parser.tab.c" /* yacc.c:1648 */ ++#line 2772 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 30: +-#line 382 "parser.y" /* yacc.c:1648 */ ++#line 380 "parser.y" /* yacc.c:1646 */ + { (yyval.statement) = make_statement_cppquote((yyvsp[0].str)); } +-#line 2783 "parser.tab.c" /* yacc.c:1648 */ ++#line 2778 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 31: +-#line 383 "parser.y" /* yacc.c:1648 */ ++#line 381 "parser.y" /* yacc.c:1646 */ + { (yyval.statement) = make_statement_type_decl((yyvsp[-1].type)); } +-#line 2789 "parser.tab.c" /* yacc.c:1648 */ ++#line 2784 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 32: +-#line 384 "parser.y" /* yacc.c:1648 */ ++#line 382 "parser.y" /* yacc.c:1646 */ + { (yyval.statement) = make_statement_declaration((yyvsp[-1].var)); } +-#line 2795 "parser.tab.c" /* yacc.c:1648 */ ++#line 2790 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 33: +-#line 385 "parser.y" /* yacc.c:1648 */ ++#line 383 "parser.y" /* yacc.c:1646 */ + { (yyval.statement) = make_statement_import((yyvsp[0].str)); } +-#line 2801 "parser.tab.c" /* yacc.c:1648 */ ++#line 2796 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 34: +-#line 386 "parser.y" /* yacc.c:1648 */ ++#line 384 "parser.y" /* yacc.c:1646 */ + { (yyval.statement) = (yyvsp[-1].statement); } +-#line 2807 "parser.tab.c" /* yacc.c:1648 */ ++#line 2802 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 35: +-#line 387 "parser.y" /* yacc.c:1648 */ ++#line 385 "parser.y" /* yacc.c:1646 */ + { (yyval.statement) = make_statement_pragma((yyvsp[0].str)); } +-#line 2813 "parser.tab.c" /* yacc.c:1648 */ ++#line 2808 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 36: +-#line 388 "parser.y" /* yacc.c:1648 */ ++#line 386 "parser.y" /* yacc.c:1646 */ + { (yyval.statement) = NULL; } +-#line 2819 "parser.tab.c" /* yacc.c:1648 */ ++#line 2814 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 37: +-#line 392 "parser.y" /* yacc.c:1648 */ ++#line 390 "parser.y" /* yacc.c:1646 */ + { + int result; + (yyval.statement) = NULL; +@@ -2827,909 +2822,909 @@ yyreduce: + if(!result) + error_loc("expected "disable" or "enable"\n"); + } +-#line 2831 "parser.tab.c" /* yacc.c:1648 */ ++#line 2826 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 38: +-#line 402 "parser.y" /* yacc.c:1648 */ ++#line 400 "parser.y" /* yacc.c:1646 */ + { (yyval.warning_list) = append_warning(NULL, (yyvsp[0].num)); } +-#line 2837 "parser.tab.c" /* yacc.c:1648 */ ++#line 2832 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 39: +-#line 403 "parser.y" /* yacc.c:1648 */ ++#line 401 "parser.y" /* yacc.c:1646 */ + { (yyval.warning_list) = append_warning((yyvsp[-1].warning_list), (yyvsp[0].num)); } +-#line 2843 "parser.tab.c" /* yacc.c:1648 */ ++#line 2838 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 41: +-#line 408 "parser.y" /* yacc.c:1648 */ ++#line 406 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_enum((yyvsp[0].str), current_namespace, FALSE, NULL); } +-#line 2849 "parser.tab.c" /* yacc.c:1648 */ ++#line 2844 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 43: +-#line 410 "parser.y" /* yacc.c:1648 */ ++#line 408 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_struct((yyvsp[0].str), current_namespace, FALSE, NULL); } +-#line 2855 "parser.tab.c" /* yacc.c:1648 */ ++#line 2850 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 45: +-#line 412 "parser.y" /* yacc.c:1648 */ ++#line 410 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_nonencapsulated_union((yyvsp[0].str), FALSE, NULL); } +-#line 2861 "parser.tab.c" /* yacc.c:1648 */ ++#line 2856 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 46: +-#line 413 "parser.y" /* yacc.c:1648 */ ++#line 411 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_enum_attrs((yyvsp[-1].attr_list)); } +-#line 2867 "parser.tab.c" /* yacc.c:1648 */ ++#line 2862 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 47: +-#line 414 "parser.y" /* yacc.c:1648 */ ++#line 412 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_struct_attrs((yyvsp[-1].attr_list)); } +-#line 2873 "parser.tab.c" /* yacc.c:1648 */ ++#line 2868 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 48: +-#line 415 "parser.y" /* yacc.c:1648 */ ++#line 413 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_union_attrs((yyvsp[-1].attr_list)); } +-#line 2879 "parser.tab.c" /* yacc.c:1648 */ ++#line 2874 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 49: +-#line 418 "parser.y" /* yacc.c:1648 */ ++#line 416 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[-1].str); } +-#line 2885 "parser.tab.c" /* yacc.c:1648 */ ++#line 2880 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 50: +-#line 420 "parser.y" /* yacc.c:1648 */ ++#line 418 "parser.y" /* yacc.c:1646 */ + { assert(yychar == YYEMPTY); + (yyval.import) = xmalloc(sizeof(struct _import_t)); + (yyval.import)->name = (yyvsp[-1].str); + (yyval.import)->import_performed = do_import((yyvsp[-1].str)); + if (!(yyval.import)->import_performed) yychar = aEOF; + } +-#line 2896 "parser.tab.c" /* yacc.c:1648 */ ++#line 2891 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 51: +-#line 428 "parser.y" /* yacc.c:1648 */ ++#line 426 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[-2].import)->name; + if ((yyvsp[-2].import)->import_performed) pop_import(); + free((yyvsp[-2].import)); + } +-#line 2905 "parser.tab.c" /* yacc.c:1648 */ ++#line 2900 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 52: +-#line 435 "parser.y" /* yacc.c:1648 */ ++#line 433 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[-2].str); if(!parse_only) add_importlib((yyvsp[-2].str), current_typelib); } +-#line 2911 "parser.tab.c" /* yacc.c:1648 */ ++#line 2906 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 53: +-#line 438 "parser.y" /* yacc.c:1648 */ ++#line 436 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[0].str); } +-#line 2917 "parser.tab.c" /* yacc.c:1648 */ ++#line 2912 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 54: +-#line 439 "parser.y" /* yacc.c:1648 */ ++#line 437 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[0].str); } +-#line 2923 "parser.tab.c" /* yacc.c:1648 */ ++#line 2918 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 55: +-#line 441 "parser.y" /* yacc.c:1648 */ ++#line 439 "parser.y" /* yacc.c:1646 */ + { (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 2931 "parser.tab.c" /* yacc.c:1648 */ ++#line 2926 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 56: +-#line 446 "parser.y" /* yacc.c:1648 */ ++#line 444 "parser.y" /* yacc.c:1646 */ + { (yyval.typelib) = (yyvsp[-3].typelib); (yyval.typelib)->stmts = (yyvsp[-2].stmt_list); } +-#line 2937 "parser.tab.c" /* yacc.c:1648 */ ++#line 2932 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 57: +-#line 449 "parser.y" /* yacc.c:1648 */ ++#line 447 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = NULL; } +-#line 2943 "parser.tab.c" /* yacc.c:1648 */ ++#line 2938 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 59: +-#line 453 "parser.y" /* yacc.c:1648 */ ++#line 451 "parser.y" /* yacc.c:1646 */ + { check_arg_attrs((yyvsp[0].var)); (yyval.var_list) = append_var( NULL, (yyvsp[0].var) ); } +-#line 2949 "parser.tab.c" /* yacc.c:1648 */ ++#line 2944 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 60: +-#line 454 "parser.y" /* yacc.c:1648 */ ++#line 452 "parser.y" /* yacc.c:1646 */ + { check_arg_attrs((yyvsp[0].var)); (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var) ); } +-#line 2955 "parser.tab.c" /* yacc.c:1648 */ ++#line 2950 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 62: +-#line 458 "parser.y" /* yacc.c:1648 */ ++#line 456 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = append_var( (yyvsp[-2].var_list), make_var(strdup("...")) ); } +-#line 2961 "parser.tab.c" /* yacc.c:1648 */ ++#line 2956 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 63: +-#line 462 "parser.y" /* yacc.c:1648 */ ++#line 460 "parser.y" /* yacc.c:1646 */ + { 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 2971 "parser.tab.c" /* yacc.c:1648 */ ++#line 2966 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 64: +-#line 467 "parser.y" /* yacc.c:1648 */ ++#line 465 "parser.y" /* yacc.c:1646 */ + { 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 2981 "parser.tab.c" /* yacc.c:1648 */ ++#line 2976 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 65: +-#line 474 "parser.y" /* yacc.c:1648 */ ++#line 472 "parser.y" /* yacc.c:1646 */ + { (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 2990 "parser.tab.c" /* yacc.c:1648 */ ++#line 2985 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 66: +-#line 478 "parser.y" /* yacc.c:1648 */ ++#line 476 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr(EXPR_VOID); } +-#line 2996 "parser.tab.c" /* yacc.c:1648 */ ++#line 2991 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 67: +-#line 479 "parser.y" /* yacc.c:1648 */ ++#line 477 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr(EXPR_VOID); } +-#line 3002 "parser.tab.c" /* yacc.c:1648 */ ++#line 2997 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 68: +-#line 482 "parser.y" /* yacc.c:1648 */ ++#line 480 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = NULL; } +-#line 3008 "parser.tab.c" /* yacc.c:1648 */ ++#line 3003 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 70: +-#line 487 "parser.y" /* yacc.c:1648 */ ++#line 485 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = (yyvsp[-1].attr_list); } +-#line 3014 "parser.tab.c" /* yacc.c:1648 */ ++#line 3009 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 71: +-#line 490 "parser.y" /* yacc.c:1648 */ ++#line 488 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = append_attr( NULL, (yyvsp[0].attr) ); } +-#line 3020 "parser.tab.c" /* yacc.c:1648 */ ++#line 3015 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 72: +-#line 491 "parser.y" /* yacc.c:1648 */ ++#line 489 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = append_attr( (yyvsp[-2].attr_list), (yyvsp[0].attr) ); } +-#line 3026 "parser.tab.c" /* yacc.c:1648 */ ++#line 3021 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 73: +-#line 492 "parser.y" /* yacc.c:1648 */ ++#line 490 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = append_attr( (yyvsp[-3].attr_list), (yyvsp[0].attr) ); } +-#line 3032 "parser.tab.c" /* yacc.c:1648 */ ++#line 3027 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 74: +-#line 495 "parser.y" /* yacc.c:1648 */ ++#line 493 "parser.y" /* yacc.c:1646 */ + { (yyval.str_list) = append_str( NULL, (yyvsp[0].str) ); } +-#line 3038 "parser.tab.c" /* yacc.c:1648 */ ++#line 3033 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 75: +-#line 496 "parser.y" /* yacc.c:1648 */ ++#line 494 "parser.y" /* yacc.c:1646 */ + { (yyval.str_list) = append_str( (yyvsp[-2].str_list), (yyvsp[0].str) ); } +-#line 3044 "parser.tab.c" /* yacc.c:1648 */ ++#line 3039 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 76: +-#line 499 "parser.y" /* yacc.c:1648 */ ++#line 497 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = NULL; } +-#line 3050 "parser.tab.c" /* yacc.c:1648 */ ++#line 3045 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 77: +-#line 500 "parser.y" /* yacc.c:1648 */ ++#line 498 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_AGGREGATABLE); } +-#line 3056 "parser.tab.c" /* yacc.c:1648 */ ++#line 3051 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 78: +-#line 501 "parser.y" /* yacc.c:1648 */ ++#line 499 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_ANNOTATION, (yyvsp[-1].str)); } +-#line 3062 "parser.tab.c" /* yacc.c:1648 */ ++#line 3057 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 79: +-#line 502 "parser.y" /* yacc.c:1648 */ ++#line 500 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_APPOBJECT); } +-#line 3068 "parser.tab.c" /* yacc.c:1648 */ ++#line 3063 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 80: +-#line 503 "parser.y" /* yacc.c:1648 */ ++#line 501 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_ASYNC); } +-#line 3074 "parser.tab.c" /* yacc.c:1648 */ ++#line 3069 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 81: +-#line 504 "parser.y" /* yacc.c:1648 */ ++#line 502 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_AUTO_HANDLE); } +-#line 3080 "parser.tab.c" /* yacc.c:1648 */ ++#line 3075 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 82: +-#line 505 "parser.y" /* yacc.c:1648 */ ++#line 503 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_BINDABLE); } +-#line 3086 "parser.tab.c" /* yacc.c:1648 */ ++#line 3081 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 83: +-#line 506 "parser.y" /* yacc.c:1648 */ ++#line 504 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_BROADCAST); } +-#line 3092 "parser.tab.c" /* yacc.c:1648 */ ++#line 3087 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 84: +-#line 507 "parser.y" /* yacc.c:1648 */ ++#line 505 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_CALLAS, (yyvsp[-1].var)); } +-#line 3098 "parser.tab.c" /* yacc.c:1648 */ ++#line 3093 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 85: +-#line 508 "parser.y" /* yacc.c:1648 */ ++#line 506 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_CASE, (yyvsp[-1].expr_list)); } +-#line 3104 "parser.tab.c" /* yacc.c:1648 */ ++#line 3099 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 86: +-#line 509 "parser.y" /* yacc.c:1648 */ ++#line 507 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_CODE); } +-#line 3110 "parser.tab.c" /* yacc.c:1648 */ ++#line 3105 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 87: +-#line 510 "parser.y" /* yacc.c:1648 */ ++#line 508 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_COMMSTATUS); } +-#line 3116 "parser.tab.c" /* yacc.c:1648 */ ++#line 3111 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 88: +-#line 511 "parser.y" /* yacc.c:1648 */ ++#line 509 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); } +-#line 3122 "parser.tab.c" /* yacc.c:1648 */ ++#line 3117 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 89: +-#line 512 "parser.y" /* yacc.c:1648 */ ++#line 510 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } +-#line 3128 "parser.tab.c" /* yacc.c:1648 */ ++#line 3123 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 90: +-#line 513 "parser.y" /* yacc.c:1648 */ ++#line 511 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } +-#line 3134 "parser.tab.c" /* yacc.c:1648 */ ++#line 3129 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 91: +-#line 514 "parser.y" /* yacc.c:1648 */ ++#line 512 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_CONTROL); } +-#line 3140 "parser.tab.c" /* yacc.c:1648 */ ++#line 3135 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 92: +-#line 515 "parser.y" /* yacc.c:1648 */ ++#line 513 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DECODE); } +-#line 3146 "parser.tab.c" /* yacc.c:1648 */ ++#line 3141 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 93: +-#line 516 "parser.y" /* yacc.c:1648 */ ++#line 514 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DEFAULT); } +-#line 3152 "parser.tab.c" /* yacc.c:1648 */ ++#line 3147 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 94: +-#line 517 "parser.y" /* yacc.c:1648 */ ++#line 515 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DEFAULTBIND); } +-#line 3158 "parser.tab.c" /* yacc.c:1648 */ ++#line 3153 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 95: +-#line 518 "parser.y" /* yacc.c:1648 */ ++#line 516 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DEFAULTCOLLELEM); } +-#line 3164 "parser.tab.c" /* yacc.c:1648 */ ++#line 3159 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 96: +-#line 519 "parser.y" /* yacc.c:1648 */ ++#line 517 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_DEFAULTVALUE, (yyvsp[-1].expr)); } +-#line 3170 "parser.tab.c" /* yacc.c:1648 */ ++#line 3165 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 97: +-#line 520 "parser.y" /* yacc.c:1648 */ ++#line 518 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DEFAULTVTABLE); } +-#line 3176 "parser.tab.c" /* yacc.c:1648 */ ++#line 3171 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 98: +-#line 521 "parser.y" /* yacc.c:1648 */ ++#line 519 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DISABLECONSISTENCYCHECK); } +-#line 3182 "parser.tab.c" /* yacc.c:1648 */ ++#line 3177 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 99: +-#line 522 "parser.y" /* yacc.c:1648 */ ++#line 520 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DISPLAYBIND); } +-#line 3188 "parser.tab.c" /* yacc.c:1648 */ ++#line 3183 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 100: +-#line 523 "parser.y" /* yacc.c:1648 */ ++#line 521 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_DLLNAME, (yyvsp[-1].str)); } +-#line 3194 "parser.tab.c" /* yacc.c:1648 */ ++#line 3189 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 101: +-#line 524 "parser.y" /* yacc.c:1648 */ ++#line 522 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DUAL); } +-#line 3200 "parser.tab.c" /* yacc.c:1648 */ ++#line 3195 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 102: +-#line 525 "parser.y" /* yacc.c:1648 */ ++#line 523 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_ENABLEALLOCATE); } +-#line 3206 "parser.tab.c" /* yacc.c:1648 */ ++#line 3201 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 103: +-#line 526 "parser.y" /* yacc.c:1648 */ ++#line 524 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_ENCODE); } +-#line 3212 "parser.tab.c" /* yacc.c:1648 */ ++#line 3207 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 104: +-#line 527 "parser.y" /* yacc.c:1648 */ ++#line 525 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_ENDPOINT, (yyvsp[-1].str_list)); } +-#line 3218 "parser.tab.c" /* yacc.c:1648 */ ++#line 3213 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 105: +-#line 528 "parser.y" /* yacc.c:1648 */ ++#line 526 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_ENTRY, (yyvsp[-1].expr)); } +-#line 3224 "parser.tab.c" /* yacc.c:1648 */ ++#line 3219 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 106: +-#line 529 "parser.y" /* yacc.c:1648 */ ++#line 527 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_EXPLICIT_HANDLE); } +-#line 3230 "parser.tab.c" /* yacc.c:1648 */ ++#line 3225 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 107: +-#line 530 "parser.y" /* yacc.c:1648 */ ++#line 528 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_FAULTSTATUS); } +-#line 3236 "parser.tab.c" /* yacc.c:1648 */ ++#line 3231 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 108: +-#line 531 "parser.y" /* yacc.c:1648 */ ++#line 529 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_FORCEALLOCATE); } +-#line 3242 "parser.tab.c" /* yacc.c:1648 */ ++#line 3237 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 109: +-#line 532 "parser.y" /* yacc.c:1648 */ ++#line 530 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_HANDLE); } +-#line 3248 "parser.tab.c" /* yacc.c:1648 */ ++#line 3243 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 110: +-#line 533 "parser.y" /* yacc.c:1648 */ ++#line 531 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_HELPCONTEXT, (yyvsp[-1].expr)); } +-#line 3254 "parser.tab.c" /* yacc.c:1648 */ ++#line 3249 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 111: +-#line 534 "parser.y" /* yacc.c:1648 */ ++#line 532 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_HELPFILE, (yyvsp[-1].str)); } +-#line 3260 "parser.tab.c" /* yacc.c:1648 */ ++#line 3255 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 112: +-#line 535 "parser.y" /* yacc.c:1648 */ ++#line 533 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_HELPSTRING, (yyvsp[-1].str)); } +-#line 3266 "parser.tab.c" /* yacc.c:1648 */ ++#line 3261 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 113: +-#line 536 "parser.y" /* yacc.c:1648 */ ++#line 534 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_HELPSTRINGCONTEXT, (yyvsp[-1].expr)); } +-#line 3272 "parser.tab.c" /* yacc.c:1648 */ ++#line 3267 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 114: +-#line 537 "parser.y" /* yacc.c:1648 */ ++#line 535 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_HELPSTRINGDLL, (yyvsp[-1].str)); } +-#line 3278 "parser.tab.c" /* yacc.c:1648 */ ++#line 3273 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 115: +-#line 538 "parser.y" /* yacc.c:1648 */ ++#line 536 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_HIDDEN); } +-#line 3284 "parser.tab.c" /* yacc.c:1648 */ ++#line 3279 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 116: +-#line 539 "parser.y" /* yacc.c:1648 */ ++#line 537 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_ID, (yyvsp[-1].expr)); } +-#line 3290 "parser.tab.c" /* yacc.c:1648 */ ++#line 3285 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 117: +-#line 540 "parser.y" /* yacc.c:1648 */ ++#line 538 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_IDEMPOTENT); } +-#line 3296 "parser.tab.c" /* yacc.c:1648 */ ++#line 3291 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 118: +-#line 541 "parser.y" /* yacc.c:1648 */ ++#line 539 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_IGNORE); } +-#line 3302 "parser.tab.c" /* yacc.c:1648 */ ++#line 3297 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 119: +-#line 542 "parser.y" /* yacc.c:1648 */ ++#line 540 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_IIDIS, (yyvsp[-1].expr)); } +-#line 3308 "parser.tab.c" /* yacc.c:1648 */ ++#line 3303 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 120: +-#line 543 "parser.y" /* yacc.c:1648 */ ++#line 541 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_IMMEDIATEBIND); } +-#line 3314 "parser.tab.c" /* yacc.c:1648 */ ++#line 3309 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 121: +-#line 544 "parser.y" /* yacc.c:1648 */ ++#line 542 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_IMPLICIT_HANDLE, (yyvsp[-1].var)); } +-#line 3320 "parser.tab.c" /* yacc.c:1648 */ ++#line 3315 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 122: +-#line 545 "parser.y" /* yacc.c:1648 */ ++#line 543 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_IN); } +-#line 3326 "parser.tab.c" /* yacc.c:1648 */ ++#line 3321 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 123: +-#line 546 "parser.y" /* yacc.c:1648 */ ++#line 544 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_INPUTSYNC); } +-#line 3332 "parser.tab.c" /* yacc.c:1648 */ ++#line 3327 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 124: +-#line 547 "parser.y" /* yacc.c:1648 */ ++#line 545 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_LENGTHIS, (yyvsp[-1].expr_list)); } +-#line 3338 "parser.tab.c" /* yacc.c:1648 */ ++#line 3333 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 125: +-#line 548 "parser.y" /* yacc.c:1648 */ ++#line 546 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_LIBLCID, (yyvsp[-1].expr)); } +-#line 3344 "parser.tab.c" /* yacc.c:1648 */ ++#line 3339 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 126: +-#line 549 "parser.y" /* yacc.c:1648 */ ++#line 547 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_PARAMLCID); } +-#line 3350 "parser.tab.c" /* yacc.c:1648 */ ++#line 3345 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 127: +-#line 550 "parser.y" /* yacc.c:1648 */ ++#line 548 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_LICENSED); } +-#line 3356 "parser.tab.c" /* yacc.c:1648 */ ++#line 3351 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 128: +-#line 551 "parser.y" /* yacc.c:1648 */ ++#line 549 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_LOCAL); } +-#line 3362 "parser.tab.c" /* yacc.c:1648 */ ++#line 3357 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 129: +-#line 552 "parser.y" /* yacc.c:1648 */ ++#line 550 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_MAYBE); } +-#line 3368 "parser.tab.c" /* yacc.c:1648 */ ++#line 3363 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 130: +-#line 553 "parser.y" /* yacc.c:1648 */ ++#line 551 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_MESSAGE); } +-#line 3374 "parser.tab.c" /* yacc.c:1648 */ ++#line 3369 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 131: +-#line 554 "parser.y" /* yacc.c:1648 */ ++#line 552 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_NOCODE); } +-#line 3380 "parser.tab.c" /* yacc.c:1648 */ ++#line 3375 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 132: +-#line 555 "parser.y" /* yacc.c:1648 */ ++#line 553 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_NONBROWSABLE); } +-#line 3386 "parser.tab.c" /* yacc.c:1648 */ ++#line 3381 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 133: +-#line 556 "parser.y" /* yacc.c:1648 */ ++#line 554 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_NONCREATABLE); } +-#line 3392 "parser.tab.c" /* yacc.c:1648 */ ++#line 3387 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 134: +-#line 557 "parser.y" /* yacc.c:1648 */ ++#line 555 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_NONEXTENSIBLE); } +-#line 3398 "parser.tab.c" /* yacc.c:1648 */ ++#line 3393 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 135: +-#line 558 "parser.y" /* yacc.c:1648 */ ++#line 556 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_NOTIFY); } +-#line 3404 "parser.tab.c" /* yacc.c:1648 */ ++#line 3399 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 136: +-#line 559 "parser.y" /* yacc.c:1648 */ ++#line 557 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_NOTIFYFLAG); } +-#line 3410 "parser.tab.c" /* yacc.c:1648 */ ++#line 3405 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 137: +-#line 560 "parser.y" /* yacc.c:1648 */ ++#line 558 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_OBJECT); } +-#line 3416 "parser.tab.c" /* yacc.c:1648 */ ++#line 3411 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 138: +-#line 561 "parser.y" /* yacc.c:1648 */ ++#line 559 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_ODL); } +-#line 3422 "parser.tab.c" /* yacc.c:1648 */ ++#line 3417 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 139: +-#line 562 "parser.y" /* yacc.c:1648 */ ++#line 560 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_OLEAUTOMATION); } +-#line 3428 "parser.tab.c" /* yacc.c:1648 */ ++#line 3423 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 140: +-#line 563 "parser.y" /* yacc.c:1648 */ ++#line 561 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_OPTIMIZE, (yyvsp[-1].str)); } +-#line 3434 "parser.tab.c" /* yacc.c:1648 */ ++#line 3429 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 141: +-#line 564 "parser.y" /* yacc.c:1648 */ ++#line 562 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_OPTIONAL); } +-#line 3440 "parser.tab.c" /* yacc.c:1648 */ ++#line 3435 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 142: +-#line 565 "parser.y" /* yacc.c:1648 */ ++#line 563 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_OUT); } +-#line 3446 "parser.tab.c" /* yacc.c:1648 */ ++#line 3441 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 143: +-#line 566 "parser.y" /* yacc.c:1648 */ ++#line 564 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_PARTIALIGNORE); } +-#line 3452 "parser.tab.c" /* yacc.c:1648 */ ++#line 3447 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 144: +-#line 567 "parser.y" /* yacc.c:1648 */ ++#line 565 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrv(ATTR_POINTERDEFAULT, (yyvsp[-1].num)); } +-#line 3458 "parser.tab.c" /* yacc.c:1648 */ ++#line 3453 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 145: +-#line 568 "parser.y" /* yacc.c:1648 */ ++#line 566 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_PROGID, (yyvsp[-1].str)); } +-#line 3464 "parser.tab.c" /* yacc.c:1648 */ ++#line 3459 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 146: +-#line 569 "parser.y" /* yacc.c:1648 */ ++#line 567 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_PROPGET); } +-#line 3470 "parser.tab.c" /* yacc.c:1648 */ ++#line 3465 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 147: +-#line 570 "parser.y" /* yacc.c:1648 */ ++#line 568 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_PROPPUT); } +-#line 3476 "parser.tab.c" /* yacc.c:1648 */ ++#line 3471 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 148: +-#line 571 "parser.y" /* yacc.c:1648 */ ++#line 569 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_PROPPUTREF); } +-#line 3482 "parser.tab.c" /* yacc.c:1648 */ ++#line 3477 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 149: +-#line 572 "parser.y" /* yacc.c:1648 */ ++#line 570 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_PROXY); } +-#line 3488 "parser.tab.c" /* yacc.c:1648 */ ++#line 3483 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 150: +-#line 573 "parser.y" /* yacc.c:1648 */ ++#line 571 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_PUBLIC); } +-#line 3494 "parser.tab.c" /* yacc.c:1648 */ ++#line 3489 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 151: +-#line 575 "parser.y" /* yacc.c:1648 */ ++#line 573 "parser.y" /* yacc.c:1646 */ + { expr_list_t *list = append_expr( NULL, (yyvsp[-3].expr) ); + list = append_expr( list, (yyvsp[-1].expr) ); + (yyval.attr) = make_attrp(ATTR_RANGE, list); } +-#line 3502 "parser.tab.c" /* yacc.c:1648 */ ++#line 3497 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 152: +-#line 578 "parser.y" /* yacc.c:1648 */ ++#line 576 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_READONLY); } +-#line 3508 "parser.tab.c" /* yacc.c:1648 */ ++#line 3503 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 153: +-#line 579 "parser.y" /* yacc.c:1648 */ ++#line 577 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_REPRESENTAS, (yyvsp[-1].type)); } +-#line 3514 "parser.tab.c" /* yacc.c:1648 */ ++#line 3509 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 154: +-#line 580 "parser.y" /* yacc.c:1648 */ ++#line 578 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_REQUESTEDIT); } +-#line 3520 "parser.tab.c" /* yacc.c:1648 */ ++#line 3515 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 155: +-#line 581 "parser.y" /* yacc.c:1648 */ ++#line 579 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_RESTRICTED); } +-#line 3526 "parser.tab.c" /* yacc.c:1648 */ ++#line 3521 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 156: +-#line 582 "parser.y" /* yacc.c:1648 */ ++#line 580 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_RETVAL); } +-#line 3532 "parser.tab.c" /* yacc.c:1648 */ ++#line 3527 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 157: +-#line 583 "parser.y" /* yacc.c:1648 */ ++#line 581 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_SIZEIS, (yyvsp[-1].expr_list)); } +-#line 3538 "parser.tab.c" /* yacc.c:1648 */ ++#line 3533 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 158: +-#line 584 "parser.y" /* yacc.c:1648 */ ++#line 582 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_SOURCE); } +-#line 3544 "parser.tab.c" /* yacc.c:1648 */ ++#line 3539 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 159: +-#line 585 "parser.y" /* yacc.c:1648 */ ++#line 583 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_STRICTCONTEXTHANDLE); } +-#line 3550 "parser.tab.c" /* yacc.c:1648 */ ++#line 3545 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 160: +-#line 586 "parser.y" /* yacc.c:1648 */ ++#line 584 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_STRING); } +-#line 3556 "parser.tab.c" /* yacc.c:1648 */ ++#line 3551 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 161: +-#line 587 "parser.y" /* yacc.c:1648 */ ++#line 585 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_SWITCHIS, (yyvsp[-1].expr)); } +-#line 3562 "parser.tab.c" /* yacc.c:1648 */ ++#line 3557 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 162: +-#line 588 "parser.y" /* yacc.c:1648 */ ++#line 586 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_SWITCHTYPE, (yyvsp[-1].type)); } +-#line 3568 "parser.tab.c" /* yacc.c:1648 */ ++#line 3563 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 163: +-#line 589 "parser.y" /* yacc.c:1648 */ ++#line 587 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_TRANSMITAS, (yyvsp[-1].type)); } +-#line 3574 "parser.tab.c" /* yacc.c:1648 */ ++#line 3569 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 164: +-#line 590 "parser.y" /* yacc.c:1648 */ ++#line 588 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrv(ATTR_THREADING, (yyvsp[-1].num)); } +-#line 3580 "parser.tab.c" /* yacc.c:1648 */ ++#line 3575 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 165: +-#line 591 "parser.y" /* yacc.c:1648 */ ++#line 589 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_UIDEFAULT); } +-#line 3586 "parser.tab.c" /* yacc.c:1648 */ ++#line 3581 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 166: +-#line 592 "parser.y" /* yacc.c:1648 */ ++#line 590 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_USESGETLASTERROR); } +-#line 3592 "parser.tab.c" /* yacc.c:1648 */ ++#line 3587 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 167: +-#line 593 "parser.y" /* yacc.c:1648 */ ++#line 591 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_USERMARSHAL, (yyvsp[-1].type)); } +-#line 3598 "parser.tab.c" /* yacc.c:1648 */ ++#line 3593 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 168: +-#line 594 "parser.y" /* yacc.c:1648 */ ++#line 592 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_UUID, (yyvsp[-1].uuid)); } +-#line 3604 "parser.tab.c" /* yacc.c:1648 */ ++#line 3599 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 169: +-#line 595 "parser.y" /* yacc.c:1648 */ ++#line 593 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_ASYNCUUID, (yyvsp[-1].uuid)); } +-#line 3610 "parser.tab.c" /* yacc.c:1648 */ ++#line 3605 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 170: +-#line 596 "parser.y" /* yacc.c:1648 */ ++#line 594 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_V1ENUM); } +-#line 3616 "parser.tab.c" /* yacc.c:1648 */ ++#line 3611 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 171: +-#line 597 "parser.y" /* yacc.c:1648 */ ++#line 595 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_VARARG); } +-#line 3622 "parser.tab.c" /* yacc.c:1648 */ ++#line 3617 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 172: +-#line 598 "parser.y" /* yacc.c:1648 */ ++#line 596 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrv(ATTR_VERSION, (yyvsp[-1].num)); } +-#line 3628 "parser.tab.c" /* yacc.c:1648 */ ++#line 3623 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 173: +-#line 599 "parser.y" /* yacc.c:1648 */ ++#line 597 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_VIPROGID, (yyvsp[-1].str)); } +-#line 3634 "parser.tab.c" /* yacc.c:1648 */ ++#line 3629 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 174: +-#line 600 "parser.y" /* yacc.c:1648 */ ++#line 598 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrp(ATTR_WIREMARSHAL, (yyvsp[-1].type)); } +-#line 3640 "parser.tab.c" /* yacc.c:1648 */ ++#line 3635 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 175: +-#line 601 "parser.y" /* yacc.c:1648 */ ++#line 599 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attrv(ATTR_POINTERTYPE, (yyvsp[0].num)); } +-#line 3646 "parser.tab.c" /* yacc.c:1648 */ ++#line 3641 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 177: +-#line 606 "parser.y" /* yacc.c:1648 */ ++#line 604 "parser.y" /* yacc.c:1646 */ + { if (!is_valid_uuid((yyvsp[0].str))) + error_loc("invalid UUID: %s\n", (yyvsp[0].str)); + (yyval.uuid) = parse_uuid((yyvsp[0].str)); } +-#line 3654 "parser.tab.c" /* yacc.c:1648 */ ++#line 3649 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 178: +-#line 611 "parser.y" /* yacc.c:1648 */ ++#line 609 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = xstrdup("__cdecl"); } +-#line 3660 "parser.tab.c" /* yacc.c:1648 */ ++#line 3655 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 179: +-#line 612 "parser.y" /* yacc.c:1648 */ ++#line 610 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = xstrdup("__fastcall"); } +-#line 3666 "parser.tab.c" /* yacc.c:1648 */ ++#line 3661 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 180: +-#line 613 "parser.y" /* yacc.c:1648 */ ++#line 611 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = xstrdup("__pascal"); } +-#line 3672 "parser.tab.c" /* yacc.c:1648 */ ++#line 3667 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 181: +-#line 614 "parser.y" /* yacc.c:1648 */ ++#line 612 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = xstrdup("__stdcall"); } +-#line 3678 "parser.tab.c" /* yacc.c:1648 */ ++#line 3673 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 182: +-#line 617 "parser.y" /* yacc.c:1648 */ ++#line 615 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = NULL; } +-#line 3684 "parser.tab.c" /* yacc.c:1648 */ ++#line 3679 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 183: +-#line 618 "parser.y" /* yacc.c:1648 */ ++#line 616 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); } +-#line 3690 "parser.tab.c" /* yacc.c:1648 */ ++#line 3685 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 184: +-#line 621 "parser.y" /* yacc.c:1648 */ ++#line 619 "parser.y" /* yacc.c:1646 */ + { attr_t *a = make_attrp(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 3699 "parser.tab.c" /* yacc.c:1648 */ ++#line 3694 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 185: +-#line 625 "parser.y" /* yacc.c:1648 */ ++#line 623 "parser.y" /* yacc.c:1646 */ + { attr_t *a = make_attr(ATTR_DEFAULT); + (yyval.var) = (yyvsp[0].var); if (!(yyval.var)) (yyval.var) = make_var(NULL); + (yyval.var)->attrs = append_attr( (yyval.var)->attrs, a ); + } +-#line 3708 "parser.tab.c" /* yacc.c:1648 */ ++#line 3703 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 186: +-#line 631 "parser.y" /* yacc.c:1648 */ ++#line 629 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = NULL; } +-#line 3714 "parser.tab.c" /* yacc.c:1648 */ ++#line 3709 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 187: +-#line 632 "parser.y" /* yacc.c:1648 */ ++#line 630 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = (yyvsp[-1].var_list); } +-#line 3720 "parser.tab.c" /* yacc.c:1648 */ ++#line 3715 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 189: +-#line 636 "parser.y" /* yacc.c:1648 */ ++#line 634 "parser.y" /* yacc.c:1646 */ + { if (!(yyvsp[0].var)->eval) + (yyvsp[0].var)->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */); + (yyval.var_list) = append_var( NULL, (yyvsp[0].var) ); + } +-#line 3729 "parser.tab.c" /* yacc.c:1648 */ ++#line 3724 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 190: +-#line 640 "parser.y" /* yacc.c:1648 */ ++#line 638 "parser.y" /* yacc.c:1646 */ + { if (!(yyvsp[0].var)->eval) + { + var_t *last = LIST_ENTRY( list_tail((yyval.var_list)), var_t, entry ); +@@ -3740,656 +3735,656 @@ yyreduce: + } + (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var) ); + } +-#line 3744 "parser.tab.c" /* yacc.c:1648 */ ++#line 3739 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 191: +-#line 652 "parser.y" /* yacc.c:1648 */ ++#line 650 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = reg_const((yyvsp[-2].var)); + (yyval.var)->eval = (yyvsp[0].expr); +- (yyval.var)->type = type_new_int(TYPE_BASIC_INT, 0); ++ (yyval.var)->declspec.type = type_new_int(TYPE_BASIC_INT, 0); + } +-#line 3753 "parser.tab.c" /* yacc.c:1648 */ ++#line 3748 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 192: +-#line 656 "parser.y" /* yacc.c:1648 */ ++#line 654 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = reg_const((yyvsp[0].var)); +- (yyval.var)->type = type_new_int(TYPE_BASIC_INT, 0); ++ (yyval.var)->declspec.type = type_new_int(TYPE_BASIC_INT, 0); + } +-#line 3761 "parser.tab.c" /* yacc.c:1648 */ ++#line 3756 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 193: +-#line 661 "parser.y" /* yacc.c:1648 */ ++#line 659 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_enum((yyvsp[-3].str), current_namespace, TRUE, (yyvsp[-1].var_list)); } +-#line 3767 "parser.tab.c" /* yacc.c:1648 */ ++#line 3762 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 194: +-#line 664 "parser.y" /* yacc.c:1648 */ ++#line 662 "parser.y" /* yacc.c:1646 */ + { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); } +-#line 3773 "parser.tab.c" /* yacc.c:1648 */ ++#line 3768 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 195: +-#line 665 "parser.y" /* yacc.c:1648 */ ++#line 663 "parser.y" /* yacc.c:1646 */ + { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); } +-#line 3779 "parser.tab.c" /* yacc.c:1648 */ ++#line 3774 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 196: +-#line 668 "parser.y" /* yacc.c:1648 */ ++#line 666 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr(EXPR_VOID); } +-#line 3785 "parser.tab.c" /* yacc.c:1648 */ ++#line 3780 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 198: +-#line 672 "parser.y" /* yacc.c:1648 */ ++#line 670 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprl(EXPR_NUM, (yyvsp[0].num)); } +-#line 3791 "parser.tab.c" /* yacc.c:1648 */ ++#line 3786 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 199: +-#line 673 "parser.y" /* yacc.c:1648 */ ++#line 671 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprl(EXPR_HEXNUM, (yyvsp[0].num)); } +-#line 3797 "parser.tab.c" /* yacc.c:1648 */ ++#line 3792 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 200: +-#line 674 "parser.y" /* yacc.c:1648 */ ++#line 672 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprd(EXPR_DOUBLE, (yyvsp[0].dbl)); } +-#line 3803 "parser.tab.c" /* yacc.c:1648 */ ++#line 3798 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 201: +-#line 675 "parser.y" /* yacc.c:1648 */ ++#line 673 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprl(EXPR_TRUEFALSE, 0); } +-#line 3809 "parser.tab.c" /* yacc.c:1648 */ ++#line 3804 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 202: +-#line 676 "parser.y" /* yacc.c:1648 */ ++#line 674 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprl(EXPR_NUM, 0); } +-#line 3815 "parser.tab.c" /* yacc.c:1648 */ ++#line 3810 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 203: +-#line 677 "parser.y" /* yacc.c:1648 */ ++#line 675 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprl(EXPR_TRUEFALSE, 1); } +-#line 3821 "parser.tab.c" /* yacc.c:1648 */ ++#line 3816 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 204: +-#line 678 "parser.y" /* yacc.c:1648 */ ++#line 676 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprs(EXPR_STRLIT, (yyvsp[0].str)); } +-#line 3827 "parser.tab.c" /* yacc.c:1648 */ ++#line 3822 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 205: +-#line 679 "parser.y" /* yacc.c:1648 */ ++#line 677 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprs(EXPR_WSTRLIT, (yyvsp[0].str)); } +-#line 3833 "parser.tab.c" /* yacc.c:1648 */ ++#line 3828 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 206: +-#line 680 "parser.y" /* yacc.c:1648 */ ++#line 678 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprs(EXPR_CHARCONST, (yyvsp[0].str)); } +-#line 3839 "parser.tab.c" /* yacc.c:1648 */ ++#line 3834 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 207: +-#line 681 "parser.y" /* yacc.c:1648 */ ++#line 679 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str)); } +-#line 3845 "parser.tab.c" /* yacc.c:1648 */ ++#line 3840 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 208: +-#line 682 "parser.y" /* yacc.c:1648 */ ++#line 680 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr3(EXPR_COND, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3851 "parser.tab.c" /* yacc.c:1648 */ ++#line 3846 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 209: +-#line 683 "parser.y" /* yacc.c:1648 */ ++#line 681 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_LOGOR, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3857 "parser.tab.c" /* yacc.c:1648 */ ++#line 3852 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 210: +-#line 684 "parser.y" /* yacc.c:1648 */ ++#line 682 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_LOGAND, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3863 "parser.tab.c" /* yacc.c:1648 */ ++#line 3858 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 211: +-#line 685 "parser.y" /* yacc.c:1648 */ ++#line 683 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_OR , (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3869 "parser.tab.c" /* yacc.c:1648 */ ++#line 3864 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 212: +-#line 686 "parser.y" /* yacc.c:1648 */ ++#line 684 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_XOR, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3875 "parser.tab.c" /* yacc.c:1648 */ ++#line 3870 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 213: +-#line 687 "parser.y" /* yacc.c:1648 */ ++#line 685 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3881 "parser.tab.c" /* yacc.c:1648 */ ++#line 3876 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 214: +-#line 688 "parser.y" /* yacc.c:1648 */ ++#line 686 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_EQUALITY, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3887 "parser.tab.c" /* yacc.c:1648 */ ++#line 3882 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 215: +-#line 689 "parser.y" /* yacc.c:1648 */ ++#line 687 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_INEQUALITY, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3893 "parser.tab.c" /* yacc.c:1648 */ ++#line 3888 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 216: +-#line 690 "parser.y" /* yacc.c:1648 */ ++#line 688 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_GTR, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3899 "parser.tab.c" /* yacc.c:1648 */ ++#line 3894 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 217: +-#line 691 "parser.y" /* yacc.c:1648 */ ++#line 689 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_LESS, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3905 "parser.tab.c" /* yacc.c:1648 */ ++#line 3900 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 218: +-#line 692 "parser.y" /* yacc.c:1648 */ ++#line 690 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_GTREQL, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3911 "parser.tab.c" /* yacc.c:1648 */ ++#line 3906 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 219: +-#line 693 "parser.y" /* yacc.c:1648 */ ++#line 691 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_LESSEQL, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3917 "parser.tab.c" /* yacc.c:1648 */ ++#line 3912 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 220: +-#line 694 "parser.y" /* yacc.c:1648 */ ++#line 692 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_SHL, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3923 "parser.tab.c" /* yacc.c:1648 */ ++#line 3918 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 221: +-#line 695 "parser.y" /* yacc.c:1648 */ ++#line 693 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_SHR, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3929 "parser.tab.c" /* yacc.c:1648 */ ++#line 3924 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 222: +-#line 696 "parser.y" /* yacc.c:1648 */ ++#line 694 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_ADD, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3935 "parser.tab.c" /* yacc.c:1648 */ ++#line 3930 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 223: +-#line 697 "parser.y" /* yacc.c:1648 */ ++#line 695 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_SUB, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3941 "parser.tab.c" /* yacc.c:1648 */ ++#line 3936 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 224: +-#line 698 "parser.y" /* yacc.c:1648 */ ++#line 696 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_MOD, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3947 "parser.tab.c" /* yacc.c:1648 */ ++#line 3942 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 225: +-#line 699 "parser.y" /* yacc.c:1648 */ ++#line 697 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_MUL, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3953 "parser.tab.c" /* yacc.c:1648 */ ++#line 3948 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 226: +-#line 700 "parser.y" /* yacc.c:1648 */ ++#line 698 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_DIV, (yyvsp[-2].expr), (yyvsp[0].expr)); } +-#line 3959 "parser.tab.c" /* yacc.c:1648 */ ++#line 3954 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 227: +-#line 701 "parser.y" /* yacc.c:1648 */ ++#line 699 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr1(EXPR_LOGNOT, (yyvsp[0].expr)); } +-#line 3965 "parser.tab.c" /* yacc.c:1648 */ ++#line 3960 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 228: +-#line 702 "parser.y" /* yacc.c:1648 */ ++#line 700 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr1(EXPR_NOT, (yyvsp[0].expr)); } +-#line 3971 "parser.tab.c" /* yacc.c:1648 */ ++#line 3966 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 229: +-#line 703 "parser.y" /* yacc.c:1648 */ ++#line 701 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr1(EXPR_POS, (yyvsp[0].expr)); } +-#line 3977 "parser.tab.c" /* yacc.c:1648 */ ++#line 3972 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 230: +-#line 704 "parser.y" /* yacc.c:1648 */ ++#line 702 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr1(EXPR_NEG, (yyvsp[0].expr)); } +-#line 3983 "parser.tab.c" /* yacc.c:1648 */ ++#line 3978 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 231: +-#line 705 "parser.y" /* yacc.c:1648 */ ++#line 703 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr1(EXPR_ADDRESSOF, (yyvsp[0].expr)); } +-#line 3989 "parser.tab.c" /* yacc.c:1648 */ ++#line 3984 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 232: +-#line 706 "parser.y" /* yacc.c:1648 */ ++#line 704 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr1(EXPR_PPTR, (yyvsp[0].expr)); } +-#line 3995 "parser.tab.c" /* yacc.c:1648 */ ++#line 3990 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 233: +-#line 707 "parser.y" /* yacc.c:1648 */ ++#line 705 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_MEMBER, make_expr1(EXPR_PPTR, (yyvsp[-2].expr)), make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str))); } +-#line 4001 "parser.tab.c" /* yacc.c:1648 */ ++#line 3996 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 234: +-#line 708 "parser.y" /* yacc.c:1648 */ ++#line 706 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_MEMBER, (yyvsp[-2].expr), make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str))); } +-#line 4007 "parser.tab.c" /* yacc.c:1648 */ ++#line 4002 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 235: +-#line 710 "parser.y" /* yacc.c:1648 */ ++#line 708 "parser.y" /* yacc.c:1646 */ + { (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 4013 "parser.tab.c" /* yacc.c:1648 */ ++#line 4008 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 236: +-#line 712 "parser.y" /* yacc.c:1648 */ ++#line 710 "parser.y" /* yacc.c:1646 */ + { (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 4019 "parser.tab.c" /* yacc.c:1648 */ ++#line 4014 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 237: +-#line 713 "parser.y" /* yacc.c:1648 */ ++#line 711 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = make_expr2(EXPR_ARRAY, (yyvsp[-3].expr), (yyvsp[-1].expr)); } +-#line 4025 "parser.tab.c" /* yacc.c:1648 */ ++#line 4020 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 238: +-#line 714 "parser.y" /* yacc.c:1648 */ ++#line 712 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = (yyvsp[-1].expr); } +-#line 4031 "parser.tab.c" /* yacc.c:1648 */ ++#line 4026 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 239: +-#line 717 "parser.y" /* yacc.c:1648 */ ++#line 715 "parser.y" /* yacc.c:1646 */ + { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); } +-#line 4037 "parser.tab.c" /* yacc.c:1648 */ ++#line 4032 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 240: +-#line 718 "parser.y" /* yacc.c:1648 */ ++#line 716 "parser.y" /* yacc.c:1646 */ + { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); } +-#line 4043 "parser.tab.c" /* yacc.c:1648 */ ++#line 4038 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 241: +-#line 721 "parser.y" /* yacc.c:1648 */ ++#line 719 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = (yyvsp[0].expr); + if (!(yyval.expr)->is_const) + error_loc("expression is not an integer constant\n"); + } +-#line 4052 "parser.tab.c" /* yacc.c:1648 */ ++#line 4047 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 242: +-#line 727 "parser.y" /* yacc.c:1648 */ ++#line 725 "parser.y" /* yacc.c:1646 */ + { (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 4061 "parser.tab.c" /* yacc.c:1648 */ ++#line 4056 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 243: +-#line 733 "parser.y" /* yacc.c:1648 */ ++#line 731 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = NULL; } +-#line 4067 "parser.tab.c" /* yacc.c:1648 */ ++#line 4062 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 244: +-#line 734 "parser.y" /* yacc.c:1648 */ ++#line 732 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = append_var_list((yyvsp[-1].var_list), (yyvsp[0].var_list)); } +-#line 4073 "parser.tab.c" /* yacc.c:1648 */ ++#line 4068 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 245: +-#line 738 "parser.y" /* yacc.c:1648 */ ++#line 736 "parser.y" /* yacc.c:1646 */ + { 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 4082 "parser.tab.c" /* yacc.c:1648 */ ++#line 4077 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 246: +-#line 742 "parser.y" /* yacc.c:1648 */ ++#line 740 "parser.y" /* yacc.c:1646 */ + { var_t *v = make_var(NULL); +- v->type = (yyvsp[-1].type); v->attrs = (yyvsp[-2].attr_list); ++ v->declspec.type = (yyvsp[-1].type); v->attrs = (yyvsp[-2].attr_list); + (yyval.var_list) = append_var(NULL, v); + } +-#line 4091 "parser.tab.c" /* yacc.c:1648 */ ++#line 4086 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 247: +-#line 749 "parser.y" /* yacc.c:1648 */ ++#line 747 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = (yyvsp[-1].var); } +-#line 4097 "parser.tab.c" /* yacc.c:1648 */ ++#line 4092 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 248: +-#line 750 "parser.y" /* yacc.c:1648 */ ++#line 748 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = make_var(NULL); (yyval.var)->attrs = (yyvsp[-1].attr_list); } +-#line 4103 "parser.tab.c" /* yacc.c:1648 */ ++#line 4098 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 249: +-#line 753 "parser.y" /* yacc.c:1648 */ ++#line 751 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = NULL; } +-#line 4109 "parser.tab.c" /* yacc.c:1648 */ ++#line 4104 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 250: +-#line 754 "parser.y" /* yacc.c:1648 */ ++#line 752 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); } +-#line 4115 "parser.tab.c" /* yacc.c:1648 */ ++#line 4110 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 251: +-#line 758 "parser.y" /* yacc.c:1648 */ ++#line 756 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = (yyvsp[-1].var); } +-#line 4121 "parser.tab.c" /* yacc.c:1648 */ ++#line 4116 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 252: +-#line 759 "parser.y" /* yacc.c:1648 */ ++#line 757 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = NULL; } +-#line 4127 "parser.tab.c" /* yacc.c:1648 */ ++#line 4122 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 253: +-#line 762 "parser.y" /* yacc.c:1648 */ ++#line 760 "parser.y" /* yacc.c:1646 */ + { (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 4136 "parser.tab.c" /* yacc.c:1648 */ ++#line 4131 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 254: +-#line 766 "parser.y" /* yacc.c:1648 */ ++#line 764 "parser.y" /* yacc.c:1646 */ + { var_t *v = make_var(NULL); +- v->type = (yyvsp[0].type); v->attrs = (yyvsp[-1].attr_list); ++ v->declspec.type = (yyvsp[0].type); v->attrs = (yyvsp[-1].attr_list); + (yyval.var) = v; + } +-#line 4145 "parser.tab.c" /* yacc.c:1648 */ ++#line 4140 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 255: +-#line 772 "parser.y" /* yacc.c:1648 */ ++#line 770 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = (yyvsp[0].var); +- if (type_get_type((yyval.var)->type) != TYPE_FUNCTION) ++ 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 4155 "parser.tab.c" /* yacc.c:1648 */ ++#line 4150 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 256: +-#line 781 "parser.y" /* yacc.c:1648 */ ++#line 779 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = declare_var((yyvsp[-2].attr_list), (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE); + free((yyvsp[0].declarator)); + } +-#line 4163 "parser.tab.c" /* yacc.c:1648 */ ++#line 4158 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 257: +-#line 784 "parser.y" /* yacc.c:1648 */ ++#line 782 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = declare_var(NULL, (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE); + free((yyvsp[0].declarator)); + } +-#line 4171 "parser.tab.c" /* yacc.c:1648 */ ++#line 4166 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 258: +-#line 789 "parser.y" /* yacc.c:1648 */ ++#line 787 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = NULL; } +-#line 4177 "parser.tab.c" /* yacc.c:1648 */ ++#line 4172 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 260: +-#line 793 "parser.y" /* yacc.c:1648 */ ++#line 791 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = NULL; } +-#line 4183 "parser.tab.c" /* yacc.c:1648 */ ++#line 4178 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 261: +-#line 794 "parser.y" /* yacc.c:1648 */ ++#line 792 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[0].str); } +-#line 4189 "parser.tab.c" /* yacc.c:1648 */ ++#line 4184 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 262: +-#line 795 "parser.y" /* yacc.c:1648 */ ++#line 793 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[0].str); } +-#line 4195 "parser.tab.c" /* yacc.c:1648 */ ++#line 4190 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 263: +-#line 798 "parser.y" /* yacc.c:1648 */ ++#line 796 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = make_var((yyvsp[0].str)); } +-#line 4201 "parser.tab.c" /* yacc.c:1648 */ ++#line 4196 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 264: +-#line 800 "parser.y" /* yacc.c:1648 */ ++#line 798 "parser.y" /* yacc.c:1646 */ + { (yyval.var) = make_var((yyvsp[0].str)); } +-#line 4207 "parser.tab.c" /* yacc.c:1648 */ ++#line 4202 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 265: +-#line 803 "parser.y" /* yacc.c:1648 */ ++#line 801 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4213 "parser.tab.c" /* yacc.c:1648 */ ++#line 4208 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 266: +-#line 804 "parser.y" /* yacc.c:1648 */ ++#line 802 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4219 "parser.tab.c" /* yacc.c:1648 */ ++#line 4214 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 268: +-#line 806 "parser.y" /* yacc.c:1648 */ ++#line 804 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(type_basic_get_type((yyvsp[0].type)), -1); } +-#line 4225 "parser.tab.c" /* yacc.c:1648 */ ++#line 4220 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 269: +-#line 807 "parser.y" /* yacc.c:1648 */ ++#line 805 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(type_basic_get_type((yyvsp[0].type)), 1); } +-#line 4231 "parser.tab.c" /* yacc.c:1648 */ ++#line 4226 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 270: +-#line 808 "parser.y" /* yacc.c:1648 */ ++#line 806 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_INT, 1); } +-#line 4237 "parser.tab.c" /* yacc.c:1648 */ ++#line 4232 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 271: +-#line 809 "parser.y" /* yacc.c:1648 */ ++#line 807 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4243 "parser.tab.c" /* yacc.c:1648 */ ++#line 4238 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 272: +-#line 810 "parser.y" /* yacc.c:1648 */ ++#line 808 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4249 "parser.tab.c" /* yacc.c:1648 */ ++#line 4244 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 273: +-#line 811 "parser.y" /* yacc.c:1648 */ ++#line 809 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4255 "parser.tab.c" /* yacc.c:1648 */ ++#line 4250 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 274: +-#line 812 "parser.y" /* yacc.c:1648 */ ++#line 810 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4261 "parser.tab.c" /* yacc.c:1648 */ ++#line 4256 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 275: +-#line 813 "parser.y" /* yacc.c:1648 */ ++#line 811 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4267 "parser.tab.c" /* yacc.c:1648 */ ++#line 4262 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 278: +-#line 820 "parser.y" /* yacc.c:1648 */ ++#line 818 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_INT, 0); } +-#line 4273 "parser.tab.c" /* yacc.c:1648 */ ++#line 4268 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 279: +-#line 821 "parser.y" /* yacc.c:1648 */ ++#line 819 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_INT16, 0); } +-#line 4279 "parser.tab.c" /* yacc.c:1648 */ ++#line 4274 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 280: +-#line 822 "parser.y" /* yacc.c:1648 */ ++#line 820 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_INT8, 0); } +-#line 4285 "parser.tab.c" /* yacc.c:1648 */ ++#line 4280 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 281: +-#line 823 "parser.y" /* yacc.c:1648 */ ++#line 821 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_LONG, 0); } +-#line 4291 "parser.tab.c" /* yacc.c:1648 */ ++#line 4286 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 282: +-#line 824 "parser.y" /* yacc.c:1648 */ ++#line 822 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_HYPER, 0); } +-#line 4297 "parser.tab.c" /* yacc.c:1648 */ ++#line 4292 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 283: +-#line 825 "parser.y" /* yacc.c:1648 */ ++#line 823 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_INT64, 0); } +-#line 4303 "parser.tab.c" /* yacc.c:1648 */ ++#line 4298 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 284: +-#line 826 "parser.y" /* yacc.c:1648 */ ++#line 824 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_CHAR, 0); } +-#line 4309 "parser.tab.c" /* yacc.c:1648 */ ++#line 4304 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 285: +-#line 827 "parser.y" /* yacc.c:1648 */ ++#line 825 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_INT32, 0); } +-#line 4315 "parser.tab.c" /* yacc.c:1648 */ ++#line 4310 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 286: +-#line 828 "parser.y" /* yacc.c:1648 */ ++#line 826 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_int(TYPE_BASIC_INT3264, 0); } +-#line 4321 "parser.tab.c" /* yacc.c:1648 */ ++#line 4316 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 287: +-#line 831 "parser.y" /* yacc.c:1648 */ ++#line 829 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_coclass((yyvsp[0].str)); } +-#line 4327 "parser.tab.c" /* yacc.c:1648 */ ++#line 4322 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 288: +-#line 832 "parser.y" /* yacc.c:1648 */ ++#line 830 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type((yyvsp[0].str), NULL, 0); + if (type_get_type_detect_alias((yyval.type)) != TYPE_COCLASS) + error_loc("%s was not declared a coclass at %s:%d\n", + (yyvsp[0].str), (yyval.type)->loc_info.input_name, + (yyval.type)->loc_info.line_number); + } +-#line 4338 "parser.tab.c" /* yacc.c:1648 */ ++#line 4333 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 289: +-#line 840 "parser.y" /* yacc.c:1648 */ ++#line 838 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); + check_def((yyval.type)); + (yyval.type)->attrs = check_coclass_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list)); + } +-#line 4347 "parser.tab.c" /* yacc.c:1648 */ ++#line 4342 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 290: +-#line 847 "parser.y" /* yacc.c:1648 */ ++#line 845 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_coclass_define((yyvsp[-4].type), (yyvsp[-2].ifref_list)); } +-#line 4353 "parser.tab.c" /* yacc.c:1648 */ ++#line 4348 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 291: +-#line 850 "parser.y" /* yacc.c:1648 */ ++#line 848 "parser.y" /* yacc.c:1646 */ + { (yyval.str) = (yyvsp[0].str); } +-#line 4359 "parser.tab.c" /* yacc.c:1648 */ ++#line 4354 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 292: +-#line 853 "parser.y" /* yacc.c:1648 */ ++#line 851 "parser.y" /* yacc.c:1646 */ + { (yyval.ifref_list) = NULL; } +-#line 4365 "parser.tab.c" /* yacc.c:1648 */ ++#line 4360 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 293: +-#line 854 "parser.y" /* yacc.c:1648 */ ++#line 852 "parser.y" /* yacc.c:1646 */ + { (yyval.ifref_list) = append_ifref( (yyvsp[-1].ifref_list), (yyvsp[0].ifref) ); } +-#line 4371 "parser.tab.c" /* yacc.c:1648 */ ++#line 4366 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 294: +-#line 858 "parser.y" /* yacc.c:1648 */ ++#line 856 "parser.y" /* yacc.c:1646 */ + { (yyval.ifref) = make_ifref((yyvsp[0].type)); (yyval.ifref)->attrs = (yyvsp[-1].attr_list); } +-#line 4377 "parser.tab.c" /* yacc.c:1648 */ ++#line 4372 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 295: +-#line 861 "parser.y" /* yacc.c:1648 */ ++#line 859 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); } +-#line 4383 "parser.tab.c" /* yacc.c:1648 */ ++#line 4378 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 296: +-#line 862 "parser.y" /* yacc.c:1648 */ ++#line 860 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); } +-#line 4389 "parser.tab.c" /* yacc.c:1648 */ ++#line 4384 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 297: +-#line 865 "parser.y" /* yacc.c:1648 */ ++#line 863 "parser.y" /* yacc.c:1646 */ + { attr_t *attrs; + (yyval.type) = (yyvsp[0].type); + check_def((yyval.type)); +@@ -4397,75 +4392,75 @@ yyreduce: + (yyval.type)->attrs = append_attr( check_dispiface_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list)), attrs ); + (yyval.type)->defined = TRUE; + } +-#line 4401 "parser.tab.c" /* yacc.c:1648 */ ++#line 4396 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 298: +-#line 874 "parser.y" /* yacc.c:1648 */ ++#line 872 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = NULL; } +-#line 4407 "parser.tab.c" /* yacc.c:1648 */ ++#line 4402 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 299: +-#line 875 "parser.y" /* yacc.c:1648 */ ++#line 873 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[-1].var) ); } +-#line 4413 "parser.tab.c" /* yacc.c:1648 */ ++#line 4408 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 300: +-#line 878 "parser.y" /* yacc.c:1648 */ ++#line 876 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = NULL; } +-#line 4419 "parser.tab.c" /* yacc.c:1648 */ ++#line 4414 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 301: +-#line 879 "parser.y" /* yacc.c:1648 */ ++#line 877 "parser.y" /* yacc.c:1646 */ + { (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[-1].var) ); } +-#line 4425 "parser.tab.c" /* yacc.c:1648 */ ++#line 4420 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 302: +-#line 885 "parser.y" /* yacc.c:1648 */ ++#line 883 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-4].type); + type_dispinterface_define((yyval.type), (yyvsp[-2].var_list), (yyvsp[-1].var_list)); + } +-#line 4433 "parser.tab.c" /* yacc.c:1648 */ ++#line 4428 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 303: +-#line 889 "parser.y" /* yacc.c:1648 */ ++#line 887 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-4].type); + type_dispinterface_define_from_iface((yyval.type), (yyvsp[-2].type)); + } +-#line 4441 "parser.tab.c" /* yacc.c:1648 */ ++#line 4436 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 304: +-#line 894 "parser.y" /* yacc.c:1648 */ ++#line 892 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = NULL; } +-#line 4447 "parser.tab.c" /* yacc.c:1648 */ ++#line 4442 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 305: +-#line 895 "parser.y" /* yacc.c:1648 */ ++#line 893 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error2((yyvsp[0].str), 0); } +-#line 4453 "parser.tab.c" /* yacc.c:1648 */ ++#line 4448 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 306: +-#line 898 "parser.y" /* yacc.c:1648 */ ++#line 896 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); } +-#line 4459 "parser.tab.c" /* yacc.c:1648 */ ++#line 4454 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 307: +-#line 899 "parser.y" /* yacc.c:1648 */ ++#line 897 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); } +-#line 4465 "parser.tab.c" /* yacc.c:1648 */ ++#line 4460 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 308: +-#line 902 "parser.y" /* yacc.c:1648 */ ++#line 900 "parser.y" /* yacc.c:1646 */ + { (yyval.ifinfo).interface = (yyvsp[0].type); + (yyval.ifinfo).old_pointer_default = pointer_default; + if (is_attr((yyvsp[-1].attr_list), ATTR_POINTERDEFAULT)) +@@ -4474,11 +4469,11 @@ yyreduce: + (yyvsp[0].type)->attrs = check_iface_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list)); + (yyvsp[0].type)->defined = TRUE; + } +-#line 4478 "parser.tab.c" /* yacc.c:1648 */ ++#line 4473 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 309: +-#line 913 "parser.y" /* yacc.c:1648 */ ++#line 911 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-5].ifinfo).interface; + if((yyval.type) == (yyvsp[-4].type)) + error_loc("Interface can't inherit from itself\n"); +@@ -4486,594 +4481,594 @@ yyreduce: + check_async_uuid((yyval.type)); + pointer_default = (yyvsp[-5].ifinfo).old_pointer_default; + } +-#line 4490 "parser.tab.c" /* yacc.c:1648 */ ++#line 4485 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 310: +-#line 924 "parser.y" /* yacc.c:1648 */ ++#line 922 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-7].ifinfo).interface; + type_interface_define((yyval.type), find_type_or_error2((yyvsp[-5].str), 0), (yyvsp[-2].stmt_list)); + pointer_default = (yyvsp[-7].ifinfo).old_pointer_default; + } +-#line 4499 "parser.tab.c" /* yacc.c:1648 */ ++#line 4494 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 311: +-#line 928 "parser.y" /* yacc.c:1648 */ ++#line 926 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-1].type); } +-#line 4505 "parser.tab.c" /* yacc.c:1648 */ ++#line 4500 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 312: +-#line 932 "parser.y" /* yacc.c:1648 */ ++#line 930 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-1].type); } +-#line 4511 "parser.tab.c" /* yacc.c:1648 */ ++#line 4506 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 313: +-#line 933 "parser.y" /* yacc.c:1648 */ ++#line 931 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-1].type); } +-#line 4517 "parser.tab.c" /* yacc.c:1648 */ ++#line 4512 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 314: +-#line 936 "parser.y" /* yacc.c:1648 */ ++#line 934 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_module((yyvsp[0].str)); } +-#line 4523 "parser.tab.c" /* yacc.c:1648 */ ++#line 4518 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 315: +-#line 937 "parser.y" /* yacc.c:1648 */ ++#line 935 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_module((yyvsp[0].str)); } +-#line 4529 "parser.tab.c" /* yacc.c:1648 */ ++#line 4524 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 316: +-#line 940 "parser.y" /* yacc.c:1648 */ ++#line 938 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); + (yyval.type)->attrs = check_module_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list)); + } +-#line 4537 "parser.tab.c" /* yacc.c:1648 */ ++#line 4532 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 317: +-#line 946 "parser.y" /* yacc.c:1648 */ ++#line 944 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[-4].type); + type_module_define((yyval.type), (yyvsp[-2].stmt_list)); + } +-#line 4545 "parser.tab.c" /* yacc.c:1648 */ ++#line 4540 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 318: +-#line 952 "parser.y" /* yacc.c:1648 */ ++#line 950 "parser.y" /* yacc.c:1646 */ + { (yyval.stgclass) = STG_EXTERN; } +-#line 4551 "parser.tab.c" /* yacc.c:1648 */ ++#line 4546 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 319: +-#line 953 "parser.y" /* yacc.c:1648 */ ++#line 951 "parser.y" /* yacc.c:1646 */ + { (yyval.stgclass) = STG_STATIC; } +-#line 4557 "parser.tab.c" /* yacc.c:1648 */ ++#line 4552 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 320: +-#line 954 "parser.y" /* yacc.c:1648 */ ++#line 952 "parser.y" /* yacc.c:1646 */ + { (yyval.stgclass) = STG_REGISTER; } +-#line 4563 "parser.tab.c" /* yacc.c:1648 */ ++#line 4558 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 321: +-#line 958 "parser.y" /* yacc.c:1648 */ +- { (yyval.attr) = make_attr(ATTR_INLINE); } +-#line 4569 "parser.tab.c" /* yacc.c:1648 */ ++#line 956 "parser.y" /* yacc.c:1646 */ ++ { (yyval.funcspecifier) = FUNCTION_SPECIFIER_INLINE; } ++#line 4564 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 322: +-#line 962 "parser.y" /* yacc.c:1648 */ +- { (yyval.attr) = make_attr(ATTR_CONST); } +-#line 4575 "parser.tab.c" /* yacc.c:1648 */ ++#line 960 "parser.y" /* yacc.c:1646 */ ++ { (yyval.typequalifier) = TYPE_QUALIFIER_CONST; } ++#line 4570 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 323: +-#line 965 "parser.y" /* yacc.c:1648 */ +- { (yyval.attr_list) = NULL; } +-#line 4581 "parser.tab.c" /* yacc.c:1648 */ ++#line 963 "parser.y" /* yacc.c:1646 */ ++ { (yyval.typequalifier) = TYPE_QUALIFIER_NONE; } ++#line 4576 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 324: +-#line 966 "parser.y" /* yacc.c:1648 */ +- { (yyval.attr_list) = append_attr((yyvsp[-1].attr_list), (yyvsp[0].attr)); } +-#line 4587 "parser.tab.c" /* yacc.c:1648 */ ++#line 964 "parser.y" /* yacc.c:1646 */ ++ { (yyval.typequalifier) = (yyvsp[-1].typequalifier) | (yyvsp[0].typequalifier); } ++#line 4582 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 325: +-#line 969 "parser.y" /* yacc.c:1648 */ +- { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[0].declspec), NULL, NULL, STG_NONE); } +-#line 4593 "parser.tab.c" /* yacc.c:1648 */ ++#line 967 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[0].declspec), NULL, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); } ++#line 4588 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 326: +-#line 971 "parser.y" /* yacc.c:1648 */ +- { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[-2].declspec), (yyvsp[0].declspec), NULL, STG_NONE); } +-#line 4599 "parser.tab.c" /* yacc.c:1648 */ ++#line 969 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[-2].declspec), (yyvsp[0].declspec), STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); } ++#line 4594 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 327: +-#line 974 "parser.y" /* yacc.c:1648 */ ++#line 972 "parser.y" /* yacc.c:1646 */ + { (yyval.declspec) = NULL; } +-#line 4605 "parser.tab.c" /* yacc.c:1648 */ ++#line 4600 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 329: +-#line 979 "parser.y" /* yacc.c:1648 */ +- { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, (yyvsp[-1].attr), STG_NONE); } +-#line 4611 "parser.tab.c" /* yacc.c:1648 */ ++#line 977 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, STG_NONE, (yyvsp[-1].typequalifier), FUNCTION_SPECIFIER_NONE); } ++#line 4606 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 330: +-#line 980 "parser.y" /* yacc.c:1648 */ +- { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, (yyvsp[-1].attr), STG_NONE); } +-#line 4617 "parser.tab.c" /* yacc.c:1648 */ ++#line 978 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, STG_NONE, TYPE_QUALIFIER_NONE, (yyvsp[-1].funcspecifier)); } ++#line 4612 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 331: +-#line 981 "parser.y" /* yacc.c:1648 */ +- { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, NULL, (yyvsp[-1].stgclass)); } +-#line 4623 "parser.tab.c" /* yacc.c:1648 */ ++#line 979 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, (yyvsp[-1].stgclass), TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); } ++#line 4618 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 332: +-#line 986 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); } +-#line 4629 "parser.tab.c" /* yacc.c:1648 */ ++#line 984 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); } ++#line 4624 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 333: +-#line 987 "parser.y" /* yacc.c:1648 */ ++#line 985 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[0].declarator); if ((yyval.declarator)->func_type) (yyval.declarator)->func_type->attrs = append_attr((yyval.declarator)->func_type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); +- else if ((yyval.declarator)->type) (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } +-#line 4636 "parser.tab.c" /* yacc.c:1648 */ ++ else if ((yyval.declarator)->declspec.type) (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } ++#line 4631 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 335: +-#line 993 "parser.y" /* yacc.c:1648 */ ++#line 991 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = make_declarator((yyvsp[0].var)); } +-#line 4642 "parser.tab.c" /* yacc.c:1648 */ ++#line 4637 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 336: +-#line 994 "parser.y" /* yacc.c:1648 */ ++#line 992 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[-1].declarator); } +-#line 4648 "parser.tab.c" /* yacc.c:1648 */ ++#line 4643 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 337: +-#line 995 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); } +-#line 4654 "parser.tab.c" /* yacc.c:1648 */ ++#line 993 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); } ++#line 4649 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 338: +-#line 996 "parser.y" /* yacc.c:1648 */ ++#line 994 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[-3].declarator); +- (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list))); +- (yyval.declarator)->type = NULL; ++ (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list))); ++ (yyval.declarator)->declspec.type = NULL; + } +-#line 4663 "parser.tab.c" /* yacc.c:1648 */ ++#line 4658 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 339: +-#line 1005 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); } +-#line 4669 "parser.tab.c" /* yacc.c:1648 */ ++#line 1003 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); } ++#line 4664 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 340: +-#line 1006 "parser.y" /* yacc.c:1648 */ ++#line 1004 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[0].declarator); if ((yyval.declarator)->func_type) (yyval.declarator)->func_type->attrs = append_attr((yyval.declarator)->func_type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); +- else if ((yyval.declarator)->type) (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } +-#line 4676 "parser.tab.c" /* yacc.c:1648 */ ++ else if ((yyval.declarator)->declspec.type) (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } ++#line 4671 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 342: +-#line 1014 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); } +-#line 4682 "parser.tab.c" /* yacc.c:1648 */ ++#line 1012 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); } ++#line 4677 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 343: +-#line 1015 "parser.y" /* yacc.c:1648 */ ++#line 1013 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[0].declarator); if ((yyval.declarator)->func_type) (yyval.declarator)->func_type->attrs = append_attr((yyval.declarator)->func_type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); +- else if ((yyval.declarator)->type) (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } +-#line 4689 "parser.tab.c" /* yacc.c:1648 */ ++ else if ((yyval.declarator)->declspec.type) (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } ++#line 4684 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 344: +-#line 1020 "parser.y" /* yacc.c:1648 */ ++#line 1018 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = make_declarator(NULL); } +-#line 4695 "parser.tab.c" /* yacc.c:1648 */ ++#line 4690 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 346: +-#line 1026 "parser.y" /* yacc.c:1648 */ ++#line 1024 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[-1].declarator); } +-#line 4701 "parser.tab.c" /* yacc.c:1648 */ ++#line 4696 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 347: +-#line 1027 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); } +-#line 4707 "parser.tab.c" /* yacc.c:1648 */ ++#line 1025 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); } ++#line 4702 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 348: +-#line 1028 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); } +-#line 4713 "parser.tab.c" /* yacc.c:1648 */ ++#line 1026 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); } ++#line 4708 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 349: +-#line 1030 "parser.y" /* yacc.c:1648 */ ++#line 1028 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = make_declarator(NULL); +- (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list))); +- (yyval.declarator)->type = NULL; ++ (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list))); ++ (yyval.declarator)->declspec.type = NULL; + } +-#line 4722 "parser.tab.c" /* yacc.c:1648 */ ++#line 4717 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 350: +-#line 1035 "parser.y" /* yacc.c:1648 */ ++#line 1033 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[-3].declarator); +- (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list))); +- (yyval.declarator)->type = NULL; ++ (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list))); ++ (yyval.declarator)->declspec.type = NULL; + } +-#line 4731 "parser.tab.c" /* yacc.c:1648 */ ++#line 4726 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 351: +-#line 1044 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); } +-#line 4737 "parser.tab.c" /* yacc.c:1648 */ ++#line 1042 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); } ++#line 4732 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 352: +-#line 1045 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } +-#line 4743 "parser.tab.c" /* yacc.c:1648 */ ++#line 1043 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } ++#line 4738 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 354: +-#line 1052 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); } +-#line 4749 "parser.tab.c" /* yacc.c:1648 */ ++#line 1050 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); } ++#line 4744 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 355: +-#line 1053 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } +-#line 4755 "parser.tab.c" /* yacc.c:1648 */ ++#line 1051 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); } ++#line 4750 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 356: +-#line 1057 "parser.y" /* yacc.c:1648 */ ++#line 1055 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = make_declarator(NULL); } +-#line 4761 "parser.tab.c" /* yacc.c:1648 */ ++#line 4756 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 358: +-#line 1065 "parser.y" /* yacc.c:1648 */ ++#line 1063 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = make_declarator((yyvsp[0].var)); } +-#line 4767 "parser.tab.c" /* yacc.c:1648 */ ++#line 4762 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 359: +-#line 1066 "parser.y" /* yacc.c:1648 */ ++#line 1064 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[-1].declarator); } +-#line 4773 "parser.tab.c" /* yacc.c:1648 */ ++#line 4768 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 360: +-#line 1067 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); } +-#line 4779 "parser.tab.c" /* yacc.c:1648 */ ++#line 1065 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); } ++#line 4774 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 361: +-#line 1068 "parser.y" /* yacc.c:1648 */ +- { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); } +-#line 4785 "parser.tab.c" /* yacc.c:1648 */ ++#line 1066 "parser.y" /* yacc.c:1646 */ ++ { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); } ++#line 4780 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 362: +-#line 1070 "parser.y" /* yacc.c:1648 */ ++#line 1068 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = make_declarator(NULL); +- (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list))); +- (yyval.declarator)->type = NULL; ++ (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list))); ++ (yyval.declarator)->declspec.type = NULL; + } +-#line 4794 "parser.tab.c" /* yacc.c:1648 */ ++#line 4789 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 363: +-#line 1075 "parser.y" /* yacc.c:1648 */ ++#line 1073 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[-3].declarator); +- (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list))); +- (yyval.declarator)->type = NULL; ++ (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list))); ++ (yyval.declarator)->declspec.type = NULL; + } +-#line 4803 "parser.tab.c" /* yacc.c:1648 */ ++#line 4798 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 364: +-#line 1082 "parser.y" /* yacc.c:1648 */ ++#line 1080 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator_list) = append_declarator( NULL, (yyvsp[0].declarator) ); } +-#line 4809 "parser.tab.c" /* yacc.c:1648 */ ++#line 4804 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 365: +-#line 1083 "parser.y" /* yacc.c:1648 */ ++#line 1081 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator_list) = append_declarator( (yyvsp[-2].declarator_list), (yyvsp[0].declarator) ); } +-#line 4815 "parser.tab.c" /* yacc.c:1648 */ ++#line 4810 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 366: +-#line 1086 "parser.y" /* yacc.c:1648 */ ++#line 1084 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = NULL; } +-#line 4821 "parser.tab.c" /* yacc.c:1648 */ ++#line 4816 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 367: +-#line 1087 "parser.y" /* yacc.c:1648 */ ++#line 1085 "parser.y" /* yacc.c:1646 */ + { (yyval.expr) = (yyvsp[0].expr); } +-#line 4827 "parser.tab.c" /* yacc.c:1648 */ ++#line 4822 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 368: +-#line 1090 "parser.y" /* yacc.c:1648 */ ++#line 1088 "parser.y" /* yacc.c:1646 */ + { (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 4836 "parser.tab.c" /* yacc.c:1648 */ ++#line 4831 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 369: +-#line 1097 "parser.y" /* yacc.c:1648 */ ++#line 1095 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator_list) = append_declarator( NULL, (yyvsp[0].declarator) ); } +-#line 4842 "parser.tab.c" /* yacc.c:1648 */ ++#line 4837 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 370: +-#line 1099 "parser.y" /* yacc.c:1648 */ ++#line 1097 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator_list) = append_declarator( (yyvsp[-2].declarator_list), (yyvsp[0].declarator) ); } +-#line 4848 "parser.tab.c" /* yacc.c:1648 */ ++#line 4843 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 371: +-#line 1103 "parser.y" /* yacc.c:1648 */ ++#line 1101 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[0].declarator); } +-#line 4854 "parser.tab.c" /* yacc.c:1648 */ ++#line 4849 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 372: +-#line 1104 "parser.y" /* yacc.c:1648 */ ++#line 1102 "parser.y" /* yacc.c:1646 */ + { (yyval.declarator) = (yyvsp[-2].declarator); (yyvsp[-2].declarator)->var->eval = (yyvsp[0].expr); } +-#line 4860 "parser.tab.c" /* yacc.c:1648 */ ++#line 4855 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 373: +-#line 1108 "parser.y" /* yacc.c:1648 */ ++#line 1106 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = THREADING_APARTMENT; } +-#line 4866 "parser.tab.c" /* yacc.c:1648 */ ++#line 4861 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 374: +-#line 1109 "parser.y" /* yacc.c:1648 */ ++#line 1107 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = THREADING_NEUTRAL; } +-#line 4872 "parser.tab.c" /* yacc.c:1648 */ ++#line 4867 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 375: +-#line 1110 "parser.y" /* yacc.c:1648 */ ++#line 1108 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = THREADING_SINGLE; } +-#line 4878 "parser.tab.c" /* yacc.c:1648 */ ++#line 4873 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 376: +-#line 1111 "parser.y" /* yacc.c:1648 */ ++#line 1109 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = THREADING_FREE; } +-#line 4884 "parser.tab.c" /* yacc.c:1648 */ ++#line 4879 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 377: +-#line 1112 "parser.y" /* yacc.c:1648 */ ++#line 1110 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = THREADING_BOTH; } +-#line 4890 "parser.tab.c" /* yacc.c:1648 */ ++#line 4885 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 378: +-#line 1116 "parser.y" /* yacc.c:1648 */ ++#line 1114 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = FC_RP; } +-#line 4896 "parser.tab.c" /* yacc.c:1648 */ ++#line 4891 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 379: +-#line 1117 "parser.y" /* yacc.c:1648 */ ++#line 1115 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = FC_UP; } +-#line 4902 "parser.tab.c" /* yacc.c:1648 */ ++#line 4897 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 380: +-#line 1118 "parser.y" /* yacc.c:1648 */ ++#line 1116 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = FC_FP; } +-#line 4908 "parser.tab.c" /* yacc.c:1648 */ ++#line 4903 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 381: +-#line 1121 "parser.y" /* yacc.c:1648 */ ++#line 1119 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_struct((yyvsp[-3].str), current_namespace, TRUE, (yyvsp[-1].var_list)); } +-#line 4914 "parser.tab.c" /* yacc.c:1648 */ ++#line 4909 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 382: +-#line 1124 "parser.y" /* yacc.c:1648 */ ++#line 1122 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_void(); } +-#line 4920 "parser.tab.c" /* yacc.c:1648 */ ++#line 4915 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 383: +-#line 1125 "parser.y" /* yacc.c:1648 */ ++#line 1123 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); } +-#line 4926 "parser.tab.c" /* yacc.c:1648 */ ++#line 4921 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 384: +-#line 1126 "parser.y" /* yacc.c:1648 */ ++#line 1124 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); } +-#line 4932 "parser.tab.c" /* yacc.c:1648 */ ++#line 4927 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 385: +-#line 1127 "parser.y" /* yacc.c:1648 */ ++#line 1125 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); } +-#line 4938 "parser.tab.c" /* yacc.c:1648 */ ++#line 4933 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 386: +-#line 1128 "parser.y" /* yacc.c:1648 */ ++#line 1126 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_enum((yyvsp[0].str), current_namespace, FALSE, NULL); } +-#line 4944 "parser.tab.c" /* yacc.c:1648 */ ++#line 4939 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 387: +-#line 1129 "parser.y" /* yacc.c:1648 */ ++#line 1127 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); } +-#line 4950 "parser.tab.c" /* yacc.c:1648 */ ++#line 4945 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 388: +-#line 1130 "parser.y" /* yacc.c:1648 */ ++#line 1128 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_struct((yyvsp[0].str), current_namespace, FALSE, NULL); } +-#line 4956 "parser.tab.c" /* yacc.c:1648 */ ++#line 4951 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 389: +-#line 1131 "parser.y" /* yacc.c:1648 */ ++#line 1129 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = (yyvsp[0].type); } +-#line 4962 "parser.tab.c" /* yacc.c:1648 */ ++#line 4957 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 390: +-#line 1132 "parser.y" /* yacc.c:1648 */ ++#line 1130 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_nonencapsulated_union((yyvsp[0].str), FALSE, NULL); } +-#line 4968 "parser.tab.c" /* yacc.c:1648 */ ++#line 4963 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 391: +-#line 1133 "parser.y" /* yacc.c:1648 */ ++#line 1131 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = make_safearray((yyvsp[-1].type)); } +-#line 4974 "parser.tab.c" /* yacc.c:1648 */ ++#line 4969 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 392: +-#line 1137 "parser.y" /* yacc.c:1648 */ ++#line 1135 "parser.y" /* yacc.c:1646 */ + { (yyvsp[-4].attr_list) = append_attribs((yyvsp[-4].attr_list), (yyvsp[-2].attr_list)); + reg_typedefs((yyvsp[-1].declspec), (yyvsp[0].declarator_list), check_typedef_attrs((yyvsp[-4].attr_list))); + (yyval.statement) = make_statement_typedef((yyvsp[0].declarator_list)); + } +-#line 4983 "parser.tab.c" /* yacc.c:1648 */ ++#line 4978 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 393: +-#line 1144 "parser.y" /* yacc.c:1648 */ ++#line 1142 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_nonencapsulated_union((yyvsp[-3].str), TRUE, (yyvsp[-1].var_list)); } +-#line 4989 "parser.tab.c" /* yacc.c:1648 */ ++#line 4984 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 394: +-#line 1147 "parser.y" /* yacc.c:1648 */ ++#line 1145 "parser.y" /* yacc.c:1646 */ + { (yyval.type) = type_new_encapsulated_union((yyvsp[-8].str), (yyvsp[-5].var), (yyvsp[-3].var), (yyvsp[-1].var_list)); } +-#line 4995 "parser.tab.c" /* yacc.c:1648 */ ++#line 4990 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 395: +-#line 1151 "parser.y" /* yacc.c:1648 */ ++#line 1149 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = MAKEVERSION((yyvsp[0].num), 0); } +-#line 5001 "parser.tab.c" /* yacc.c:1648 */ ++#line 4996 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 396: +-#line 1152 "parser.y" /* yacc.c:1648 */ ++#line 1150 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = MAKEVERSION((yyvsp[-2].num), (yyvsp[0].num)); } +-#line 5007 "parser.tab.c" /* yacc.c:1648 */ ++#line 5002 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 397: +-#line 1153 "parser.y" /* yacc.c:1648 */ ++#line 1151 "parser.y" /* yacc.c:1646 */ + { (yyval.num) = (yyvsp[0].num); } +-#line 5013 "parser.tab.c" /* yacc.c:1648 */ ++#line 5008 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 402: +-#line 1166 "parser.y" /* yacc.c:1648 */ ++#line 1164 "parser.y" /* yacc.c:1646 */ + { type_t *type = find_type_or_error((yyvsp[-1].str), 0); + type->attrs = append_attr_list(type->attrs, (yyvsp[-2].attr_list)); + } +-#line 5021 "parser.tab.c" /* yacc.c:1648 */ ++#line 5016 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 403: +-#line 1171 "parser.y" /* yacc.c:1648 */ ++#line 1169 "parser.y" /* yacc.c:1646 */ + { type_t *iface = find_type_or_error2((yyvsp[-3].str), 0); + 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 5031 "parser.tab.c" /* yacc.c:1648 */ ++#line 5026 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 404: +-#line 1178 "parser.y" /* yacc.c:1648 */ ++#line 1176 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = NULL; } +-#line 5037 "parser.tab.c" /* yacc.c:1648 */ ++#line 5032 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 405: +-#line 1179 "parser.y" /* yacc.c:1648 */ ++#line 1177 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = (yyvsp[-1].attr_list); } +-#line 5043 "parser.tab.c" /* yacc.c:1648 */ ++#line 5038 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 406: +-#line 1182 "parser.y" /* yacc.c:1648 */ ++#line 1180 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = append_attr(NULL, (yyvsp[0].attr)); } +-#line 5049 "parser.tab.c" /* yacc.c:1648 */ ++#line 5044 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 407: +-#line 1183 "parser.y" /* yacc.c:1648 */ ++#line 1181 "parser.y" /* yacc.c:1646 */ + { (yyval.attr_list) = append_attr((yyvsp[-2].attr_list), (yyvsp[0].attr)); } +-#line 5055 "parser.tab.c" /* yacc.c:1648 */ ++#line 5050 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 408: +-#line 1186 "parser.y" /* yacc.c:1648 */ ++#line 1184 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_ENCODE); } +-#line 5061 "parser.tab.c" /* yacc.c:1648 */ ++#line 5056 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 409: +-#line 1187 "parser.y" /* yacc.c:1648 */ ++#line 1185 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_DECODE); } +-#line 5067 "parser.tab.c" /* yacc.c:1648 */ ++#line 5062 "parser.tab.c" /* yacc.c:1646 */ + break; + + case 410: +-#line 1188 "parser.y" /* yacc.c:1648 */ ++#line 1186 "parser.y" /* yacc.c:1646 */ + { (yyval.attr) = make_attr(ATTR_EXPLICIT_HANDLE); } +-#line 5073 "parser.tab.c" /* yacc.c:1648 */ ++#line 5068 "parser.tab.c" /* yacc.c:1646 */ + break; + + +-#line 5077 "parser.tab.c" /* yacc.c:1648 */ ++#line 5072 "parser.tab.c" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires +@@ -5301,7 +5296,7 @@ yyreturn: + #endif + return yyresult; + } +-#line 1190 "parser.y" /* yacc.c:1907 */ ++#line 1188 "parser.y" /* yacc.c:1906 */ + + + static void decl_builtin_basic(const char *name, enum type_basic_type type) +@@ -5312,7 +5307,8 @@ static void decl_builtin_basic(const char *name, enum type_basic_type type) + + static void decl_builtin_alias(const char *name, type_t *t) + { +- reg_type(type_new_alias(t, name), name, NULL, 0); ++ decl_spec_t ds; ++ reg_type(type_new_alias(init_declspec(&ds, t), name), name, &global_namespace, 0); + } + + void init_types(void) +@@ -5323,7 +5319,7 @@ void init_types(void) + decl_builtin_basic("double", TYPE_BASIC_DOUBLE); + decl_builtin_basic("error_status_t", TYPE_BASIC_ERROR_STATUS_T); + decl_builtin_basic("handle_t", TYPE_BASIC_HANDLE); +- decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_BYTE)); ++ decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_CHAR)); + } + + static str_list_t *append_str(str_list_t *list, char *str) +@@ -5354,6 +5350,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) + LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry) + if (attr_existing->type == attr->type) + { ++ __builtin_trap(); + parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type)); + /* use the last attribute, like MIDL does */ + list_remove(&attr_existing->entry); +@@ -5413,53 +5410,73 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter + return new_list; + } + +-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass) ++static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier) + { + decl_spec_t *declspec = left ? left : right; + if (!declspec) + { + declspec = xmalloc(sizeof(*declspec)); + declspec->type = NULL; +- declspec->attrs = NULL; + declspec->stgclass = STG_NONE; ++ declspec->typequalifier = TYPE_QUALIFIER_NONE; ++ declspec->funcspecifier = FUNCTION_SPECIFIER_NONE; + } + declspec->type = type; + if (left && declspec != left) + { +- declspec->attrs = append_attr_list(declspec->attrs, left->attrs); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = left->stgclass; + else if (left->stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); ++ ++ if (declspec->typequalifier == TYPE_QUALIFIER_NONE) ++ declspec->typequalifier = left->typequalifier; ++ else if (left->typequalifier != TYPE_QUALIFIER_NONE) ++ error_loc("only one type qualifier can be specified\n"); ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE) ++ declspec->funcspecifier = left->funcspecifier; ++ else if (left->funcspecifier != FUNCTION_SPECIFIER_NONE) ++ error_loc("only one function specifier can be specified\n"); ++ + assert(!left->type); + free(left); + } + if (right && declspec != right) + { +- declspec->attrs = append_attr_list(declspec->attrs, right->attrs); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = right->stgclass; + else if (right->stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); ++ ++ if (declspec->typequalifier == TYPE_QUALIFIER_NONE) ++ declspec->typequalifier = right->typequalifier; ++ else if (right->typequalifier != TYPE_QUALIFIER_NONE) ++ error_loc("only one type qualifier can be specified\n"); ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE) ++ declspec->funcspecifier = right->funcspecifier; ++ else if (right->funcspecifier != FUNCTION_SPECIFIER_NONE) ++ error_loc("only one function specifier can be specified\n"); ++ + assert(!right->type); + free(right); + } + +- declspec->attrs = append_attr(declspec->attrs, attr); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = stgclass; + else if (stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); + +- /* apply attributes to type */ +- if (type && declspec->attrs) +- { +- attr_list_t *attrs; +- declspec->type = duptype(type, 1); +- attrs = map_attrs(type->attrs, NULL); +- declspec->type->attrs = append_attr_list(attrs, declspec->attrs); +- declspec->attrs = NULL; +- } ++ if (declspec->typequalifier == TYPE_QUALIFIER_NONE) ++ declspec->typequalifier = typequalifier; ++ else if (typequalifier != TYPE_QUALIFIER_NONE) ++ error_loc("only one type qualifier can be specified\n"); ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE) ++ declspec->funcspecifier = funcspecifier; ++ else if (funcspecifier != FUNCTION_SPECIFIER_NONE) ++ error_loc("only one function specifier can be specified\n"); + + return declspec; + } +@@ -5545,6 +5562,7 @@ void clear_all_offsets(void) + + static void type_function_add_head_arg(type_t *type, var_t *arg) + { ++ assert(type_get_type_detect_alias(type) == TYPE_FUNCTION); + if (!type->details.function->args) + { + type->details.function->args = xmalloc( sizeof(*type->details.function->args) ); +@@ -5589,31 +5607,60 @@ static int is_allowed_range_type(const type_t *type) + static type_t *get_array_or_ptr_ref(type_t *type) + { + if (is_ptr(type)) +- return type_pointer_get_ref(type); ++ return type_pointer_get_ref_type(type); + else if (is_array(type)) +- return type_array_get_element(type); ++ return type_array_get_element_type(type); + return NULL; + } + + static type_t *append_chain_type(type_t *chain, type_t *type) + { +- type_t *chain_type; ++ type_t *chain_type = NULL; + + if (!chain) + return type; + for (chain_type = chain; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type)) + ; + ++ assert(!type_is_alias(chain_type)); + if (is_ptr(chain_type)) +- chain_type->details.pointer.ref = type; ++ chain_type->details.pointer.ref.type = type; + else if (is_array(chain_type)) +- chain_type->details.array.elem = type; ++ chain_type->details.array.elem.type = type; + else + assert(0); + + return chain; + } + ++static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier) ++{ ++ type_t *chain_type = chain->type; ++ decl_spec_t *chain_declspec = NULL; ++ ++ if (!chain_type) ++ { ++ chain->type = type; ++ chain->typequalifier = typequalifier; ++ return chain; ++ } ++ ++ for(; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type)) ++ ; ++ ++ if (is_ptr(chain_type)) ++ chain_declspec = &chain_type->details.pointer.ref; ++ else if (is_array(chain_type)) ++ chain_declspec = &chain_type->details.array.elem; ++ else ++ assert(NULL); ++ ++ chain_declspec->type = type; ++ chain_declspec->typequalifier = typequalifier; ++ ++ return chain; ++} ++ + static warning_list_t *append_warning(warning_list_t *list, int num) + { + warning_t *entry; +@@ -5629,7 +5676,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num) + return list; + } + +-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl, ++static var_t *declare_var(attr_list_t *attrs, decl_spec_t *declspec, const declarator_t *decl, + int top) + { + var_t *v = decl->var; +@@ -5638,58 +5685,80 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + expr_t *dim; + type_t **ptype; + type_t *func_type = decl ? decl->func_type : NULL; +- type_t *type = decl_spec->type; ++ type_t *type = declspec->type; + +- if (is_attr(type->attrs, ATTR_INLINE)) +- { ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_INLINE) { + if (!func_type) + error_loc("inline attribute applied to non-function type\n"); + else + { +- type_t *t; +- /* move inline attribute from return type node to function node */ +- for (t = func_type; is_ptr(t); t = type_pointer_get_ref(t)) +- ; +- t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE); ++ v->declspec.funcspecifier = declspec->funcspecifier; + } + } + +- /* add type onto the end of the pointers in pident->type */ +- v->type = append_chain_type(decl ? decl->type : NULL, type); +- v->stgclass = decl_spec->stgclass; ++ /* if the var type is a pointerish, we need to move the type qualifier to the pointee's declspec ++ * unless the pointee already has const type qualifier*/ ++ if (!decl) ++ { ++ /* simplest case, no pointers to deal with here */ ++ v->declspec.typequalifier = declspec->typequalifier; ++ } else if (decl->bits) ++ { ++ /* dealing with a bitfield, generate bitfield and copy over typequalifier*/ ++ v->declspec.type = type_new_bitfield(declspec->type, decl->bits); ++ v->declspec.typequalifier = declspec->typequalifier; ++ } ++ else ++ { ++ /* here we're dealing with a pointerish type chain, so we need to pull ++ * the typequalifier off of the declspec and stick them in the type's attr list ++ */ ++ v->declspec.type = decl->declspec.type; ++ v->declspec.typequalifier = decl->declspec.typequalifier; ++ append_chain_declspec(&v->declspec, type, declspec->typequalifier); ++ } ++ ++ v->declspec.stgclass = declspec->stgclass; + v->attrs = attrs; + + /* check for pointer attribute being applied to non-pointer, non-array + * type */ +- if (!is_array(v->type)) ++ if (!is_array(v->declspec.type)) + { + int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); + const type_t *ptr = NULL; + /* pointer attributes on the left side of the type belong to the function + * pointer, if one is being declared */ +- type_t **pt = func_type ? &func_type : &v->type; ++ type_t **pt = func_type ? &func_type : &v->declspec.type; + for (ptr = *pt; ptr && !ptr_attr; ) + { + ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE); + if (!ptr_attr && type_is_alias(ptr)) +- ptr = type_alias_get_aliasee(ptr); ++ ptr = type_alias_get_aliasee_type(ptr); + else + break; + } + if (is_ptr(ptr)) + { + if (ptr_attr && ptr_attr != FC_UP && +- type_get_type(type_pointer_get_ref(ptr)) == TYPE_INTERFACE) ++ type_get_type(type_pointer_get_ref_type(ptr)) == TYPE_INTERFACE) + warning_loc_info(&v->loc_info, + "%s: pointer attribute applied to interface " + "pointer type has no effect\n", v->name); +- if (!ptr_attr && top && (*pt)->details.pointer.def_fc != FC_RP) ++ if (!ptr_attr && top && type_pointer_get_default_fc(*pt) != FC_RP) + { ++ printf("dup_pointer_type!\n"); ++ printf("type : %p name : %s\n", *pt, (*pt)->name); ++ /* ptr_attr is ref,unique or full (FC_RP, FC_UP, FC_FP) */ ++ /* *pt could be the var's declspec's type OR a type on a typedef */ ++ /* not an array */ ++ + /* FIXME: this is a horrible hack to cope with the issue that we + * store an offset to the typeformat string in the type object, but + * two typeformat strings may be written depending on whether the + * pointer is a toplevel parameter or not */ +- *pt = duptype(*pt, 1); ++ *pt = dup_pointer_type(*pt); + } + } + else if (ptr_attr) +@@ -5700,16 +5769,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + { + type_t *t = type; + +- if (!is_ptr(v->type) && !is_array(v->type)) ++ if (!is_ptr(v->declspec.type) && !is_array(v->declspec.type)) + error_loc("'%s': [string] attribute applied to non-pointer, non-array type\n", + v->name); + + for (;;) + { + if (is_ptr(t)) +- t = type_pointer_get_ref(t); ++ t = type_pointer_get_ref_type(t); + else if (is_array(t)) +- t = type_array_get_element(t); ++ t = type_array_get_element_type(t); + else + break; + } +@@ -5726,15 +5795,15 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + + if (is_attr(v->attrs, ATTR_V1ENUM)) + { +- if (type_get_type_detect_alias(v->type) != TYPE_ENUM) ++ if (type_get_type_detect_alias(v->declspec.type) != TYPE_ENUM) + error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name); + } + +- if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->type)) ++ if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->declspec.type)) + error_loc("'%s': [range] attribute applied to non-integer type\n", + v->name); + +- ptype = &v->type; ++ ptype = &v->declspec.type; + if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry) + { + if (dim->type != EXPR_VOID) +@@ -5747,7 +5816,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + else + *ptype = type_new_array((*ptype)->name, + type_array_get_element(*ptype), FALSE, +- 0, dim, NULL, 0); ++ 0, dim, NULL, FC_RP); + } + else if (is_ptr(*ptype)) + *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE, +@@ -5756,15 +5825,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + error_loc("%s: size_is attribute applied to illegal type\n", v->name); + } + ++ assert(!type_is_alias(*ptype)); + if (is_ptr(*ptype)) +- ptype = &(*ptype)->details.pointer.ref; ++ ptype = &(*ptype)->details.pointer.ref.type; + else if (is_array(*ptype)) +- ptype = &(*ptype)->details.array.elem; ++ ptype = &(*ptype)->details.array.elem.type; + else + error_loc("%s: too many expressions in size_is attribute\n", v->name); + } + +- ptype = &v->type; ++ ptype = &v->declspec.type; + if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry) + { + if (dim->type != EXPR_VOID) +@@ -5782,10 +5852,11 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + error_loc("%s: length_is attribute applied to illegal type\n", v->name); + } + ++ assert(!type_is_alias(*ptype)); + if (is_ptr(*ptype)) +- ptype = &(*ptype)->details.pointer.ref; ++ ptype = &(*ptype)->details.pointer.ref.type; + else if (is_array(*ptype)) +- ptype = &(*ptype)->details.array.elem; ++ ptype = &(*ptype)->details.array.elem.type; + else + error_loc("%s: too many expressions in length_is attribute\n", v->name); + } +@@ -5796,29 +5867,31 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + if (func_type) + { + type_t *ft, *t; +- type_t *return_type = v->type; +- v->type = func_type; +- for (ft = v->type; is_ptr(ft); ft = type_pointer_get_ref(ft)) ++ type_t *return_type = v->declspec.type; ++ enum type_qualifier typequalifier = v->declspec.typequalifier; ++ ++ v->declspec.type = func_type; ++ v->declspec.typequalifier = TYPE_QUALIFIER_NONE; ++ for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref_type(ft)) + ; + assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION); + ft->details.function->retval = make_var(xstrdup("_RetVal")); +- ft->details.function->retval->type = return_type; ++ ft->details.function->retval->declspec.type = return_type; ++ ft->details.function->retval->declspec.typequalifier = typequalifier; ++ + /* move calling convention attribute, if present, from pointer nodes to + * function node */ +- for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t)) ++ for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t)) + ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV); + } + else + { + type_t *t; +- for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t)) ++ for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t)) + if (is_attr(t->attrs, ATTR_CALLCONV)) + error_loc("calling convention applied to non-function-pointer type\n"); + } + +- if (decl->bits) +- v->type = type_new_bitfield(v->type, decl->bits); +- + return v; + } + +@@ -5866,6 +5939,10 @@ var_list_t *append_var(var_list_t *list, var_t *var) + list_init( list ); + } + list_add_tail( list, &var->entry ); ++ ++ if (var->declspec.type) ++ var->declonly = !type_is_defined(var->declspec.type); ++ + return list; + } + +@@ -5885,11 +5962,11 @@ var_t *make_var(char *name) + { + var_t *v = xmalloc(sizeof(var_t)); + v->name = name; +- v->type = NULL; ++ init_declspec(&v->declspec, NULL); + v->attrs = NULL; + v->eval = NULL; +- v->stgclass = STG_NONE; + init_loc_info(&v->loc_info); ++ v->declonly = TRUE; + return v; + } + +@@ -5897,10 +5974,9 @@ static var_t *copy_var(var_t *src, char *name, map_attrs_filter_t attr_filter) + { + var_t *v = xmalloc(sizeof(var_t)); + v->name = name; +- v->type = src->type; ++ v->declspec = src->declspec; + v->attrs = map_attrs(src->attrs, attr_filter); + v->eval = src->eval; +- v->stgclass = src->stgclass; + v->loc_info = src->loc_info; + return v; + } +@@ -5920,7 +5996,7 @@ static declarator_t *make_declarator(var_t *var) + { + declarator_t *d = xmalloc(sizeof(*d)); + d->var = var ? var : make_var(NULL); +- d->type = NULL; ++ init_declspec(&d->declspec, NULL); + d->func_type = NULL; + d->bits = NULL; + return d; +@@ -5928,7 +6004,15 @@ static declarator_t *make_declarator(var_t *var) + + static type_t *make_safearray(type_t *type) + { +- return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0, ++ decl_spec_t aliasee_ds; ++ decl_spec_t element_ds; ++ ++ init_declspec(&element_ds, ++ type_new_alias( ++ init_declspec(&aliasee_ds, type), ++ "SAFEARRAY")); ++ ++ return type_new_array(NULL, &element_ds, TRUE, 0, + NULL, NULL, FC_RP); + } + +@@ -6007,6 +6091,8 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in + } + if (!namespace) + namespace = &global_namespace; ++ printf("reg_type { name : %s, namespace : %s, type : %s, ptr : %p}\n", name, namespace->name, ts_to_str(t), type); ++ + hash = hash_ident(name); + nt = xmalloc(sizeof(struct rtype)); + nt->name = name; +@@ -6018,15 +6104,16 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in + nt->t = t; + nt->next = namespace->type_hash[hash]; + namespace->type_hash[hash] = nt; +- if ((t == tsSTRUCT || t == tsUNION)) ++ if ((t == tsSTRUCT || t == tsUNION || t == tsENUM)) + fix_incomplete_types(type); + return type; + } + + static int is_incomplete(const type_t *t) + { +- return !t->defined && +- (type_get_type_detect_alias(t) == TYPE_STRUCT || ++ return !type_is_defined(t) && ++ (type_get_type_detect_alias(t) == TYPE_ENUM || ++ type_get_type_detect_alias(t) == TYPE_STRUCT || + type_get_type_detect_alias(t) == TYPE_UNION || + type_get_type_detect_alias(t) == TYPE_ENCAPSULATED_UNION); + } +@@ -6034,19 +6121,16 @@ static int is_incomplete(const type_t *t) + void add_incomplete(type_t *t) + { + struct typenode *tn = xmalloc(sizeof *tn); ++ assert(is_incomplete(t)); + tn->type = t; + list_add_tail(&incomplete_types, &tn->entry); + } + + static void fix_type(type_t *t) + { +- if (type_is_alias(t) && is_incomplete(t)) { +- type_t *ot = type_alias_get_aliasee(t); +- fix_type(ot); +- if (type_get_type_detect_alias(ot) == TYPE_STRUCT || +- type_get_type_detect_alias(ot) == TYPE_UNION || +- type_get_type_detect_alias(ot) == TYPE_ENCAPSULATED_UNION) +- t->details.structure = ot->details.structure; ++ if (type_is_alias(t) && is_incomplete(t)) ++ { ++ type_t *ot = type_alias_get_aliasee_type(t); + t->defined = ot->defined; + } + } +@@ -6070,7 +6154,7 @@ static void fix_incomplete_types(type_t *complete_type) + { + if (type_is_equal(complete_type, tn->type)) + { +- tn->type->details.structure = complete_type->details.structure; ++ tn->type->details = complete_type->details; + list_remove(&tn->entry); + free(tn); + } +@@ -6094,7 +6178,13 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at + type_get_type_detect_alias(type) == TYPE_ENCAPSULATED_UNION) + { + if (!type->name) ++ { + type->name = gen_name(); ++ /* the generated name will be used and this typedef excluded from the ++ * built typelib unless the typedef has the 'public' attribute, so add it here */ ++ if (do_typelib && !is_attr(attrs, ATTR_PUBLIC)) ++ attrs = append_attr(attrs, make_attr(ATTR_PUBLIC)); ++ } + + /* replace existing attributes when generating a typelib */ + if (do_typelib) +@@ -6120,12 +6210,12 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at + * for cleaner solution. + */ + if (cur && input_name == cur->loc_info.input_name) +- error_loc("%s: redefinition error; original definition was at %s:%d\n", ++ error_loc("FOO %s: redefinition error; original definition was at %s:%d\n", + cur->name, cur->loc_info.input_name, + cur->loc_info.line_number); + + name = declare_var(attrs, decl_spec, decl, 0); +- cur = type_new_alias(name->type, name->name); ++ cur = type_new_alias(&name->declspec, name->name); + cur->attrs = attrs; + + if (is_incomplete(cur)) +@@ -6140,6 +6230,8 @@ type_t *find_type(const char *name, struct namespace *namespace, int t) + { + struct rtype *cur; + ++ printf("find_type { name : %s, namespace %s, type : %s }\n", name, namespace ? namespace->name : NULL, ts_to_str(t)); ++ + if(namespace && namespace != &global_namespace) { + for(cur = namespace->type_hash[hash_ident(name)]; cur; cur = cur->next) { + if(cur->t == t && !strcmp(cur->name, name)) +@@ -6293,7 +6385,6 @@ struct allowed_attr allowed_attr[] = + /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" }, + /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, + /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, +- /* ATTR_CONST */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" }, + /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, + /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, + /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, +@@ -6328,7 +6419,6 @@ struct allowed_attr allowed_attr[] = + /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, + /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, + /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, +- /* ATTR_INLINE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" }, + /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, + /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" }, + /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" }, +@@ -6400,10 +6490,10 @@ static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs) + if (attr->type == ATTR_IMPLICIT_HANDLE) + { + const var_t *var = attr->u.pval; +- if (type_get_type( var->type) == TYPE_BASIC && +- type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) ++ if (type_get_type( var->declspec.type) == TYPE_BASIC && ++ type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE) + continue; +- if (is_aliaschain_attr( var->type, ATTR_HANDLE )) ++ if (is_aliaschain_attr( var->declspec.type, ATTR_HANDLE )) + continue; + error_loc("attribute %s requires a handle type in interface %s\n", + allowed_attr[attr->type].display_name, name); +@@ -6608,7 +6698,7 @@ static int is_ptr_guid_type(const type_t *type) + + /* second, make sure it is a pointer to something of size sizeof(GUID), + * i.e. 16 bytes */ +- return (type_memsize(type_pointer_get_ref(type)) == 16); ++ return (type_memsize(type_pointer_get_ref_type(type)) == 16); + } + + static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list) +@@ -6635,7 +6725,7 @@ static void check_remoting_fields(const var_t *var, type_t *type); + static void check_field_common(const type_t *container_type, + const char *container_name, const var_t *arg) + { +- type_t *type = arg->type; ++ type_t *type = arg->declspec.type; + int more_to_do; + const char *container_type_name; + const char *var_type; +@@ -6665,7 +6755,7 @@ static void check_field_common(const type_t *container_type, + } + + if (is_attr(arg->attrs, ATTR_LENGTHIS) && +- (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->type, ATTR_STRING))) ++ (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->declspec.type, ATTR_STRING))) + error_loc_info(&arg->loc_info, + "string and length_is specified for argument %s are mutually exclusive attributes\n", + arg->name); +@@ -6762,23 +6852,28 @@ static void check_field_common(const type_t *container_type, + { + const type_t *t = type; + while (is_ptr(t)) +- t = type_pointer_get_ref(t); ++ t = type_pointer_get_ref_type(t); + if (is_aliaschain_attr(t, ATTR_RANGE)) + warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name); + break; + } + case TGT_POINTER: +- type = type_pointer_get_ref(type); ++ type = type_pointer_get_ref_type(type); + more_to_do = TRUE; + break; + case TGT_ARRAY: +- type = type_array_get_element(type); ++ type = type_array_get_element_type(type); + more_to_do = TRUE; + break; ++ case TGT_ENUM: ++ type = type_get_real_type(type); ++ if(!type_is_complete(type)) ++ { ++ error_loc_info(&arg->loc_info, "undefined type declaration enum %s\n", type->name); ++ } + case TGT_USER_TYPE: + case TGT_IFACE_POINTER: + case TGT_BASIC: +- case TGT_ENUM: + case TGT_RANGE: + /* nothing to do */ + break; +@@ -6803,13 +6898,18 @@ static void check_remoting_fields(const var_t *var, type_t *type) + if (type_is_complete(type)) + fields = type_struct_get_fields(type); + else +- error_loc_info(&var->loc_info, "undefined type declaration %s\n", type->name); ++ error_loc_info(&var->loc_info, "undefined type declaration struct %s\n", type->name); + } + else if (type_get_type(type) == TYPE_UNION || type_get_type(type) == TYPE_ENCAPSULATED_UNION) +- fields = type_union_get_cases(type); ++ { ++ if (type_is_complete(type)) ++ fields = type_union_get_cases(type); ++ else ++ error_loc_info(&var->loc_info, "undefined type declaration union %s\n", type->name); ++ } + + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) +- if (field->type) check_field_common(type, type->name, field); ++ if (field->declspec.type) check_field_common(type, type->name, field); + } + + /* checks that arguments for a function make sense for marshalling and unmarshalling */ +@@ -6818,9 +6918,10 @@ static void check_remoting_args(const var_t *func) + const char *funcname = func->name; + const var_t *arg; + +- if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry ) ++ assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION); ++ if (func->declspec.type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->declspec.type->details.function->args, const var_t, entry ) + { +- const type_t *type = arg->type; ++ const type_t *type = arg->declspec.type; + + /* check that [out] parameters have enough pointer levels */ + if (is_attr(arg->attrs, ATTR_OUT)) +@@ -6860,16 +6961,16 @@ static void check_remoting_args(const var_t *func) + } + } + +- check_field_common(func->type, funcname, arg); ++ check_field_common(func->declspec.type, funcname, arg); + } + +- if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID) ++ if (type_get_type(type_function_get_rettype(func->declspec.type)) != TYPE_VOID) + { + var_t var; + var = *func; +- var.type = type_function_get_rettype(func->type); ++ var.declspec.type = type_function_get_rettype(func->declspec.type); + var.name = xstrdup("return value"); +- check_field_common(func->type, funcname, &var); ++ check_field_common(func->declspec.type, funcname, &var); + free(var.name); + } + } +@@ -6886,8 +6987,8 @@ static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func) + * function */ + var_t *idl_handle = make_var(xstrdup("IDL_handle")); + idl_handle->attrs = append_attr(NULL, make_attr(ATTR_IN)); +- idl_handle->type = find_type_or_error("handle_t", 0); +- type_function_add_head_arg(func->type, idl_handle); ++ idl_handle->declspec.type = find_type_or_error("handle_t", 0); ++ type_function_add_head_arg(func->declspec.type, idl_handle); + } + } + +@@ -6952,6 +7053,7 @@ static void check_async_uuid(type_t *iface) + type_t *async_iface; + type_t *inherit; + ++ assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE); + if (!is_attr(iface->attrs, ATTR_ASYNCUUID)) return; + + inherit = iface->details.iface->inherit; +@@ -6968,7 +7070,8 @@ static void check_async_uuid(type_t *iface) + var_t *begin_func, *finish_func, *func = stmt->u.var, *arg; + var_list_t *begin_args = NULL, *finish_args = NULL, *args; + +- args = func->type->details.function->args; ++ assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION); ++ args = func->declspec.type->details.function->args; + if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry) + { + if (is_attr(arg->attrs, ATTR_IN) || !is_attr(arg->attrs, ATTR_OUT)) +@@ -6978,15 +7081,15 @@ static void check_async_uuid(type_t *iface) + } + + begin_func = copy_var(func, concat_str("Begin_", func->name), NULL); +- begin_func->type = type_new_function(begin_args); +- begin_func->type->attrs = func->attrs; +- begin_func->type->details.function->retval = func->type->details.function->retval; ++ begin_func->declspec.type = type_new_function(begin_args); ++ begin_func->declspec.type->attrs = func->attrs; ++ begin_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval; + stmts = append_statement(stmts, make_statement_declaration(begin_func)); + + finish_func = copy_var(func, concat_str("Finish_", func->name), NULL); +- finish_func->type = type_new_function(finish_args); +- finish_func->type->attrs = func->attrs; +- finish_func->type->details.function->retval = func->type->details.function->retval; ++ finish_func->declspec.type = type_new_function(finish_args); ++ finish_func->declspec.type->attrs = func->attrs; ++ finish_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval; + stmts = append_statement(stmts, make_statement_declaration(finish_func)); + } + +@@ -7026,6 +7129,7 @@ static void check_statements(const statement_list_t *stmts, int is_inside_librar + static void check_all_user_types(const statement_list_t *stmts) + { + const statement_t *stmt; ++ const var_t *v; + + if (stmts) LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry) + { +@@ -7037,7 +7141,11 @@ static void check_all_user_types(const statement_list_t *stmts) + const statement_t *stmt_func; + STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) { + const var_t *func = stmt_func->u.var; +- check_for_additional_prototype_types(func->type->details.function->args); ++ assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION); ++ if (func->declspec.type->details.function->args) ++ LIST_FOR_EACH_ENTRY( v, func->declspec.type->details.function->args, const var_t, entry ) ++ check_for_additional_prototype_types(v->declspec.type); ++ check_for_additional_prototype_types(type_function_get_rettype(func->declspec.type)); + } + } + } +@@ -7071,6 +7179,10 @@ static statement_t *make_statement_type_decl(type_t *type) + { + statement_t *stmt = make_statement(STMT_TYPE); + stmt->u.type = type; ++ if (type_is_defined(type)) ++ { ++ stmt->declonly = FALSE; ++ } + return stmt; + } + +@@ -7085,16 +7197,16 @@ static statement_t *make_statement_declaration(var_t *var) + { + statement_t *stmt = make_statement(STMT_DECLARATION); + stmt->u.var = var; +- if (var->stgclass == STG_EXTERN && var->eval) ++ if (var->declspec.stgclass == STG_EXTERN && var->eval) + warning("'%s' initialised and declared extern\n", var->name); + if (is_const_decl(var)) + { + if (var->eval) + reg_const(var); + } +- else if (type_get_type(var->type) == TYPE_FUNCTION) ++ else if (type_get_type(var->declspec.type) == TYPE_FUNCTION) + check_function_attrs(var->name, var->attrs); +- else if (var->stgclass == STG_NONE || var->stgclass == STG_REGISTER) ++ else if (var->declspec.stgclass == STG_NONE || var->declspec.stgclass == STG_REGISTER) + error_loc("instantiation of data is illegal\n"); + return stmt; + } +@@ -7146,6 +7258,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) + declarator_t *decl, *next; + statement_t *stmt; + type_list_t **type_list; ++ int defined = TRUE; + + if (!decls) return NULL; + +@@ -7157,6 +7270,18 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) + { + var_t *var = decl->var; + type_t *type = find_type_or_error(var->name, 0); ++ ++ /* ensure that all of the types in this typedef statement have been defined ++ * before setting its declonly flag */ ++ if (type_is_pointerish(type)) ++ { ++ defined = defined & type_is_defined(type_get_pointer_chain_tail(type)); ++ } ++ else ++ { ++ defined = defined & type_is_defined(type_get_real_type(type)); ++ } ++ + *type_list = xmalloc(sizeof(type_list_t)); + (*type_list)->type = type; + (*type_list)->next = NULL; +@@ -7166,6 +7291,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) + free(var); + } + ++ stmt->declonly = !defined; + return stmt; + } + +@@ -7206,7 +7332,7 @@ void init_loc_info(loc_info_t *i) + + static void check_def(const type_t *t) + { +- if (t->defined) +- error_loc("%s: redefinition error; original definition was at %s:%d\n", ++ if (type_is_defined(t)) ++ error_loc("BAR %s: redefinition error; original definition was at %s:%d\n", + t->name, t->loc_info.input_name, t->loc_info.line_number); + } +diff --git a/mingw-w64-tools/widl/src/parser.tab.h b/mingw-w64-tools/widl/src/parser.tab.h +index 09874726..fc7a8f4d 100644 +--- a/mingw-w64-tools/widl/src/parser.tab.h ++++ b/mingw-w64-tools/widl/src/parser.tab.h +@@ -1,8 +1,8 @@ +-/* A Bison parser, made by GNU Bison 3.0.5. */ ++/* A Bison parser, made by GNU Bison 3.0.4. */ + + /* Bison interface for Yacc-like parsers in C + +- Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc. ++ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -239,7 +239,7 @@ extern int parser_debug; + + union YYSTYPE + { +-#line 142 "parser.y" /* yacc.c:1910 */ ++#line 136 "parser.y" /* yacc.c:1909 */ + + attr_t *attr; + attr_list_t *attr_list; +@@ -266,8 +266,10 @@ union YYSTYPE + struct _import_t *import; + struct _decl_spec_t *declspec; + enum storage_class stgclass; ++ enum type_qualifier typequalifier; ++ enum function_specifier funcspecifier; + +-#line 271 "parser.tab.h" /* yacc.c:1910 */ ++#line 273 "parser.tab.h" /* yacc.c:1909 */ + }; + + typedef union YYSTYPE YYSTYPE; +diff --git a/mingw-w64-tools/widl/src/parser.y b/mingw-w64-tools/widl/src/parser.y +index d9793941..bb14bf76 100644 +--- a/mingw-w64-tools/widl/src/parser.y ++++ b/mingw-w64-tools/widl/src/parser.y +@@ -52,13 +52,6 @@ struct _import_t + int import_performed; + }; + +-typedef struct _decl_spec_t +-{ +- type_t *type; +- attr_list_t *attrs; +- enum storage_class stgclass; +-} decl_spec_t; +- + typelist_t incomplete_types = LIST_INIT(incomplete_types); + + static void fix_incomplete(void); +@@ -67,7 +60,7 @@ static void fix_incomplete_types(type_t *complete_type); + static str_list_t *append_str(str_list_t *list, char *str); + static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); + static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list); +-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass); ++static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier); + static attr_t *make_attr(enum attr_type type); + static attr_t *make_attrv(enum attr_type type, unsigned int val); + static attr_t *make_attrp(enum attr_type type, void *val); +@@ -83,6 +76,7 @@ static declarator_t *make_declarator(var_t *var); + static type_t *make_safearray(type_t *type); + static typelib_t *make_library(const char *name, const attr_list_t *attrs); + static type_t *append_chain_type(type_t *chain, type_t *type); ++static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier); + static warning_list_t *append_warning(warning_list_t *, int); + + static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs); +@@ -165,6 +159,8 @@ static typelib_t *current_typelib; + struct _import_t *import; + struct _decl_spec_t *declspec; + enum storage_class stgclass; ++ enum type_qualifier typequalifier; ++ enum function_specifier funcspecifier; + } + + %token <str> aIDENTIFIER aPRAGMA +@@ -266,14 +262,16 @@ static typelib_t *current_typelib; + %token tWCHAR tWIREMARSHAL + %token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH + +-%type <attr> attribute type_qualifier function_specifier acf_attribute +-%type <attr_list> m_attributes attributes attrib_list m_type_qual_list ++%type <attr> attribute acf_attribute ++%type <attr_list> m_attributes attributes attrib_list + %type <attr_list> acf_attributes acf_attribute_list + %type <str_list> str_list + %type <expr> m_expr expr expr_const expr_int_const array m_bitfield + %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const + %type <ifinfo> interfacehdr + %type <stgclass> storage_cls_spec ++%type <typequalifier> type_qualifier m_type_qual_bits ++%type <funcspecifier> function_specifier + %type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type + %type <type> inherit interface interfacedef interfacedec + %type <type> dispinterface dispinterfacehdr dispinterfacedef +@@ -318,7 +316,7 @@ static typelib_t *current_typelib; + %right '!' '~' CAST PPTR POS NEG ADDRESSOF tSIZEOF + %left '.' MEMBERPTR '[' ']' + +-%error-verbose ++%define parse.error verbose + + %% + +@@ -651,10 +649,10 @@ enum_list: enum { if (!$1->eval) + + enum: ident '=' expr_int_const { $$ = reg_const($1); + $$->eval = $3; +- $$->type = type_new_int(TYPE_BASIC_INT, 0); ++ $$->declspec.type = type_new_int(TYPE_BASIC_INT, 0); + } + | ident { $$ = reg_const($1); +- $$->type = type_new_int(TYPE_BASIC_INT, 0); ++ $$->declspec.type = type_new_int(TYPE_BASIC_INT, 0); + } + ; + +@@ -740,7 +738,7 @@ field: m_attributes decl_spec struct_declarator_list ';' + $$ = set_var_types($1, $2, $3); + } + | m_attributes uniondef ';' { var_t *v = make_var(NULL); +- v->type = $2; v->attrs = $1; ++ v->declspec.type = $2; v->attrs = $1; + $$ = append_var(NULL, v); + } + ; +@@ -764,13 +762,13 @@ s_field: m_attributes decl_spec declarator { $$ = declare_var(check_field_attrs + free($3); + } + | m_attributes structdef { var_t *v = make_var(NULL); +- v->type = $2; v->attrs = $1; ++ v->declspec.type = $2; v->attrs = $1; + $$ = v; + } + ; + + funcdef: declaration { $$ = $1; +- if (type_get_type($$->type) != TYPE_FUNCTION) ++ if (type_get_type($$->declspec.type) != TYPE_FUNCTION) + error_loc("only methods may be declared inside the methods section of a dispinterface\n"); + check_function_attrs($$->name, $$->attrs); + } +@@ -955,20 +953,20 @@ storage_cls_spec: + ; + + function_specifier: +- tINLINE { $$ = make_attr(ATTR_INLINE); } ++ tINLINE { $$ = FUNCTION_SPECIFIER_INLINE; } + ; + + type_qualifier: +- tCONST { $$ = make_attr(ATTR_CONST); } ++ tCONST { $$ = TYPE_QUALIFIER_CONST; } + ; + +-m_type_qual_list: { $$ = NULL; } +- | m_type_qual_list type_qualifier { $$ = append_attr($1, $2); } ++m_type_qual_bits: { $$ = TYPE_QUALIFIER_NONE; } ++ | m_type_qual_bits type_qualifier { $$ = $1 | $2; } + ; + +-decl_spec: type m_decl_spec_no_type { $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE); } ++decl_spec: type m_decl_spec_no_type { $$ = make_decl_spec($1, $2, NULL, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); } + | decl_spec_no_type type m_decl_spec_no_type +- { $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); } ++ { $$ = make_decl_spec($2, $1, $3, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); } + ; + + m_decl_spec_no_type: { $$ = NULL; } +@@ -976,44 +974,44 @@ m_decl_spec_no_type: { $$ = NULL; } + ; + + decl_spec_no_type: +- type_qualifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); } +- | function_specifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); } +- | storage_cls_spec m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1); } ++ type_qualifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, $1, FUNCTION_SPECIFIER_NONE); } ++ | function_specifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, TYPE_QUALIFIER_NONE, $1); } ++ | storage_cls_spec m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); } + ; + + declarator: +- '*' m_type_qual_list declarator %prec PPTR +- { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } ++ '*' m_type_qual_bits declarator %prec PPTR ++ { $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); } + | callconv declarator { $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1)); +- else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } ++ else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + | direct_declarator + ; + + direct_declarator: + ident { $$ = make_declarator($1); } + | '(' declarator ')' { $$ = $2; } +- | direct_declarator array { $$ = $1; $$->type = append_array($$->type, $2); } ++ | direct_declarator array { $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); } + | direct_declarator '(' m_args ')' { $$ = $1; +- $$->func_type = append_chain_type($$->type, type_new_function($3)); +- $$->type = NULL; ++ $$->func_type = append_chain_type($$->declspec.type, type_new_function($3)); ++ $$->declspec.type = NULL; + } + ; + + /* abstract declarator */ + abstract_declarator: +- '*' m_type_qual_list m_abstract_declarator %prec PPTR +- { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } ++ '*' m_type_qual_bits m_abstract_declarator %prec PPTR ++ { $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); } + | callconv m_abstract_declarator { $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1)); +- else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } ++ else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + | abstract_direct_declarator + ; + + /* abstract declarator without accepting direct declarator */ + abstract_declarator_no_direct: +- '*' m_type_qual_list m_any_declarator %prec PPTR +- { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } ++ '*' m_type_qual_bits m_any_declarator %prec PPTR ++ { $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); } + | callconv m_any_declarator { $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1)); +- else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } ++ else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + ; + + /* abstract declarator or empty */ +@@ -1024,33 +1022,33 @@ m_abstract_declarator: { $$ = make_declarator(NULL); } + /* abstract direct declarator */ + abstract_direct_declarator: + '(' abstract_declarator_no_direct ')' { $$ = $2; } +- | abstract_direct_declarator array { $$ = $1; $$->type = append_array($$->type, $2); } +- | array { $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); } ++ | abstract_direct_declarator array { $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); } ++ | array { $$ = make_declarator(NULL); $$->declspec.type = append_array($$->declspec.type, $1); } + | '(' m_args ')' + { $$ = make_declarator(NULL); +- $$->func_type = append_chain_type($$->type, type_new_function($2)); +- $$->type = NULL; ++ $$->func_type = append_chain_type($$->declspec.type, type_new_function($2)); ++ $$->declspec.type = NULL; + } + | abstract_direct_declarator '(' m_args ')' + { $$ = $1; +- $$->func_type = append_chain_type($$->type, type_new_function($3)); +- $$->type = NULL; ++ $$->func_type = append_chain_type($$->declspec.type, type_new_function($3)); ++ $$->declspec.type = NULL; + } + ; + + /* abstract or non-abstract declarator */ + any_declarator: +- '*' m_type_qual_list m_any_declarator %prec PPTR +- { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } +- | callconv m_any_declarator { $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } ++ '*' m_type_qual_bits m_any_declarator %prec PPTR ++ { $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); } ++ | callconv m_any_declarator { $$ = $2; $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + | any_direct_declarator + ; + + /* abstract or non-abstract declarator without accepting direct declarator */ + any_declarator_no_direct: +- '*' m_type_qual_list m_any_declarator %prec PPTR +- { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } +- | callconv m_any_declarator { $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } ++ '*' m_type_qual_bits m_any_declarator %prec PPTR ++ { $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); } ++ | callconv m_any_declarator { $$ = $2; $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + ; + + /* abstract or non-abstract declarator or empty */ +@@ -1064,17 +1062,17 @@ m_any_declarator: { $$ = make_declarator(NULL); } + any_direct_declarator: + ident { $$ = make_declarator($1); } + | '(' any_declarator_no_direct ')' { $$ = $2; } +- | any_direct_declarator array { $$ = $1; $$->type = append_array($$->type, $2); } +- | array { $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); } ++ | any_direct_declarator array { $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); } ++ | array { $$ = make_declarator(NULL); $$->declspec.type = append_array($$->declspec.type, $1); } + | '(' m_args ')' + { $$ = make_declarator(NULL); +- $$->func_type = append_chain_type($$->type, type_new_function($2)); +- $$->type = NULL; ++ $$->func_type = append_chain_type($$->declspec.type, type_new_function($2)); ++ $$->declspec.type = NULL; + } + | any_direct_declarator '(' m_args ')' + { $$ = $1; +- $$->func_type = append_chain_type($$->type, type_new_function($3)); +- $$->type = NULL; ++ $$->func_type = append_chain_type($$->declspec.type, type_new_function($3)); ++ $$->declspec.type = NULL; + } + ; + +@@ -1197,7 +1195,8 @@ static void decl_builtin_basic(const char *name, enum type_basic_type type) + + static void decl_builtin_alias(const char *name, type_t *t) + { +- reg_type(type_new_alias(t, name), name, NULL, 0); ++ decl_spec_t ds; ++ reg_type(type_new_alias(init_declspec(&ds, t), name), name, &global_namespace, 0); + } + + void init_types(void) +@@ -1208,7 +1207,7 @@ void init_types(void) + decl_builtin_basic("double", TYPE_BASIC_DOUBLE); + decl_builtin_basic("error_status_t", TYPE_BASIC_ERROR_STATUS_T); + decl_builtin_basic("handle_t", TYPE_BASIC_HANDLE); +- decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_BYTE)); ++ decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_CHAR)); + } + + static str_list_t *append_str(str_list_t *list, char *str) +@@ -1239,6 +1238,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) + LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry) + if (attr_existing->type == attr->type) + { ++ __builtin_trap(); + parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type)); + /* use the last attribute, like MIDL does */ + list_remove(&attr_existing->entry); +@@ -1298,53 +1298,73 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter + return new_list; + } + +-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass) ++static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier) + { + decl_spec_t *declspec = left ? left : right; + if (!declspec) + { + declspec = xmalloc(sizeof(*declspec)); + declspec->type = NULL; +- declspec->attrs = NULL; + declspec->stgclass = STG_NONE; ++ declspec->typequalifier = TYPE_QUALIFIER_NONE; ++ declspec->funcspecifier = FUNCTION_SPECIFIER_NONE; + } + declspec->type = type; + if (left && declspec != left) + { +- declspec->attrs = append_attr_list(declspec->attrs, left->attrs); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = left->stgclass; + else if (left->stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); ++ ++ if (declspec->typequalifier == TYPE_QUALIFIER_NONE) ++ declspec->typequalifier = left->typequalifier; ++ else if (left->typequalifier != TYPE_QUALIFIER_NONE) ++ error_loc("only one type qualifier can be specified\n"); ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE) ++ declspec->funcspecifier = left->funcspecifier; ++ else if (left->funcspecifier != FUNCTION_SPECIFIER_NONE) ++ error_loc("only one function specifier can be specified\n"); ++ + assert(!left->type); + free(left); + } + if (right && declspec != right) + { +- declspec->attrs = append_attr_list(declspec->attrs, right->attrs); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = right->stgclass; + else if (right->stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); ++ ++ if (declspec->typequalifier == TYPE_QUALIFIER_NONE) ++ declspec->typequalifier = right->typequalifier; ++ else if (right->typequalifier != TYPE_QUALIFIER_NONE) ++ error_loc("only one type qualifier can be specified\n"); ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE) ++ declspec->funcspecifier = right->funcspecifier; ++ else if (right->funcspecifier != FUNCTION_SPECIFIER_NONE) ++ error_loc("only one function specifier can be specified\n"); ++ + assert(!right->type); + free(right); + } + +- declspec->attrs = append_attr(declspec->attrs, attr); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = stgclass; + else if (stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); + +- /* apply attributes to type */ +- if (type && declspec->attrs) +- { +- attr_list_t *attrs; +- declspec->type = duptype(type, 1); +- attrs = map_attrs(type->attrs, NULL); +- declspec->type->attrs = append_attr_list(attrs, declspec->attrs); +- declspec->attrs = NULL; +- } ++ if (declspec->typequalifier == TYPE_QUALIFIER_NONE) ++ declspec->typequalifier = typequalifier; ++ else if (typequalifier != TYPE_QUALIFIER_NONE) ++ error_loc("only one type qualifier can be specified\n"); ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE) ++ declspec->funcspecifier = funcspecifier; ++ else if (funcspecifier != FUNCTION_SPECIFIER_NONE) ++ error_loc("only one function specifier can be specified\n"); + + return declspec; + } +@@ -1430,6 +1450,7 @@ void clear_all_offsets(void) + + static void type_function_add_head_arg(type_t *type, var_t *arg) + { ++ assert(type_get_type_detect_alias(type) == TYPE_FUNCTION); + if (!type->details.function->args) + { + type->details.function->args = xmalloc( sizeof(*type->details.function->args) ); +@@ -1474,31 +1495,60 @@ static int is_allowed_range_type(const type_t *type) + static type_t *get_array_or_ptr_ref(type_t *type) + { + if (is_ptr(type)) +- return type_pointer_get_ref(type); ++ return type_pointer_get_ref_type(type); + else if (is_array(type)) +- return type_array_get_element(type); ++ return type_array_get_element_type(type); + return NULL; + } + + static type_t *append_chain_type(type_t *chain, type_t *type) + { +- type_t *chain_type; ++ type_t *chain_type = NULL; + + if (!chain) + return type; + for (chain_type = chain; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type)) + ; + ++ assert(!type_is_alias(chain_type)); + if (is_ptr(chain_type)) +- chain_type->details.pointer.ref = type; ++ chain_type->details.pointer.ref.type = type; + else if (is_array(chain_type)) +- chain_type->details.array.elem = type; ++ chain_type->details.array.elem.type = type; + else + assert(0); + + return chain; + } + ++static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier) ++{ ++ type_t *chain_type = chain->type; ++ decl_spec_t *chain_declspec = NULL; ++ ++ if (!chain_type) ++ { ++ chain->type = type; ++ chain->typequalifier = typequalifier; ++ return chain; ++ } ++ ++ for(; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type)) ++ ; ++ ++ if (is_ptr(chain_type)) ++ chain_declspec = &chain_type->details.pointer.ref; ++ else if (is_array(chain_type)) ++ chain_declspec = &chain_type->details.array.elem; ++ else ++ assert(NULL); ++ ++ chain_declspec->type = type; ++ chain_declspec->typequalifier = typequalifier; ++ ++ return chain; ++} ++ + static warning_list_t *append_warning(warning_list_t *list, int num) + { + warning_t *entry; +@@ -1514,7 +1564,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num) + return list; + } + +-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl, ++static var_t *declare_var(attr_list_t *attrs, decl_spec_t *declspec, const declarator_t *decl, + int top) + { + var_t *v = decl->var; +@@ -1523,58 +1573,80 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + expr_t *dim; + type_t **ptype; + type_t *func_type = decl ? decl->func_type : NULL; +- type_t *type = decl_spec->type; ++ type_t *type = declspec->type; + +- if (is_attr(type->attrs, ATTR_INLINE)) +- { ++ ++ if (declspec->funcspecifier == FUNCTION_SPECIFIER_INLINE) { + if (!func_type) + error_loc("inline attribute applied to non-function type\n"); + else + { +- type_t *t; +- /* move inline attribute from return type node to function node */ +- for (t = func_type; is_ptr(t); t = type_pointer_get_ref(t)) +- ; +- t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE); ++ v->declspec.funcspecifier = declspec->funcspecifier; + } + } + +- /* add type onto the end of the pointers in pident->type */ +- v->type = append_chain_type(decl ? decl->type : NULL, type); +- v->stgclass = decl_spec->stgclass; ++ /* if the var type is a pointerish, we need to move the type qualifier to the pointee's declspec ++ * unless the pointee already has const type qualifier*/ ++ if (!decl) ++ { ++ /* simplest case, no pointers to deal with here */ ++ v->declspec.typequalifier = declspec->typequalifier; ++ } else if (decl->bits) ++ { ++ /* dealing with a bitfield, generate bitfield and copy over typequalifier*/ ++ v->declspec.type = type_new_bitfield(declspec->type, decl->bits); ++ v->declspec.typequalifier = declspec->typequalifier; ++ } ++ else ++ { ++ /* here we're dealing with a pointerish type chain, so we need to pull ++ * the typequalifier off of the declspec and stick them in the type's attr list ++ */ ++ v->declspec.type = decl->declspec.type; ++ v->declspec.typequalifier = decl->declspec.typequalifier; ++ append_chain_declspec(&v->declspec, type, declspec->typequalifier); ++ } ++ ++ v->declspec.stgclass = declspec->stgclass; + v->attrs = attrs; + + /* check for pointer attribute being applied to non-pointer, non-array + * type */ +- if (!is_array(v->type)) ++ if (!is_array(v->declspec.type)) + { + int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); + const type_t *ptr = NULL; + /* pointer attributes on the left side of the type belong to the function + * pointer, if one is being declared */ +- type_t **pt = func_type ? &func_type : &v->type; ++ type_t **pt = func_type ? &func_type : &v->declspec.type; + for (ptr = *pt; ptr && !ptr_attr; ) + { + ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE); + if (!ptr_attr && type_is_alias(ptr)) +- ptr = type_alias_get_aliasee(ptr); ++ ptr = type_alias_get_aliasee_type(ptr); + else + break; + } + if (is_ptr(ptr)) + { + if (ptr_attr && ptr_attr != FC_UP && +- type_get_type(type_pointer_get_ref(ptr)) == TYPE_INTERFACE) ++ type_get_type(type_pointer_get_ref_type(ptr)) == TYPE_INTERFACE) + warning_loc_info(&v->loc_info, + "%s: pointer attribute applied to interface " + "pointer type has no effect\n", v->name); +- if (!ptr_attr && top && (*pt)->details.pointer.def_fc != FC_RP) ++ if (!ptr_attr && top && type_pointer_get_default_fc(*pt) != FC_RP) + { ++ printf("dup_pointer_type!\n"); ++ printf("type : %p name : %s\n", *pt, (*pt)->name); ++ /* ptr_attr is ref,unique or full (FC_RP, FC_UP, FC_FP) */ ++ /* *pt could be the var's declspec's type OR a type on a typedef */ ++ /* not an array */ ++ + /* FIXME: this is a horrible hack to cope with the issue that we + * store an offset to the typeformat string in the type object, but + * two typeformat strings may be written depending on whether the + * pointer is a toplevel parameter or not */ +- *pt = duptype(*pt, 1); ++ *pt = dup_pointer_type(*pt); + } + } + else if (ptr_attr) +@@ -1585,16 +1657,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + { + type_t *t = type; + +- if (!is_ptr(v->type) && !is_array(v->type)) ++ if (!is_ptr(v->declspec.type) && !is_array(v->declspec.type)) + error_loc("'%s': [string] attribute applied to non-pointer, non-array type\n", + v->name); + + for (;;) + { + if (is_ptr(t)) +- t = type_pointer_get_ref(t); ++ t = type_pointer_get_ref_type(t); + else if (is_array(t)) +- t = type_array_get_element(t); ++ t = type_array_get_element_type(t); + else + break; + } +@@ -1611,15 +1683,15 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + + if (is_attr(v->attrs, ATTR_V1ENUM)) + { +- if (type_get_type_detect_alias(v->type) != TYPE_ENUM) ++ if (type_get_type_detect_alias(v->declspec.type) != TYPE_ENUM) + error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name); + } + +- if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->type)) ++ if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->declspec.type)) + error_loc("'%s': [range] attribute applied to non-integer type\n", + v->name); + +- ptype = &v->type; ++ ptype = &v->declspec.type; + if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry) + { + if (dim->type != EXPR_VOID) +@@ -1632,7 +1704,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + else + *ptype = type_new_array((*ptype)->name, + type_array_get_element(*ptype), FALSE, +- 0, dim, NULL, 0); ++ 0, dim, NULL, FC_RP); + } + else if (is_ptr(*ptype)) + *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE, +@@ -1641,15 +1713,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + error_loc("%s: size_is attribute applied to illegal type\n", v->name); + } + ++ assert(!type_is_alias(*ptype)); + if (is_ptr(*ptype)) +- ptype = &(*ptype)->details.pointer.ref; ++ ptype = &(*ptype)->details.pointer.ref.type; + else if (is_array(*ptype)) +- ptype = &(*ptype)->details.array.elem; ++ ptype = &(*ptype)->details.array.elem.type; + else + error_loc("%s: too many expressions in size_is attribute\n", v->name); + } + +- ptype = &v->type; ++ ptype = &v->declspec.type; + if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry) + { + if (dim->type != EXPR_VOID) +@@ -1667,10 +1740,11 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + error_loc("%s: length_is attribute applied to illegal type\n", v->name); + } + ++ assert(!type_is_alias(*ptype)); + if (is_ptr(*ptype)) +- ptype = &(*ptype)->details.pointer.ref; ++ ptype = &(*ptype)->details.pointer.ref.type; + else if (is_array(*ptype)) +- ptype = &(*ptype)->details.array.elem; ++ ptype = &(*ptype)->details.array.elem.type; + else + error_loc("%s: too many expressions in length_is attribute\n", v->name); + } +@@ -1681,29 +1755,31 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl + if (func_type) + { + type_t *ft, *t; +- type_t *return_type = v->type; +- v->type = func_type; +- for (ft = v->type; is_ptr(ft); ft = type_pointer_get_ref(ft)) ++ type_t *return_type = v->declspec.type; ++ enum type_qualifier typequalifier = v->declspec.typequalifier; ++ ++ v->declspec.type = func_type; ++ v->declspec.typequalifier = TYPE_QUALIFIER_NONE; ++ for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref_type(ft)) + ; + assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION); + ft->details.function->retval = make_var(xstrdup("_RetVal")); +- ft->details.function->retval->type = return_type; ++ ft->details.function->retval->declspec.type = return_type; ++ ft->details.function->retval->declspec.typequalifier = typequalifier; ++ + /* move calling convention attribute, if present, from pointer nodes to + * function node */ +- for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t)) ++ for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t)) + ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV); + } + else + { + type_t *t; +- for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t)) ++ for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t)) + if (is_attr(t->attrs, ATTR_CALLCONV)) + error_loc("calling convention applied to non-function-pointer type\n"); + } + +- if (decl->bits) +- v->type = type_new_bitfield(v->type, decl->bits); +- + return v; + } + +@@ -1751,6 +1827,10 @@ var_list_t *append_var(var_list_t *list, var_t *var) + list_init( list ); + } + list_add_tail( list, &var->entry ); ++ ++ if (var->declspec.type) ++ var->declonly = !type_is_defined(var->declspec.type); ++ + return list; + } + +@@ -1770,11 +1850,11 @@ var_t *make_var(char *name) + { + var_t *v = xmalloc(sizeof(var_t)); + v->name = name; +- v->type = NULL; ++ init_declspec(&v->declspec, NULL); + v->attrs = NULL; + v->eval = NULL; +- v->stgclass = STG_NONE; + init_loc_info(&v->loc_info); ++ v->declonly = TRUE; + return v; + } + +@@ -1782,10 +1862,9 @@ static var_t *copy_var(var_t *src, char *name, map_attrs_filter_t attr_filter) + { + var_t *v = xmalloc(sizeof(var_t)); + v->name = name; +- v->type = src->type; ++ v->declspec = src->declspec; + v->attrs = map_attrs(src->attrs, attr_filter); + v->eval = src->eval; +- v->stgclass = src->stgclass; + v->loc_info = src->loc_info; + return v; + } +@@ -1805,7 +1884,7 @@ static declarator_t *make_declarator(var_t *var) + { + declarator_t *d = xmalloc(sizeof(*d)); + d->var = var ? var : make_var(NULL); +- d->type = NULL; ++ init_declspec(&d->declspec, NULL); + d->func_type = NULL; + d->bits = NULL; + return d; +@@ -1813,7 +1892,15 @@ static declarator_t *make_declarator(var_t *var) + + static type_t *make_safearray(type_t *type) + { +- return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0, ++ decl_spec_t aliasee_ds; ++ decl_spec_t element_ds; ++ ++ init_declspec(&element_ds, ++ type_new_alias( ++ init_declspec(&aliasee_ds, type), ++ "SAFEARRAY")); ++ ++ return type_new_array(NULL, &element_ds, TRUE, 0, + NULL, NULL, FC_RP); + } + +@@ -1892,6 +1979,8 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in + } + if (!namespace) + namespace = &global_namespace; ++ printf("reg_type { name : %s, namespace : %s, type : %s, ptr : %p}\n", name, namespace->name, ts_to_str(t), type); ++ + hash = hash_ident(name); + nt = xmalloc(sizeof(struct rtype)); + nt->name = name; +@@ -1903,15 +1992,16 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in + nt->t = t; + nt->next = namespace->type_hash[hash]; + namespace->type_hash[hash] = nt; +- if ((t == tsSTRUCT || t == tsUNION)) ++ if ((t == tsSTRUCT || t == tsUNION || t == tsENUM)) + fix_incomplete_types(type); + return type; + } + + static int is_incomplete(const type_t *t) + { +- return !t->defined && +- (type_get_type_detect_alias(t) == TYPE_STRUCT || ++ return !type_is_defined(t) && ++ (type_get_type_detect_alias(t) == TYPE_ENUM || ++ type_get_type_detect_alias(t) == TYPE_STRUCT || + type_get_type_detect_alias(t) == TYPE_UNION || + type_get_type_detect_alias(t) == TYPE_ENCAPSULATED_UNION); + } +@@ -1919,19 +2009,16 @@ static int is_incomplete(const type_t *t) + void add_incomplete(type_t *t) + { + struct typenode *tn = xmalloc(sizeof *tn); ++ assert(is_incomplete(t)); + tn->type = t; + list_add_tail(&incomplete_types, &tn->entry); + } + + static void fix_type(type_t *t) + { +- if (type_is_alias(t) && is_incomplete(t)) { +- type_t *ot = type_alias_get_aliasee(t); +- fix_type(ot); +- if (type_get_type_detect_alias(ot) == TYPE_STRUCT || +- type_get_type_detect_alias(ot) == TYPE_UNION || +- type_get_type_detect_alias(ot) == TYPE_ENCAPSULATED_UNION) +- t->details.structure = ot->details.structure; ++ if (type_is_alias(t) && is_incomplete(t)) ++ { ++ type_t *ot = type_alias_get_aliasee_type(t); + t->defined = ot->defined; + } + } +@@ -1955,7 +2042,7 @@ static void fix_incomplete_types(type_t *complete_type) + { + if (type_is_equal(complete_type, tn->type)) + { +- tn->type->details.structure = complete_type->details.structure; ++ tn->type->details = complete_type->details; + list_remove(&tn->entry); + free(tn); + } +@@ -1979,7 +2066,13 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at + type_get_type_detect_alias(type) == TYPE_ENCAPSULATED_UNION) + { + if (!type->name) ++ { + type->name = gen_name(); ++ /* the generated name will be used and this typedef excluded from the ++ * built typelib unless the typedef has the 'public' attribute, so add it here */ ++ if (do_typelib && !is_attr(attrs, ATTR_PUBLIC)) ++ attrs = append_attr(attrs, make_attr(ATTR_PUBLIC)); ++ } + + /* replace existing attributes when generating a typelib */ + if (do_typelib) +@@ -2005,12 +2098,12 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at + * for cleaner solution. + */ + if (cur && input_name == cur->loc_info.input_name) +- error_loc("%s: redefinition error; original definition was at %s:%d\n", ++ error_loc("FOO %s: redefinition error; original definition was at %s:%d\n", + cur->name, cur->loc_info.input_name, + cur->loc_info.line_number); + + name = declare_var(attrs, decl_spec, decl, 0); +- cur = type_new_alias(name->type, name->name); ++ cur = type_new_alias(&name->declspec, name->name); + cur->attrs = attrs; + + if (is_incomplete(cur)) +@@ -2025,6 +2118,8 @@ type_t *find_type(const char *name, struct namespace *namespace, int t) + { + struct rtype *cur; + ++ printf("find_type { name : %s, namespace %s, type : %s }\n", name, namespace ? namespace->name : NULL, ts_to_str(t)); ++ + if(namespace && namespace != &global_namespace) { + for(cur = namespace->type_hash[hash_ident(name)]; cur; cur = cur->next) { + if(cur->t == t && !strcmp(cur->name, name)) +@@ -2178,7 +2273,6 @@ struct allowed_attr allowed_attr[] = + /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" }, + /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, + /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, +- /* ATTR_CONST */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" }, + /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, + /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, + /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, +@@ -2213,7 +2307,6 @@ struct allowed_attr allowed_attr[] = + /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, + /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, + /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, +- /* ATTR_INLINE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" }, + /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, + /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" }, + /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" }, +@@ -2285,10 +2378,10 @@ static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs) + if (attr->type == ATTR_IMPLICIT_HANDLE) + { + const var_t *var = attr->u.pval; +- if (type_get_type( var->type) == TYPE_BASIC && +- type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) ++ if (type_get_type( var->declspec.type) == TYPE_BASIC && ++ type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE) + continue; +- if (is_aliaschain_attr( var->type, ATTR_HANDLE )) ++ if (is_aliaschain_attr( var->declspec.type, ATTR_HANDLE )) + continue; + error_loc("attribute %s requires a handle type in interface %s\n", + allowed_attr[attr->type].display_name, name); +@@ -2493,7 +2586,7 @@ static int is_ptr_guid_type(const type_t *type) + + /* second, make sure it is a pointer to something of size sizeof(GUID), + * i.e. 16 bytes */ +- return (type_memsize(type_pointer_get_ref(type)) == 16); ++ return (type_memsize(type_pointer_get_ref_type(type)) == 16); + } + + static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list) +@@ -2520,7 +2613,7 @@ static void check_remoting_fields(const var_t *var, type_t *type); + static void check_field_common(const type_t *container_type, + const char *container_name, const var_t *arg) + { +- type_t *type = arg->type; ++ type_t *type = arg->declspec.type; + int more_to_do; + const char *container_type_name; + const char *var_type; +@@ -2550,7 +2643,7 @@ static void check_field_common(const type_t *container_type, + } + + if (is_attr(arg->attrs, ATTR_LENGTHIS) && +- (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->type, ATTR_STRING))) ++ (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->declspec.type, ATTR_STRING))) + error_loc_info(&arg->loc_info, + "string and length_is specified for argument %s are mutually exclusive attributes\n", + arg->name); +@@ -2647,23 +2740,28 @@ static void check_field_common(const type_t *container_type, + { + const type_t *t = type; + while (is_ptr(t)) +- t = type_pointer_get_ref(t); ++ t = type_pointer_get_ref_type(t); + if (is_aliaschain_attr(t, ATTR_RANGE)) + warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name); + break; + } + case TGT_POINTER: +- type = type_pointer_get_ref(type); ++ type = type_pointer_get_ref_type(type); + more_to_do = TRUE; + break; + case TGT_ARRAY: +- type = type_array_get_element(type); ++ type = type_array_get_element_type(type); + more_to_do = TRUE; + break; ++ case TGT_ENUM: ++ type = type_get_real_type(type); ++ if(!type_is_complete(type)) ++ { ++ error_loc_info(&arg->loc_info, "undefined type declaration enum %s\n", type->name); ++ } + case TGT_USER_TYPE: + case TGT_IFACE_POINTER: + case TGT_BASIC: +- case TGT_ENUM: + case TGT_RANGE: + /* nothing to do */ + break; +@@ -2688,13 +2786,18 @@ static void check_remoting_fields(const var_t *var, type_t *type) + if (type_is_complete(type)) + fields = type_struct_get_fields(type); + else +- error_loc_info(&var->loc_info, "undefined type declaration %s\n", type->name); ++ error_loc_info(&var->loc_info, "undefined type declaration struct %s\n", type->name); + } + else if (type_get_type(type) == TYPE_UNION || type_get_type(type) == TYPE_ENCAPSULATED_UNION) +- fields = type_union_get_cases(type); ++ { ++ if (type_is_complete(type)) ++ fields = type_union_get_cases(type); ++ else ++ error_loc_info(&var->loc_info, "undefined type declaration union %s\n", type->name); ++ } + + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) +- if (field->type) check_field_common(type, type->name, field); ++ if (field->declspec.type) check_field_common(type, type->name, field); + } + + /* checks that arguments for a function make sense for marshalling and unmarshalling */ +@@ -2703,9 +2806,10 @@ static void check_remoting_args(const var_t *func) + const char *funcname = func->name; + const var_t *arg; + +- if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry ) ++ assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION); ++ if (func->declspec.type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->declspec.type->details.function->args, const var_t, entry ) + { +- const type_t *type = arg->type; ++ const type_t *type = arg->declspec.type; + + /* check that [out] parameters have enough pointer levels */ + if (is_attr(arg->attrs, ATTR_OUT)) +@@ -2745,16 +2849,16 @@ static void check_remoting_args(const var_t *func) + } + } + +- check_field_common(func->type, funcname, arg); ++ check_field_common(func->declspec.type, funcname, arg); + } + +- if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID) ++ if (type_get_type(type_function_get_rettype(func->declspec.type)) != TYPE_VOID) + { + var_t var; + var = *func; +- var.type = type_function_get_rettype(func->type); ++ var.declspec.type = type_function_get_rettype(func->declspec.type); + var.name = xstrdup("return value"); +- check_field_common(func->type, funcname, &var); ++ check_field_common(func->declspec.type, funcname, &var); + free(var.name); + } + } +@@ -2771,8 +2875,8 @@ static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func) + * function */ + var_t *idl_handle = make_var(xstrdup("IDL_handle")); + idl_handle->attrs = append_attr(NULL, make_attr(ATTR_IN)); +- idl_handle->type = find_type_or_error("handle_t", 0); +- type_function_add_head_arg(func->type, idl_handle); ++ idl_handle->declspec.type = find_type_or_error("handle_t", 0); ++ type_function_add_head_arg(func->declspec.type, idl_handle); + } + } + +@@ -2837,6 +2941,7 @@ static void check_async_uuid(type_t *iface) + type_t *async_iface; + type_t *inherit; + ++ assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE); + if (!is_attr(iface->attrs, ATTR_ASYNCUUID)) return; + + inherit = iface->details.iface->inherit; +@@ -2853,7 +2958,8 @@ static void check_async_uuid(type_t *iface) + var_t *begin_func, *finish_func, *func = stmt->u.var, *arg; + var_list_t *begin_args = NULL, *finish_args = NULL, *args; + +- args = func->type->details.function->args; ++ assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION); ++ args = func->declspec.type->details.function->args; + if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry) + { + if (is_attr(arg->attrs, ATTR_IN) || !is_attr(arg->attrs, ATTR_OUT)) +@@ -2863,15 +2969,15 @@ static void check_async_uuid(type_t *iface) + } + + begin_func = copy_var(func, concat_str("Begin_", func->name), NULL); +- begin_func->type = type_new_function(begin_args); +- begin_func->type->attrs = func->attrs; +- begin_func->type->details.function->retval = func->type->details.function->retval; ++ begin_func->declspec.type = type_new_function(begin_args); ++ begin_func->declspec.type->attrs = func->attrs; ++ begin_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval; + stmts = append_statement(stmts, make_statement_declaration(begin_func)); + + finish_func = copy_var(func, concat_str("Finish_", func->name), NULL); +- finish_func->type = type_new_function(finish_args); +- finish_func->type->attrs = func->attrs; +- finish_func->type->details.function->retval = func->type->details.function->retval; ++ finish_func->declspec.type = type_new_function(finish_args); ++ finish_func->declspec.type->attrs = func->attrs; ++ finish_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval; + stmts = append_statement(stmts, make_statement_declaration(finish_func)); + } + +@@ -2911,6 +3017,7 @@ static void check_statements(const statement_list_t *stmts, int is_inside_librar + static void check_all_user_types(const statement_list_t *stmts) + { + const statement_t *stmt; ++ const var_t *v; + + if (stmts) LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry) + { +@@ -2922,7 +3029,11 @@ static void check_all_user_types(const statement_list_t *stmts) + const statement_t *stmt_func; + STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) { + const var_t *func = stmt_func->u.var; +- check_for_additional_prototype_types(func->type->details.function->args); ++ assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION); ++ if (func->declspec.type->details.function->args) ++ LIST_FOR_EACH_ENTRY( v, func->declspec.type->details.function->args, const var_t, entry ) ++ check_for_additional_prototype_types(v->declspec.type); ++ check_for_additional_prototype_types(type_function_get_rettype(func->declspec.type)); + } + } + } +@@ -2956,6 +3067,10 @@ static statement_t *make_statement_type_decl(type_t *type) + { + statement_t *stmt = make_statement(STMT_TYPE); + stmt->u.type = type; ++ if (type_is_defined(type)) ++ { ++ stmt->declonly = FALSE; ++ } + return stmt; + } + +@@ -2970,16 +3085,16 @@ static statement_t *make_statement_declaration(var_t *var) + { + statement_t *stmt = make_statement(STMT_DECLARATION); + stmt->u.var = var; +- if (var->stgclass == STG_EXTERN && var->eval) ++ if (var->declspec.stgclass == STG_EXTERN && var->eval) + warning("'%s' initialised and declared extern\n", var->name); + if (is_const_decl(var)) + { + if (var->eval) + reg_const(var); + } +- else if (type_get_type(var->type) == TYPE_FUNCTION) ++ else if (type_get_type(var->declspec.type) == TYPE_FUNCTION) + check_function_attrs(var->name, var->attrs); +- else if (var->stgclass == STG_NONE || var->stgclass == STG_REGISTER) ++ else if (var->declspec.stgclass == STG_NONE || var->declspec.stgclass == STG_REGISTER) + error_loc("instantiation of data is illegal\n"); + return stmt; + } +@@ -3031,6 +3146,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) + declarator_t *decl, *next; + statement_t *stmt; + type_list_t **type_list; ++ int defined = TRUE; + + if (!decls) return NULL; + +@@ -3042,6 +3158,18 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) + { + var_t *var = decl->var; + type_t *type = find_type_or_error(var->name, 0); ++ ++ /* ensure that all of the types in this typedef statement have been defined ++ * before setting its declonly flag */ ++ if (type_is_pointerish(type)) ++ { ++ defined = defined & type_is_defined(type_get_pointer_chain_tail(type)); ++ } ++ else ++ { ++ defined = defined & type_is_defined(type_get_real_type(type)); ++ } ++ + *type_list = xmalloc(sizeof(type_list_t)); + (*type_list)->type = type; + (*type_list)->next = NULL; +@@ -3051,6 +3179,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) + free(var); + } + ++ stmt->declonly = !defined; + return stmt; + } + +@@ -3091,7 +3220,7 @@ void init_loc_info(loc_info_t *i) + + static void check_def(const type_t *t) + { +- if (t->defined) +- error_loc("%s: redefinition error; original definition was at %s:%d\n", ++ if (type_is_defined(t)) ++ error_loc("BAR %s: redefinition error; original definition was at %s:%d\n", + t->name, t->loc_info.input_name, t->loc_info.line_number); + } +diff --git a/mingw-w64-tools/widl/src/parser.yy.c b/mingw-w64-tools/widl/src/parser.yy.c +index 2aaf3c27..0482aa7e 100644 +--- a/mingw-w64-tools/widl/src/parser.yy.c ++++ b/mingw-w64-tools/widl/src/parser.yy.c +@@ -1,6 +1,6 @@ +-#line 1 "parser.yy.c" ++#line 2 "parser.yy.c" + +-#line 3 "parser.yy.c" ++#line 4 "parser.yy.c" + + #define YY_INT_ALIGNED short int + +@@ -1041,13 +1041,13 @@ UUID *parse_uuid(const char *u) + return uuid; + } + +-#line 1044 "parser.yy.c" ++#line 1045 "parser.yy.c" + /* + ************************************************************************** + * The flexer starts here + ************************************************************************** + */ +-#line 1050 "parser.yy.c" ++#line 1051 "parser.yy.c" + + #define INITIAL 0 + #define QUOTE 1 +@@ -1281,7 +1281,7 @@ YY_DECL + { + #line 132 "parser.l" + +-#line 1284 "parser.yy.c" ++#line 1285 "parser.yy.c" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { +@@ -1616,7 +1616,7 @@ YY_RULE_SETUP + #line 239 "parser.l" + ECHO; + YY_BREAK +-#line 1619 "parser.yy.c" ++#line 1620 "parser.yy.c" + + case YY_END_OF_BUFFER: + { +diff --git a/mingw-w64-tools/widl/src/proxy.c b/mingw-w64-tools/widl/src/proxy.c +index 87c27be9..36b552be 100644 +--- a/mingw-w64-tools/widl/src/proxy.c ++++ b/mingw-w64-tools/widl/src/proxy.c +@@ -67,7 +67,7 @@ static void write_stubdesc(int expr_eval_routines) + print_proxy( "1, /* -error bounds_check flag */\n"); + print_proxy( "0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); + print_proxy( "0,\n"); +- print_proxy( "0x50100a4, /* MIDL Version 5.1.164 */\n"); ++ print_proxy( "0x50200ca, /* MIDL Version 5.2.202 */\n"); + print_proxy( "0,\n"); + print_proxy("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); + print_proxy( "0, /* notify & notify_flag routine table */\n"); +@@ -105,15 +105,15 @@ static void clear_output_vars( const var_list_t *args ) + { + if (is_attr(arg->attrs, ATTR_IN)) continue; + if (!is_attr(arg->attrs, ATTR_OUT)) continue; +- if (is_ptr(arg->type)) ++ if (is_ptr(arg->declspec.type)) + { +- if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_BASIC) continue; +- if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_ENUM) continue; ++ if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_BASIC) continue; ++ if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_ENUM) continue; + } + print_proxy( "if (%s) MIDL_memset( %s, 0, ", arg->name, arg->name ); +- if (is_array(arg->type) && type_array_has_conformance(arg->type)) ++ if (is_array(arg->declspec.type) && type_array_has_conformance(arg->declspec.type)) + { +- write_expr( proxy, type_array_get_conformance(arg->type), 1, 1, NULL, NULL, "" ); ++ write_expr( proxy, type_array_get_conformance(arg->declspec.type), 1, 1, NULL, NULL, "" ); + fprintf( proxy, " * " ); + } + fprintf( proxy, "sizeof( *%s ));\n", arg->name ); +@@ -147,7 +147,7 @@ static int need_delegation_indirect(const type_t *iface) + static void free_variable( const var_t *arg, const char *local_var_prefix ) + { + unsigned int type_offset = arg->typestring_offset; +- type_t *type = arg->type; ++ type_t *type = arg->declspec.type; + + write_parameter_conf_or_var_exprs(proxy, indent, local_var_prefix, PHASE_FREE, arg, FALSE); + +@@ -191,18 +191,18 @@ static void proxy_free_variables( var_list_t *args, const char *local_var_prefix + static void gen_proxy(type_t *iface, const var_t *func, int idx, + unsigned int proc_offset) + { +- var_t *retval = type_function_get_retval(func->type); +- int has_ret = !is_void(retval->type); ++ var_t *retval = type_function_get_retval(func->declspec.type); ++ int has_ret = !is_void(retval->declspec.type); + int has_full_pointer = is_full_pointer_function(func); +- const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); +- const var_list_t *args = type_get_function_args(func->type); ++ const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); ++ const var_list_t *args = type_function_get_args(func->declspec.type); + if (!callconv) callconv = "STDMETHODCALLTYPE"; + + indent = 0; + if (is_interpreted_func( iface, func )) + { + if (get_stub_mode() == MODE_Oif && !is_callas( func->attrs )) return; +- write_type_decl_left(proxy, retval->type); ++ write_declspec_decl_left(proxy, &retval->declspec); + print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); + write_args(proxy, args, iface->name, 1, TRUE); + print_proxy( ")\n"); +@@ -219,7 +219,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, + print_proxy( "}\n"); + print_proxy( "\n"); + +- write_type_decl_left(proxy, retval->type); ++ write_declspec_decl_left(proxy, &retval->declspec); + print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); + write_args(proxy, args, iface->name, 1, TRUE); + print_proxy( ")\n"); +@@ -229,12 +229,12 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, + /* local variables */ + if (has_ret) { + print_proxy( "%s", "" ); +- write_type_decl(proxy, retval->type, retval->name); ++ write_declspec_decl(proxy, &retval->declspec, retval->name); + fprintf( proxy, ";\n" ); + } + print_proxy( "RPC_MESSAGE _RpcMessage;\n" ); + if (has_ret) { +- if (decl_indirect(retval->type)) ++ if (decl_indirect(retval->declspec.type)) + print_proxy("void *_p_%s = &%s;\n", retval->name, retval->name); + } + print_proxy( "\n"); +@@ -246,7 +246,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, + write_full_pointer_init(proxy, indent, func, FALSE); + + /* FIXME: trace */ +- clear_output_vars( type_get_function_args(func->type) ); ++ clear_output_vars( type_function_get_args(func->declspec.type) ); + + print_proxy( "RpcTryExcept\n" ); + print_proxy( "{\n" ); +@@ -279,9 +279,9 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, + + if (has_ret) + { +- if (decl_indirect(retval->type)) ++ if (decl_indirect(retval->declspec.type)) + print_proxy("MIDL_memset(&%s, 0, sizeof(%s));\n", retval->name, retval->name); +- else if (is_ptr(retval->type) || is_array(retval->type)) ++ else if (is_ptr(retval->declspec.type) || is_array(retval->declspec.type)) + print_proxy("%s = 0;\n", retval->name); + write_remoting_arguments(proxy, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL); + } +@@ -301,7 +301,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, + print_proxy( "{\n" ); + if (has_ret) { + indent++; +- proxy_free_variables( type_get_function_args(func->type), "" ); ++ proxy_free_variables( type_function_get_args(func->declspec.type), "" ); + print_proxy( "_RetVal = NdrProxyErrorHandler(RpcExceptionCode());\n" ); + indent--; + } +@@ -320,7 +320,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, + unsigned int proc_offset) + { + const var_t *arg; +- int has_ret = !is_void(type_function_get_rettype(func->type)); ++ int has_ret = !is_void(type_function_get_rettype(func->declspec.type)); + int has_full_pointer = is_full_pointer_function(func); + + if (is_interpreted_func( iface, func )) return; +@@ -389,10 +389,10 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, + else fprintf(proxy, "__frame->_This->lpVtbl->%s", get_name(func)); + fprintf(proxy, "(__frame->_This"); + +- if (type_get_function_args(func->type)) ++ if (type_function_get_args(func->declspec.type)) + { +- LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) +- fprintf(proxy, ", %s__frame->%s", is_array(arg->type) && !type_array_is_decl_as_ptr(arg->type) ? "*" :"" , arg->name); ++ LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) ++ fprintf(proxy, ", %s__frame->%s", is_array(arg->declspec.type) && !type_array_is_decl_as_ptr(arg->declspec.type) ? "*" :"" , arg->name); + } + fprintf(proxy, ");\n"); + fprintf(proxy, "\n"); +@@ -401,7 +401,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, + + write_remoting_arguments(proxy, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE); + +- if (!is_void(type_function_get_rettype(func->type))) ++ if (!is_void(type_function_get_rettype(func->declspec.type))) + write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE); + + print_proxy("NdrStubGetBuffer(This, _pRpcChannelBuffer, &__frame->_StubMsg);\n"); +@@ -410,7 +410,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, + fprintf(proxy, "\n"); + + /* marshall the return value */ +- if (!is_void(type_function_get_rettype(func->type))) ++ if (!is_void(type_function_get_rettype(func->declspec.type))) + write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL); + + indent--; +@@ -432,16 +432,16 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, + + static void gen_stub_thunk( type_t *iface, const var_t *func, unsigned int proc_offset ) + { +- int has_ret = !is_void( type_function_get_rettype( func->type )); ++ int has_ret = !is_void( type_function_get_rettype( func->declspec.type )); + const var_t *arg, *callas = is_callas( func->attrs ); +- const var_list_t *args = type_get_function_args( func->type ); ++ const var_list_t *args = type_function_get_args( func->declspec.type ); + + indent = 0; + print_proxy( "void __RPC_API %s_%s_Thunk( PMIDL_STUB_MESSAGE pStubMsg )\n", + iface->name, get_name(func) ); + print_proxy( "{\n"); + indent++; +- write_func_param_struct( proxy, iface, func->type, ++ write_func_param_struct( proxy, iface, func->declspec.type, + "*pParamStruct = (struct _PARAM_STRUCT *)pStubMsg->StackTop", has_ret ); + print_proxy( "%s%s_%s_Stub( pParamStruct->This", + has_ret ? "pParamStruct->_RetVal = " : "", iface->name, callas->name ); +@@ -526,6 +526,7 @@ static int write_proxy_methods(type_t *iface, int skip) + if (skip || (is_local(func->attrs) && !get_callas_source(iface, func))) + print_proxy( "0, /* %s::%s */\n", iface->name, get_name(func)); + else if (is_interpreted_func( iface, func ) && ++ get_stub_mode() == MODE_Oif && + !is_local( func->attrs ) && + type_iface_get_inherit(iface)) + print_proxy( "(void *)-1, /* %s::%s */\n", iface->name, get_name(func)); +@@ -613,14 +614,14 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) + if (!is_local(func->attrs)) { + const var_t *cas = is_callas(func->attrs); + const char *cname = cas ? cas->name : NULL; +- int idx = func->type->details.function->idx; ++ int idx = type_get_details(func->declspec.type)->function->idx; + if (cname) { + const statement_t *stmt2; + STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) { + const var_t *m = stmt2->u.var; + if (!strcmp(m->name, cname)) + { +- idx = m->type->details.function->idx; ++ idx = type_get_details(m->declspec.type)->function->idx; + break; + } + } +@@ -738,7 +739,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) + print_proxy( "{\n"); + indent++; + print_proxy( "%s_%s\n", +- iface->details.iface->async_iface == iface ? "CStdAsyncStubBuffer" : "CStdStubBuffer", ++ type_get_details(iface)->iface->async_iface == iface ? "CStdAsyncStubBuffer" : "CStdStubBuffer", + need_delegation_indirect(iface) ? "DELEGATING_METHODS" : "METHODS"); + indent--; + print_proxy( "}\n"); +@@ -839,8 +840,8 @@ static void write_proxy_stmts(const statement_list_t *stmts, unsigned int *proc_ + if (need_proxy(iface)) + { + write_proxy(iface, proc_offset); +- if (iface->details.iface->async_iface) +- write_proxy(iface->details.iface->async_iface, proc_offset); ++ if (type_get_details(iface)->iface->async_iface) ++ write_proxy(type_get_details(iface)->iface->async_iface, proc_offset); + } + } + } +@@ -869,9 +870,9 @@ static void build_iface_list( const statement_list_t *stmts, type_t **ifaces[], + { + *ifaces = xrealloc( *ifaces, (*count + 1) * sizeof(**ifaces) ); + (*ifaces)[(*count)++] = iface; +- if (iface->details.iface->async_iface) ++ if (type_get_details(iface)->iface->async_iface) + { +- iface = iface->details.iface->async_iface; ++ iface = type_get_details(iface)->iface->async_iface; + *ifaces = xrealloc( *ifaces, (*count + 1) * sizeof(**ifaces) ); + (*ifaces)[(*count)++] = iface; + } +@@ -942,7 +943,7 @@ static void write_proxy_routines(const statement_list_t *stmts) + write_stubdesc(expr_eval_routines); + + print_proxy( "#if !defined(__RPC_WIN%u__)\n", pointer_size == 8 ? 64 : 32); +- print_proxy( "#error Currently only Wine and WIN32 are supported.\n"); ++ print_proxy( "#error Invalid build platform for this proxy.\n"); + print_proxy( "#endif\n"); + print_proxy( "\n"); + write_procformatstring(proxy, stmts, need_proxy); +@@ -1011,7 +1012,7 @@ static void write_proxy_routines(const statement_list_t *stmts) + table_version = get_stub_mode() == MODE_Oif ? 2 : 1; + for (i = 0; i < count; i++) + { +- if (interfaces[i]->details.iface->async_iface != interfaces[i]) continue; ++ if (type_get_details(interfaces[i])->iface->async_iface != interfaces[i]) continue; + if (table_version != 6) + { + fprintf(proxy, "static const IID *_AsyncInterfaceTable[] =\n"); +@@ -1053,26 +1054,6 @@ void write_proxies(const statement_list_t *stmts) + init_proxy(stmts); + if(!proxy) return; + +- if (do_win32 && do_win64) +- { +- fprintf(proxy, "\n#ifndef _WIN64\n\n"); +- pointer_size = 4; +- write_proxy_routines( stmts ); +- fprintf(proxy, "\n#else /* _WIN64 */\n\n"); +- pointer_size = 8; +- write_proxy_routines( stmts ); +- fprintf(proxy, "\n#endif /* _WIN64 */\n"); +- } +- else if (do_win32) +- { +- pointer_size = 4; +- write_proxy_routines( stmts ); +- } +- else if (do_win64) +- { +- pointer_size = 8; +- write_proxy_routines( stmts ); +- } +- ++ write_proxy_routines( stmts ); + fclose(proxy); + } +diff --git a/mingw-w64-tools/widl/src/register.c b/mingw-w64-tools/widl/src/register.c +index 210fb747..1c369e7c 100644 +--- a/mingw-w64-tools/widl/src/register.c ++++ b/mingw-w64-tools/widl/src/register.c +@@ -325,7 +325,7 @@ void output_typelib_regscript( const typelib_t *typelib ) + sprintf(resname, "%s\%d", typelib_name, expr->cval); + } + put_str( indent, "'%x' { %s = s '%%MODULE%%%s' }\n", +- lcid_expr ? lcid_expr->cval : 0, typelib_kind == SYS_WIN64 ? "win64" : "win32", id_part ); ++ lcid_expr ? lcid_expr->cval : 0, pointer_size == 8 ? "win64" : "win32", id_part ); + put_str( indent, "FLAGS = s '%u'\n", flags ); + put_str( --indent, "}\n" ); + put_str( --indent, "}\n" ); +diff --git a/mingw-w64-tools/widl/src/server.c b/mingw-w64-tools/widl/src/server.c +index 783ff900..dbed870a 100644 +--- a/mingw-w64-tools/widl/src/server.c ++++ b/mingw-w64-tools/widl/src/server.c +@@ -55,6 +55,8 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned + unsigned char explicit_fc, implicit_fc; + int has_full_pointer = is_full_pointer_function(func); + const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); ++ const decl_spec_t *ret_declspec = type_function_get_retdeclspec(func->declspec.type); ++ type_t *ret_type = ret_declspec->type; + + if (is_interpreted_func( iface, func )) return; + +@@ -75,7 +77,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned + indent++; + write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_FREE); + +- if (!is_void(type_function_get_rettype(func->type))) ++ if (!is_void(ret_type)) + write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_FREE); + + if (has_full_pointer) +@@ -120,7 +122,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned + if (has_full_pointer) + write_full_pointer_init(server, indent, func, TRUE); + +- if (type_get_function_args(func->type)) ++ if (type_function_get_args(func->declspec.type)) + { + print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); + indent++; +@@ -154,35 +156,42 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned + assign_stub_out_args(server, indent, func, "__frame->"); + + /* Call the real server function */ +- print_server("%s%s%s", +- is_void(type_function_get_rettype(func->type)) ? "" : "__frame->_RetVal = ", +- prefix_server, get_name(func)); ++ if (is_context_handle(ret_type)) ++ { ++ print_server("__frame->_RetVal = NDRSContextUnmarshall((char*)0, _pRpcMessage->DataRepresentation);\n"); ++ print_server("*(("); ++ write_declspec_decl(server, ret_declspec, NULL); ++ fprintf(server, "*)NDRSContextValue(__frame->_RetVal)) = "); ++ } ++ else ++ print_server("%s", is_void(ret_type) ? "" : "__frame->_RetVal = "); ++ fprintf(server, "%s%s", prefix_server, get_name(func)); + +- if (type_get_function_args(func->type)) ++ if (type_function_get_args(func->declspec.type)) + { + int first_arg = 1; + + fprintf(server, "(\n"); + indent++; +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + { + if (first_arg) + first_arg = 0; + else + fprintf(server, ",\n"); +- if (is_context_handle(var->type)) ++ if (is_context_handle(var->declspec.type)) + { + /* if the context_handle attribute appears in the chain of types + * without pointers being followed, then the context handle must + * be direct, otherwise it is a pointer */ +- const char *ch_ptr = is_aliaschain_attr(var->type, ATTR_CONTEXTHANDLE) ? "*" : ""; ++ const char *ch_ptr = is_aliaschain_attr(var->declspec.type, ATTR_CONTEXTHANDLE) ? "*" : ""; + print_server("("); +- write_type_decl_left(server, var->type); ++ write_declspec_decl_left(server, &var->declspec); + fprintf(server, ")%sNDRSContextValue(__frame->%s)", ch_ptr, var->name); + } + else + { +- print_server("%s__frame->%s", is_array(var->type) && !type_array_is_decl_as_ptr(var->type) ? "*" : "", var->name); ++ print_server("%s__frame->%s", is_array(var->declspec.type) && !type_array_is_decl_as_ptr(var->declspec.type) ? "*" : "", var->name); + } + } + fprintf(server, ");\n"); +@@ -197,7 +206,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned + { + write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE); + +- if (!is_void(type_function_get_rettype(func->type))) ++ if (!is_void(ret_type)) + write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE); + + print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.BufferLength;\n"); +@@ -216,7 +225,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned + write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_MARSHAL); + + /* marshall the return value */ +- if (!is_void(type_function_get_rettype(func->type))) ++ if (!is_void(ret_type)) + write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL); + + indent--; +@@ -378,7 +387,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines) + print_server("1, /* -error bounds_check flag */\n"); + print_server("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); + print_server("0,\n"); +- print_server("0x50100a4, /* MIDL Version 5.1.164 */\n"); ++ print_server("0x50200ca, /* MIDL Version 5.2.202 */\n"); + print_server("0,\n"); + print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); + print_server("0, /* notify & notify_flag routine table */\n"); +@@ -544,26 +553,6 @@ void write_server(const statement_list_t *stmts) + if (!server) + return; + +- if (do_win32 && do_win64) +- { +- fprintf(server, "#ifndef _WIN64\n\n"); +- pointer_size = 4; +- write_server_routines( stmts ); +- fprintf(server, "\n#else /* _WIN64 */\n\n"); +- pointer_size = 8; +- write_server_routines( stmts ); +- fprintf(server, "\n#endif /* _WIN64 */\n"); +- } +- else if (do_win32) +- { +- pointer_size = 4; +- write_server_routines( stmts ); +- } +- else if (do_win64) +- { +- pointer_size = 8; +- write_server_routines( stmts ); +- } +- ++ write_server_routines( stmts ); + fclose(server); + } +diff --git a/mingw-w64-tools/widl/src/typegen.c b/mingw-w64-tools/widl/src/typegen.c +index 27ba60fc..eebb99f0 100644 +--- a/mingw-w64-tools/widl/src/typegen.c ++++ b/mingw-w64-tools/widl/src/typegen.c +@@ -67,6 +67,7 @@ enum type_context + TYPE_CONTEXT_PARAM, + TYPE_CONTEXT_CONTAINER, + TYPE_CONTEXT_CONTAINER_NO_POINTERS, ++ TYPE_CONTEXT_RETVAL, + }; + + /* parameter flags in Oif mode */ +@@ -84,14 +85,14 @@ static const unsigned short IsSimpleRef = 0x0100; + + static unsigned int field_memsize(const type_t *type, unsigned int *offset); + static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align); +-static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type, ++static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + const char *name, unsigned int *typestring_offset); +-static unsigned int write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff); +-static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, ++static unsigned int write_struct_tfs(FILE *file, const decl_spec_t *declspec, const char *name, unsigned int *tfsoff); ++static int write_embedded_types(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + const char *name, int write_ptr, unsigned int *tfsoff); + static const var_t *find_array_or_string_in_struct(const type_t *type); + static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, +- type_t *type, enum type_context context, ++ const decl_spec_t *declspec, enum type_context context, + const char *name, unsigned int *typestring_offset); + static unsigned int get_required_buffer_size_type( const type_t *type, const char *name, + const attr_list_t *attrs, int toplevel_param, +@@ -196,7 +197,7 @@ static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr) + if (is_attr(t->attrs, attr)) + return get_attrp(t->attrs, attr); + else if (type_is_alias(t)) +- t = type_alias_get_aliasee(t); ++ t = type_alias_get_aliasee_type(t); + else return NULL; + } + } +@@ -266,7 +267,7 @@ unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int t + if (pointer_type) + return pointer_type; + +- for (t = type; type_is_alias(t); t = type_alias_get_aliasee(t)) ++ for (t = type; type_is_alias(t); t = type_alias_get_aliasee_type(t)) + { + pointer_type = get_attrv(t->attrs, ATTR_POINTERTYPE); + if (pointer_type) +@@ -287,7 +288,7 @@ static unsigned char get_pointer_fc_context( const type_t *type, const attr_list + int pointer_fc = get_pointer_fc(type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM); + + if (pointer_fc == FC_UP && is_attr( attrs, ATTR_OUT ) && +- context == TYPE_CONTEXT_PARAM && is_object( current_iface )) ++ (context == TYPE_CONTEXT_PARAM || context == TYPE_CONTEXT_RETVAL) && is_object( current_iface )) + pointer_fc = FC_OP; + + return pointer_fc; +@@ -315,7 +316,7 @@ static type_t *get_user_type(const type_t *t, const char **pname) + } + + if (type_is_alias(t)) +- t = type_alias_get_aliasee(t); ++ t = type_alias_get_aliasee_type(t); + else + return NULL; + } +@@ -350,10 +351,10 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + return TGT_RANGE; + return TGT_ENUM; + case TYPE_POINTER: +- if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE || +- (type_get_type(type_pointer_get_ref(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) ++ if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || ++ (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) + return TGT_IFACE_POINTER; +- else if (is_aliaschain_attr(type_pointer_get_ref(type), ATTR_CONTEXTHANDLE)) ++ else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE)) + return TGT_CTXT_HANDLE_POINTER; + else + return TGT_POINTER; +@@ -378,13 +379,13 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att + + static int cant_be_null(const var_t *v) + { +- switch (typegen_detect_type(v->type, v->attrs, TDT_IGNORE_STRINGS)) ++ switch (typegen_detect_type(v->declspec.type, v->attrs, TDT_IGNORE_STRINGS)) + { + case TGT_ARRAY: +- if (!type_array_is_decl_as_ptr( v->type )) return 0; ++ if (!type_array_is_decl_as_ptr( v->declspec.type )) return 0; + /* fall through */ + case TGT_POINTER: +- return (get_pointer_fc(v->type, v->attrs, TRUE) == FC_RP); ++ return (get_pointer_fc(v->declspec.type, v->attrs, TRUE) == FC_RP); + case TGT_CTXT_HANDLE_POINTER: + return TRUE; + default: +@@ -404,7 +405,7 @@ static int get_padding(const var_list_t *fields) + + LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) + { +- type_t *ft = f->type; ++ type_t *ft = f->declspec.type; + unsigned int align = 0; + unsigned int size = type_memsize_and_alignment(ft, &align); + align = clamp_align(align); +@@ -421,7 +422,7 @@ static unsigned int get_stack_size( const var_t *var, int *by_value ) + unsigned int stack_size; + int by_val; + +- switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES )) ++ switch (typegen_detect_type( var->declspec.type, var->attrs, TDT_ALL_TYPES )) + { + case TGT_BASIC: + case TGT_ENUM: +@@ -429,7 +430,7 @@ static unsigned int get_stack_size( const var_t *var, int *by_value ) + case TGT_STRUCT: + case TGT_UNION: + case TGT_USER_TYPE: +- stack_size = type_memsize( var->type ); ++ stack_size = type_memsize( var->declspec.type ); + by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */ + break; + default: +@@ -442,23 +443,27 @@ static unsigned int get_stack_size( const var_t *var, int *by_value ) + } + + static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs, +- const type_t *type ) ++ const type_t *type, int is_return ) + { + unsigned char flags = 0; ++ int is_out; + + if (is_attr(iface->attrs, ATTR_STRICTCONTEXTHANDLE)) flags |= NDR_STRICT_CONTEXT_HANDLE; + + if (is_ptr(type) && + !is_attr( type->attrs, ATTR_CONTEXTHANDLE ) && + !is_attr( attrs, ATTR_CONTEXTHANDLE )) +- flags |= 0x80; ++ flags |= HANDLE_PARAM_IS_VIA_PTR; + +- if (is_attr(attrs, ATTR_IN)) ++ if (is_return) return flags | HANDLE_PARAM_IS_OUT | HANDLE_PARAM_IS_RETURN; ++ ++ is_out = is_attr(attrs, ATTR_OUT); ++ if (is_attr(attrs, ATTR_IN) || !is_out) + { +- flags |= 0x40; +- if (!is_attr(attrs, ATTR_OUT)) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL; ++ flags |= HANDLE_PARAM_IS_IN; ++ if (!is_out) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL; + } +- if (is_attr(attrs, ATTR_OUT)) flags |= 0x20; ++ if (is_out) flags |= HANDLE_PARAM_IS_OUT; + + return flags; + } +@@ -490,14 +495,14 @@ unsigned char get_struct_fc(const type_t *type) + + if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry ) + { +- type_t *t = field->type; ++ type_t *t = field->declspec.type; + enum typegen_type typegen_type; + + typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); + + if (typegen_type == TGT_ARRAY && !type_array_is_decl_as_ptr(t)) + { +- if (is_string_type(field->attrs, field->type)) ++ if (is_string_type(field->attrs, field->declspec.type)) + { + if (is_conformant_array(t)) + has_conformance = 1; +@@ -505,10 +510,10 @@ unsigned char get_struct_fc(const type_t *type) + continue; + } + +- if (is_array(type_array_get_element(field->type))) ++ if (is_array(type_array_get_element_type(field->declspec.type))) + return FC_BOGUS_STRUCT; + +- if (type_array_has_conformance(field->type)) ++ if (type_array_has_conformance(field->declspec.type)) + { + has_conformance = 1; + if (list_next(fields, &field->entry)) +@@ -518,7 +523,7 @@ unsigned char get_struct_fc(const type_t *type) + if (type_array_has_variance(t)) + has_variance = 1; + +- t = type_array_get_element(t); ++ t = type_array_get_element_type(t); + typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); + } + +@@ -620,7 +625,7 @@ static unsigned char get_array_fc(const type_t *type) + const expr_t *size_is; + const type_t *elem_type; + +- elem_type = type_array_get_element(type); ++ elem_type = type_array_get_element_type(type); + size_is = type_array_get_conformance(type); + + if (!size_is) +@@ -709,14 +714,14 @@ static int type_has_pointers(const type_t *type) + case TGT_POINTER: + return TRUE; + case TGT_ARRAY: +- return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element(type)); ++ return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element_type(type)); + case TGT_STRUCT: + { + var_list_t *fields = type_struct_get_fields(type); + const var_t *field; + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + { +- if (type_has_pointers(field->type)) ++ if (type_has_pointers(field->declspec.type)) + return TRUE; + } + break; +@@ -728,7 +733,7 @@ static int type_has_pointers(const type_t *type) + fields = type_union_get_cases(type); + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + { +- if (field->type && type_has_pointers(field->type)) ++ if (field->declspec.type && type_has_pointers(field->declspec.type)) + return TRUE; + } + break; +@@ -763,14 +768,14 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, + if (get_pointer_fc(type, attrs, toplevel_param) == FC_FP) + return TRUE; + else +- return type_has_full_pointer(type_array_get_element(type), NULL, FALSE); ++ return type_has_full_pointer(type_array_get_element_type(type), NULL, FALSE); + case TGT_STRUCT: + { + var_list_t *fields = type_struct_get_fields(type); + const var_t *field; + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + { +- if (type_has_full_pointer(field->type, field->attrs, FALSE)) ++ if (type_has_full_pointer(field->declspec.type, field->attrs, FALSE)) + return TRUE; + } + break; +@@ -782,7 +787,7 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, + fields = type_union_get_cases(type); + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + { +- if (field->type && type_has_full_pointer(field->type, field->attrs, FALSE)) ++ if (field->declspec.type && type_has_full_pointer(field->declspec.type, field->attrs, FALSE)) + return TRUE; + } + break; +@@ -852,7 +857,7 @@ static const char *get_context_handle_type_name(const type_t *type) + const type_t *t; + for (t = type; + is_ptr(t) || type_is_alias(t); +- t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) ++ t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t)) + if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) + return t->name; + assert(0); +@@ -902,16 +907,16 @@ static void write_var_init(FILE *file, int indent, const type_t *t, const char * + + void write_parameters_init(FILE *file, int indent, const var_t *func, const char *local_var_prefix) + { +- const var_t *var = type_function_get_retval(func->type); ++ const var_t *var = type_function_get_retval(func->declspec.type); + +- if (!is_void(var->type)) +- write_var_init(file, indent, var->type, var->name, local_var_prefix); ++ if (!is_void(var->declspec.type)) ++ write_var_init(file, indent, var->declspec.type, var->name, local_var_prefix); + +- if (!type_get_function_args(func->type)) ++ if (!type_function_get_args(func->declspec.type)) + return; + +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) +- write_var_init(file, indent, var->type, var->name, local_var_prefix); ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) ++ write_var_init(file, indent, var->declspec.type, var->name, local_var_prefix); + + fprintf(file, "\n"); + } +@@ -975,14 +980,14 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned + if (is_out) *flags |= IsOut; + if (is_return) *flags |= IsReturn; + +- if (!is_string_type( var->attrs, var->type )) +- buffer_size = get_required_buffer_size_type( var->type, NULL, var->attrs, TRUE, &alignment ); ++ if (!is_string_type( var->attrs, var->declspec.type )) ++ buffer_size = get_required_buffer_size_type( var->declspec.type, NULL, var->attrs, TRUE, &alignment ); + +- switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES )) ++ switch (typegen_detect_type( var->declspec.type, var->attrs, TDT_ALL_TYPES )) + { + case TGT_BASIC: + *flags |= IsBasetype; +- fc = get_basic_fc_signed( var->type ); ++ fc = get_basic_fc_signed( var->declspec.type ); + if (fc == FC_BIND_PRIMITIVE) + { + buffer_size = 4; /* actually 0 but avoids setting MustSize */ +@@ -991,7 +996,7 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned + break; + case TGT_ENUM: + *flags |= IsBasetype; +- fc = get_enum_fc( var->type ); ++ fc = get_enum_fc( var->declspec.type ); + break; + case TGT_RANGE: + *flags |= IsByValue; +@@ -1006,19 +1011,19 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned + break; + case TGT_ARRAY: + *flags |= MustFree; +- if (type_array_is_decl_as_ptr(var->type) && var->type->details.array.ptr_tfsoff && +- get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP) ++ if (type_array_is_decl_as_ptr(var->declspec.type) && type_get_details(var->declspec.type)->array.ptr_tfsoff && ++ get_pointer_fc( var->declspec.type, var->attrs, !is_return ) == FC_RP) + { +- *typestring_offset = var->type->typestring_offset; ++ *typestring_offset = var->declspec.type->typestring_offset; + *flags |= IsSimpleRef; + } + break; + case TGT_STRING: + *flags |= MustFree; +- if (is_declptr( var->type ) && get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP) ++ if (is_declptr( var->declspec.type ) && get_pointer_fc( var->declspec.type, var->attrs, !is_return ) == FC_RP) + { + /* skip over pointer description straight to string description */ +- if (is_conformant_array( var->type )) *typestring_offset += 4; ++ if (is_conformant_array( var->declspec.type )) *typestring_offset += 4; + else *typestring_offset += 2; + *flags |= IsSimpleRef; + } +@@ -1031,9 +1036,9 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned + buffer_size = 20; + break; + case TGT_POINTER: +- if (get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP) ++ if (get_pointer_fc( var->declspec.type, var->attrs, !is_return ) == FC_RP) + { +- const type_t *ref = type_pointer_get_ref( var->type ); ++ const type_t *ref = type_pointer_get_ref_type( var->declspec.type ); + + if (!is_string_type( var->attrs, ref )) + buffer_size = get_required_buffer_size_type( ref, NULL, NULL, TRUE, &alignment ); +@@ -1059,11 +1064,19 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned + case TGT_UNION: + case TGT_USER_TYPE: + case TGT_RANGE: +- case TGT_ARRAY: +- *flags |= IsSimpleRef | MustFree; ++ *flags |= MustFree | IsSimpleRef; + *typestring_offset = ref->typestring_offset; + if (!is_in && is_out) server_size = type_memsize( ref ); + break; ++ case TGT_ARRAY: ++ *flags |= MustFree; ++ if (!type_array_is_decl_as_ptr(ref)) ++ { ++ *flags |= IsSimpleRef; ++ *typestring_offset = ref->typestring_offset; ++ } ++ if (!is_in && is_out) server_size = type_memsize( ref ); ++ break; + case TGT_STRING: + case TGT_POINTER: + case TGT_CTXT_HANDLE: +@@ -1115,8 +1128,8 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned + static unsigned char get_func_oi2_flags( const var_t *func ) + { + const var_t *var; +- var_list_t *args = type_get_function_args( func->type ); +- var_t *retval = type_function_get_retval( func->type ); ++ var_list_t *args = type_function_get_args( func->declspec.type ); ++ var_t *retval = type_function_get_retval( func->declspec.type ); + unsigned char oi2_flags = 0x40; /* HasExtensions */ + unsigned short flags; + unsigned int stack_size, typestring_offset; +@@ -1131,7 +1144,7 @@ static unsigned char get_func_oi2_flags( const var_t *func ) + } + } + +- if (!is_void( retval->type )) ++ if (!is_void( retval->declspec.type )) + { + oi2_flags |= 0x04; /* HasRet */ + get_parameter_fc( retval, 1, &flags, &stack_size, &typestring_offset ); +@@ -1185,8 +1198,8 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons + + if (!is_in && !is_out) is_in = TRUE; + +- if (type_get_type(var->type) == TYPE_BASIC || +- type_get_type(var->type) == TYPE_ENUM) ++ if (type_get_type(var->declspec.type) == TYPE_BASIC || ++ type_get_type(var->declspec.type) == TYPE_ENUM) + { + unsigned char fc; + +@@ -1195,13 +1208,13 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons + else + print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n"); + +- if (type_get_type(var->type) == TYPE_ENUM) ++ if (type_get_type(var->declspec.type) == TYPE_ENUM) + { +- fc = get_enum_fc(var->type); ++ fc = get_enum_fc(var->declspec.type); + } + else + { +- fc = get_basic_fc_signed(var->type); ++ fc = get_basic_fc_signed(var->declspec.type); + + if (fc == FC_BIND_PRIMITIVE) + fc = FC_IGNORE; +@@ -1215,10 +1228,12 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons + { + unsigned short offset = var->typestring_offset; + +- if (!is_interpreted && is_array(var->type) && +- type_array_is_decl_as_ptr(var->type) && +- var->type->details.array.ptr_tfsoff) +- offset = var->type->typestring_offset; ++ if (!is_interpreted && is_array(var->declspec.type) && ++ type_array_is_decl_as_ptr(var->declspec.type) && ++ type_get_details(var->declspec.type)->array.ptr_tfsoff) ++ { ++ offset = var->declspec.type->typestring_offset; ++ } + + if (is_return) + print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n"); +@@ -1241,8 +1256,8 @@ int is_interpreted_func( const type_t *iface, const var_t *func ) + { + const char *str; + const var_t *var; +- const var_list_t *args = type_get_function_args( func->type ); +- const type_t *ret_type = type_function_get_rettype( func->type ); ++ const var_list_t *args = type_function_get_args( func->declspec.type ); ++ const type_t *ret_type = type_function_get_rettype( func->declspec.type ); + + if (type_get_type( ret_type ) == TYPE_BASIC) + { +@@ -1264,10 +1279,10 @@ int is_interpreted_func( const type_t *iface, const var_t *func ) + if (get_stub_mode() != MODE_Oif && args) + { + LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) +- switch (type_get_type( var->type )) ++ switch (type_get_type( var->declspec.type )) + { + case TYPE_BASIC: +- switch (type_basic_get_type( var->type )) ++ switch (type_basic_get_type( var->declspec.type )) + { + /* floating point arguments are not supported in Oi mode */ + case TYPE_BASIC_FLOAT: return 0; +@@ -1292,7 +1307,7 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface, + unsigned short num_proc ) + { + var_t *var; +- var_list_t *args = type_get_function_args( func->type ); ++ var_list_t *args = type_function_get_args( func->declspec.type ); + unsigned char explicit_fc, implicit_fc; + unsigned char handle_flags; + const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); +@@ -1323,7 +1338,7 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface, + param_num++; + nb_args++; + } +- if (!is_void( type_function_get_rettype( func->type ))) ++ if (!is_void( type_function_get_rettype( func->declspec.type ))) + { + stack_size += pointer_size; + nb_args++; +@@ -1351,22 +1366,22 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface, + *offset += 4; + break; + case FC_BIND_GENERIC: +- handle_flags = type_memsize( handle_var->type ); ++ handle_flags = type_memsize( handle_var->declspec.type ); + print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); + print_file( file, indent, "0x%02x,\n", handle_flags ); + print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", + handle_stack_offset, handle_stack_offset ); +- print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) ); ++ print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->declspec.type ) ); + print_file( file, indent, "0x%x,\t/* FC_PAD */\n", FC_PAD); + *offset += 6; + break; + case FC_BIND_CONTEXT: +- handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type ); ++ handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->declspec.type, 0 ); + print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); + print_file( file, indent, "0x%02x,\n", handle_flags ); + print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", + handle_stack_offset, handle_stack_offset ); +- print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) ); ++ print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->declspec.type ) ); + print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num ); + *offset += 6; + break; +@@ -1381,7 +1396,7 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface, + + if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08; /* HasNotify */ + if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10; /* HasNotify2 */ +- if (iface == iface->details.iface->async_iface) oi2_flags |= 0x20; ++ if (iface == type_get_const_details(iface)->iface->async_iface) oi2_flags |= 0x20; + + size = get_function_buffer_size( func, PASS_IN ); + print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %u */\n", size, size ); +@@ -1402,9 +1417,9 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface, + if (is_object( iface )) pos += 2; + if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) + { +- if (type_get_type( var->type ) == TYPE_BASIC) ++ if (type_get_type( var->declspec.type ) == TYPE_BASIC) + { +- switch (type_basic_get_type( var->type )) ++ switch (type_basic_get_type( var->declspec.type )) + { + case TYPE_BASIC_FLOAT: fpu_mask |= 1 << pos; break; + case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break; +@@ -1427,15 +1442,15 @@ static void write_procformatstring_func( FILE *file, int indent, const type_t *i + unsigned int stack_offset = is_object( iface ) ? pointer_size : 0; + int is_interpreted = is_interpreted_func( iface, func ); + int is_new_style = is_interpreted && (get_stub_mode() == MODE_Oif); +- var_t *retval = type_function_get_retval( func->type ); ++ var_t *retval = type_function_get_retval( func->declspec.type ); + + if (is_interpreted) write_proc_func_header( file, indent, iface, func, offset, num_proc ); + + /* emit argument data */ +- if (type_get_function_args(func->type)) ++ if (type_function_get_args(func->declspec.type)) + { + const var_t *var; +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + { + print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name ); + if (is_new_style) +@@ -1446,7 +1461,7 @@ static void write_procformatstring_func( FILE *file, int indent, const type_t *i + } + + /* emit return value data */ +- if (is_void(retval->type)) ++ if (is_void(retval->declspec.type)) + { + if (!is_new_style) + { +@@ -1475,13 +1490,13 @@ static void for_each_iface(const statement_list_t *stmts, + + if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) + { +- if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE) ++ if (stmt->type != STMT_TYPE || type_get_type_detect_alias(stmt->u.type) != TYPE_INTERFACE) + continue; + iface = stmt->u.type; + if (!pred(iface)) continue; + proc(iface, file, indent, offset); +- if (iface->details.iface->async_iface) +- proc(iface->details.iface->async_iface, file, indent, offset); ++ if (type_get_const_details(iface)->iface->async_iface) ++ proc(type_get_const_details(iface)->iface->async_iface, file, indent, offset); + } + } + +@@ -1593,7 +1608,7 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, + { + conftype = FC_TOP_LEVEL_CONFORMANCE; + conftype_string = "parameter"; +- cont_type = current_func->type; ++ cont_type = current_func->declspec.type; + name = current_func->name; + iface = current_iface; + } +@@ -1656,7 +1671,7 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, + + if (type_get_type(cont_type) == TYPE_FUNCTION) + { +- var_list_t *args = type_get_function_args( cont_type ); ++ var_list_t *args = type_function_get_args( cont_type ); + + if (is_object( iface )) offset += pointer_size; + if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) +@@ -1664,7 +1679,7 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, + if (var->name && !strcmp(var->name, subexpr->u.sval)) + { + expr_loc.v = var; +- correlation_variable = var->type; ++ correlation_variable = var->declspec.type; + break; + } + offset += get_stack_size( var, NULL ); +@@ -1676,11 +1691,11 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, + + if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) + { +- unsigned int size = field_memsize( var->type, &offset ); ++ unsigned int size = field_memsize( var->declspec.type, &offset ); + if (var->name && !strcmp(var->name, subexpr->u.sval)) + { + expr_loc.v = var; +- correlation_variable = var->type; ++ correlation_variable = var->declspec.type; + break; + } + offset += size; +@@ -1819,7 +1834,7 @@ static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align + LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) + { + unsigned int falign = 0; +- unsigned int fsize = type_memsize_and_alignment(v->type, &falign); ++ unsigned int fsize = type_memsize_and_alignment(v->declspec.type, &falign); + if (*align < falign) *align = falign; + falign = clamp_align(falign); + size = ROUND_SIZE(size, falign); +@@ -1841,9 +1856,9 @@ static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa) + if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) + { + /* we could have an empty default field with NULL type */ +- if (v->type) ++ if (v->declspec.type) + { +- size = type_memsize_and_alignment(v->type, &align); ++ size = type_memsize_and_alignment(v->declspec.type, &align); + if (maxs < size) maxs = size; + if (*pmaxa < align) *pmaxa = align; + } +@@ -1931,12 +1946,12 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) + { + if (is_conformant_array(t)) + { +- type_memsize_and_alignment(type_array_get_element(t), align); ++ type_memsize_and_alignment(type_array_get_element_type(t), align); + size = 0; + } + else + size = type_array_get_dim(t) * +- type_memsize_and_alignment(type_array_get_element(t), align); ++ type_memsize_and_alignment(type_array_get_element_type(t), align); + } + else /* declared as a pointer */ + { +@@ -2016,8 +2031,8 @@ static unsigned int type_buffer_alignment(const type_t *t) + if (!(fields = type_struct_get_fields(t))) break; + LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) + { +- if (!var->type) continue; +- align = type_buffer_alignment( var->type ); ++ if (!var->declspec.type) continue; ++ align = type_buffer_alignment( var->declspec.type ); + if (max < align) max = align; + } + break; +@@ -2025,8 +2040,8 @@ static unsigned int type_buffer_alignment(const type_t *t) + if (!(fields = type_encapsulated_union_get_fields(t))) break; + LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) + { +- if (!var->type) continue; +- align = type_buffer_alignment( var->type ); ++ if (!var->declspec.type) continue; ++ align = type_buffer_alignment( var->declspec.type ); + if (max < align) max = align; + } + break; +@@ -2034,14 +2049,14 @@ static unsigned int type_buffer_alignment(const type_t *t) + if (!(fields = type_union_get_cases(t))) break; + LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) + { +- if (!var->type) continue; +- align = type_buffer_alignment( var->type ); ++ if (!var->declspec.type) continue; ++ align = type_buffer_alignment( var->declspec.type ); + if (max < align) max = align; + } + break; + case TYPE_ARRAY: + if (!type_array_is_decl_as_ptr(t)) +- return type_buffer_alignment( type_array_get_element(t) ); ++ return type_buffer_alignment( type_array_get_element_type(t) ); + /* else fall through */ + case TYPE_POINTER: + return 4; +@@ -2064,12 +2079,12 @@ static unsigned int type_buffer_alignment(const type_t *t) + int is_full_pointer_function(const var_t *func) + { + const var_t *var; +- if (type_has_full_pointer(type_function_get_rettype(func->type), func->attrs, TRUE)) ++ if (type_has_full_pointer(type_function_get_rettype(func->declspec.type), func->attrs, TRUE)) + return TRUE; +- if (!type_get_function_args(func->type)) ++ if (!type_function_get_args(func->declspec.type)) + return FALSE; +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) +- if (type_has_full_pointer( var->type, var->attrs, TRUE )) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) ++ if (type_has_full_pointer( var->declspec.type, var->attrs, TRUE )) + return TRUE; + return FALSE; + } +@@ -2114,12 +2129,13 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs + { + if (context == TYPE_CONTEXT_TOPLEVELPARAM && is_ptr(type) && pointer_type == FC_RP) + { +- switch (typegen_detect_type(type_pointer_get_ref(type), NULL, TDT_ALL_TYPES)) ++ switch (typegen_detect_type(type_pointer_get_ref_type(type), NULL, TDT_ALL_TYPES)) + { + case TGT_STRING: + case TGT_POINTER: + case TGT_CTXT_HANDLE: + case TGT_CTXT_HANDLE_POINTER: ++ case TGT_ARRAY: + flags |= FC_ALLOCED_ON_STACK; + break; + case TGT_IFACE_POINTER: +@@ -2134,7 +2150,7 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs + + if (is_ptr(type)) + { +- type_t *ref = type_pointer_get_ref(type); ++ type_t *ref = type_pointer_get_ref_type(type); + if(is_declptr(ref) && !is_user_type(ref)) + flags |= FC_POINTER_DEREF; + } +@@ -2175,7 +2191,7 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, + + pointer_fc = get_pointer_fc_context(type, attrs, context); + +- ref = type_pointer_get_ref(type); ++ ref = type_pointer_get_ref_type(type); + if (type_get_type(ref) == TYPE_ENUM) + fc = get_enum_fc(ref); + else +@@ -2200,22 +2216,23 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, + return 4; + } + +-static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff) ++static void print_start_tfs_comment(FILE *file, const decl_spec_t *ds, unsigned int tfsoff) + { + print_file(file, 0, "/* %u (", tfsoff); +- write_type_decl(file, t, NULL); ++ write_declspec_decl(file, ds, NULL); + print_file(file, 0, ") */\n"); + } + + static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs, +- type_t *type, unsigned int ref_offset, ++ const decl_spec_t *declspec, unsigned int ref_offset, + enum type_context context, + unsigned int *typestring_offset) + { + unsigned int offset = *typestring_offset; +- type_t *ref = type_pointer_get_ref(type); ++ type_t *type = declspec->type; ++ type_t *ref = type_pointer_get_ref_type(type); + +- print_start_tfs_comment(file, type, offset); ++ print_start_tfs_comment(file, declspec, offset); + update_tfsoff(type, offset, file); + + switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES)) +@@ -2258,10 +2275,11 @@ static int user_type_has_variable_size(const type_t *t) + return FALSE; + } + +-static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff) ++static unsigned int write_user_tfs(FILE *file, const decl_spec_t *declspec, unsigned int *tfsoff) + { + unsigned int start, absoff, flags; + const char *name = NULL; ++ type_t *type = declspec->type; + type_t *utype = get_user_type(type, &name); + unsigned int usize = type_memsize(utype); + unsigned int ualign = type_buffer_alignment(utype); +@@ -2279,6 +2297,7 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof + type_get_type(utype) == TYPE_ENUM) + { + unsigned char fc; ++ decl_spec_t ds; + + if (type_get_type(utype) == TYPE_ENUM) + fc = get_enum_fc(utype); +@@ -2286,7 +2305,7 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof + fc = get_basic_fc(utype); + + absoff = *tfsoff; +- print_start_tfs_comment(file, utype, absoff); ++ print_start_tfs_comment(file, init_declspec(&ds, utype), absoff); + print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); + print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); + *tfsoff += 2; +@@ -2294,7 +2313,10 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof + else + { + if (!processed(utype)) +- write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff); ++ { ++ decl_spec_t ds; ++ write_embedded_types(file, NULL, init_declspec(&ds, utype), utype->name, TRUE, tfsoff); ++ } + absoff = utype->typestring_offset; + } + +@@ -2307,7 +2329,7 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof + + start = *tfsoff; + update_tfsoff(type, start, file); +- print_start_tfs_comment(file, type, start); ++ print_start_tfs_comment(file, declspec, start); + print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", FC_USER_MARSHAL); + print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n", + flags | (ualign - 1), ualign - 1, flags); +@@ -2364,11 +2386,12 @@ static void write_member_type(FILE *file, const type_t *cont, + static void write_array_element_type(FILE *file, const attr_list_t *attrs, const type_t *type, + int cont_is_complex, unsigned int *tfsoff) + { +- type_t *elem = type_array_get_element(type); ++ const decl_spec_t *element = type_array_get_element(type); ++ type_t *elem = element->type; + + if (!is_embedded_complex(elem) && is_ptr(elem)) + { +- type_t *ref = type_pointer_get_ref(elem); ++ type_t *ref = type_pointer_get_ref_type(elem); + + if (processed(ref)) + { +@@ -2378,7 +2401,7 @@ static void write_array_element_type(FILE *file, const attr_list_t *attrs, const + } + if (cont_is_complex && is_string_type(attrs, elem)) + { +- write_string_tfs(file, NULL, elem, TYPE_CONTEXT_CONTAINER, NULL, tfsoff); ++ write_string_tfs(file, NULL, element, TYPE_CONTEXT_CONTAINER, NULL, tfsoff); + return; + } + if (!is_string_type(NULL, elem) && +@@ -2410,7 +2433,7 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) + + if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) + { +- type_t *ft = f->type; ++ type_t *ft = f->declspec.type; + unsigned int size = field_memsize( ft, &offset ); + if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS)) + { +@@ -2433,13 +2456,14 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) + } + + static int write_pointer_description_offsets( +- FILE *file, const attr_list_t *attrs, type_t *type, ++ FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + unsigned int *offset_in_memory, unsigned int *offset_in_buffer, + unsigned int *typestring_offset) + { ++ type_t *type = declspec->type; + int written = 0; + +- if ((is_ptr(type) && type_get_type(type_pointer_get_ref(type)) != TYPE_INTERFACE) || ++ if ((is_ptr(type) && type_get_type(type_pointer_get_ref_type(type)) != TYPE_INTERFACE) || + (is_array(type) && type_array_is_decl_as_ptr(type))) + { + if (offset_in_memory && offset_in_buffer) +@@ -2464,10 +2488,10 @@ static int write_pointer_description_offsets( + + if (is_ptr(type)) + { +- type_t *ref = type_pointer_get_ref(type); ++ type_t *ref = type_pointer_get_ref_type(type); + + if (is_string_type(attrs, type)) +- write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset); ++ write_string_tfs(file, attrs, declspec, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset); + else if (processed(ref)) + write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, + ref->typestring_offset, typestring_offset); +@@ -2505,13 +2529,13 @@ static int write_pointer_description_offsets( + { + unsigned int padding; + unsigned int align = 0; +- type_memsize_and_alignment(v->type, &align); ++ type_memsize_and_alignment(v->declspec.type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } + written += write_pointer_description_offsets( +- file, v->attrs, v->type, offset_in_memory, offset_in_buffer, ++ file, v->attrs, &v->declspec, offset_in_memory, offset_in_buffer, + typestring_offset); + } + } +@@ -2531,10 +2555,11 @@ static int write_pointer_description_offsets( + } + + static int write_no_repeat_pointer_descriptions( +- FILE *file, const attr_list_t *attrs, type_t *type, ++ FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + unsigned int *offset_in_memory, unsigned int *offset_in_buffer, + unsigned int *typestring_offset) + { ++ type_t *type = declspec->type; + int written = 0; + + if (is_ptr(type) || +@@ -2544,7 +2569,7 @@ static int write_no_repeat_pointer_descriptions( + print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD); + *typestring_offset += 2; + +- return write_pointer_description_offsets(file, attrs, type, ++ return write_pointer_description_offsets(file, attrs, declspec, + offset_in_memory, offset_in_buffer, typestring_offset); + } + +@@ -2557,13 +2582,13 @@ static int write_no_repeat_pointer_descriptions( + { + unsigned int padding; + unsigned int align = 0; +- type_memsize_and_alignment(v->type, &align); ++ type_memsize_and_alignment(v->declspec.type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } + written += write_no_repeat_pointer_descriptions( +- file, v->attrs, v->type, ++ file, v->attrs, &v->declspec, + offset_in_memory, offset_in_buffer, typestring_offset); + } + } +@@ -2582,10 +2607,11 @@ static int write_no_repeat_pointer_descriptions( + /* Note: if file is NULL return value is number of pointers to write, else + * it is the number of type format characters written */ + static int write_fixed_array_pointer_descriptions( +- FILE *file, const attr_list_t *attrs, type_t *type, ++ FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + unsigned int *offset_in_memory, unsigned int *offset_in_buffer, + unsigned int *typestring_offset) + { ++ type_t *type = declspec->type; + int pointer_count = 0; + + if (type_get_type(type) == TYPE_ARRAY && +@@ -2602,7 +2628,7 @@ static int write_fixed_array_pointer_descriptions( + unsigned int offset_of_array_pointer_mem = 0; + unsigned int offset_of_array_pointer_buf = 0; + +- increment_size = type_memsize(type_array_get_element(type)); ++ increment_size = type_memsize(type_array_get_element_type(type)); + + print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", FC_FIXED_REPEAT); + print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD); +@@ -2613,7 +2639,7 @@ static int write_fixed_array_pointer_descriptions( + *typestring_offset += 10; + + pointer_count = write_pointer_description_offsets( +- file, attrs, type, &offset_of_array_pointer_mem, ++ file, attrs, declspec, &offset_of_array_pointer_mem, + &offset_of_array_pointer_buf, typestring_offset); + } + } +@@ -2626,13 +2652,13 @@ static int write_fixed_array_pointer_descriptions( + { + unsigned int padding; + unsigned int align = 0; +- type_memsize_and_alignment(v->type, &align); ++ type_memsize_and_alignment(v->declspec.type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } + pointer_count += write_fixed_array_pointer_descriptions( +- file, v->attrs, v->type, offset_in_memory, offset_in_buffer, ++ file, v->attrs, &v->declspec, offset_in_memory, offset_in_buffer, + typestring_offset); + } + } +@@ -2673,7 +2699,7 @@ static int write_conformant_array_pointer_descriptions( + unsigned int offset_of_array_pointer_mem = offset_in_memory; + unsigned int offset_of_array_pointer_buf = offset_in_memory; + +- increment_size = type_memsize(type_array_get_element(type)); ++ increment_size = type_memsize(type_array_get_element_type(type)); + + if (increment_size > USHRT_MAX) + error("array size of %u bytes is too large\n", increment_size); +@@ -2715,7 +2741,7 @@ static int write_varying_array_pointer_descriptions( + { + unsigned int increment_size; + +- increment_size = type_memsize(type_array_get_element(type)); ++ increment_size = type_memsize(type_array_get_element_type(type)); + + if (increment_size > USHRT_MAX) + error("array size of %u bytes is too large\n", increment_size); +@@ -2741,20 +2767,20 @@ static int write_varying_array_pointer_descriptions( + { + unsigned int align = 0, padding; + +- if (is_array(v->type) && type_array_has_variance(v->type)) ++ if (is_array(v->declspec.type) && type_array_has_variance(v->declspec.type)) + { + *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4); + /* skip over variance and offset in buffer */ + *offset_in_buffer += 8; + } + +- type_memsize_and_alignment(v->type, &align); ++ type_memsize_and_alignment(v->declspec.type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } + pointer_count += write_varying_array_pointer_descriptions( +- file, v->attrs, v->type, offset_in_memory, offset_in_buffer, ++ file, v->attrs, v->declspec.type, offset_in_memory, offset_in_buffer, + typestring_offset); + } + } +@@ -2773,9 +2799,10 @@ static int write_varying_array_pointer_descriptions( + return pointer_count; + } + +-static void write_pointer_description(FILE *file, const attr_list_t *attrs, type_t *type, ++static void write_pointer_description(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + unsigned int *typestring_offset) + { ++ type_t *type = declspec->type; + unsigned int offset_in_buffer; + unsigned int offset_in_memory; + +@@ -2786,7 +2813,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type + offset_in_memory = 0; + offset_in_buffer = 0; + write_no_repeat_pointer_descriptions( +- file, NULL, type, ++ file, NULL, declspec, + &offset_in_memory, &offset_in_buffer, typestring_offset); + } + +@@ -2794,7 +2821,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type + offset_in_memory = 0; + offset_in_buffer = 0; + write_fixed_array_pointer_descriptions( +- file, NULL, type, ++ file, NULL, declspec, + &offset_in_memory, &offset_in_buffer, typestring_offset); + + /* pass 3: search for pointers in conformant only arrays (but don't descend +@@ -2806,7 +2833,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type + else if (type_get_type(type) == TYPE_STRUCT && + get_struct_fc(type) == FC_CPSTRUCT) + { +- type_t *carray = find_array_or_string_in_struct(type)->type; ++ type_t *carray = find_array_or_string_in_struct(type)->declspec.type; + write_conformant_array_pointer_descriptions( file, NULL, carray, + type_memsize(type), typestring_offset); + } +@@ -2820,9 +2847,10 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type + } + + static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, +- type_t *type, enum type_context context, ++ const decl_spec_t *declspec, enum type_context context, + const char *name, unsigned int *typestring_offset) + { ++ type_t *type = declspec->type; + unsigned int start_offset; + unsigned char rtype; + type_t *elem_type; +@@ -2836,7 +2864,7 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, + int pointer_type = get_pointer_fc_context(type, attrs, context); + if (!pointer_type) + pointer_type = FC_RP; +- print_start_tfs_comment(file, type, *typestring_offset); ++ print_start_tfs_comment(file, declspec, *typestring_offset); + print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n", + pointer_type, flag, string_of_type(pointer_type), + flag ? " [simple_pointer]" : ""); +@@ -2850,12 +2878,12 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, + } + + if (is_array(type)) +- elem_type = type_array_get_element(type); ++ elem_type = type_array_get_element_type(type); + else +- elem_type = type_pointer_get_ref(type); ++ elem_type = type_pointer_get_ref_type(type); + + if (type_get_type(elem_type) == TYPE_POINTER && is_array(type)) +- return write_array_tfs(file, attrs, type, name, typestring_offset); ++ return write_array_tfs(file, attrs, declspec, name, typestring_offset); + + if (type_get_type(elem_type) != TYPE_BASIC) + { +@@ -2929,34 +2957,31 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, + } + } + +-static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type, ++static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + const char *name, unsigned int *typestring_offset) + { ++ type_t *type = declspec->type; + const expr_t *length_is = type_array_get_variance(type); + const expr_t *size_is = type_array_get_conformance(type); + unsigned int align; + unsigned int size; + unsigned int start_offset; + unsigned char fc; +- int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); + unsigned int baseoff + = !type_array_is_decl_as_ptr(type) && current_structure + ? type_memsize(current_structure) + : 0; + +- if (!pointer_type) +- pointer_type = FC_RP; +- +- if (!is_string_type(attrs, type_array_get_element(type))) ++ if (!is_string_type(attrs, type_array_get_element_type(type))) + write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset); + +- size = type_memsize(is_conformant_array(type) ? type_array_get_element(type) : type); +- align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element(type) : type); ++ size = type_memsize(is_conformant_array(type) ? type_array_get_element_type(type) : type); ++ align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element_type(type) : type); + fc = get_array_fc(type); + + start_offset = *typestring_offset; + update_tfsoff(type, start_offset, file); +- print_start_tfs_comment(file, type, start_offset); ++ print_start_tfs_comment(file, declspec, start_offset); + print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc)); + print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); + *typestring_offset += 2; +@@ -2982,7 +3007,7 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t + + if (fc == FC_SMVARRAY || fc == FC_LGVARRAY) + { +- unsigned int elsize = type_memsize(type_array_get_element(type)); ++ unsigned int elsize = type_memsize(type_array_get_element_type(type)); + unsigned int dim = type_array_get_dim(type); + + if (fc == FC_LGVARRAY) +@@ -3005,13 +3030,13 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t + += write_conf_or_var_desc(file, current_structure, baseoff, + type, length_is); + +- if (type_has_pointers(type_array_get_element(type)) && ++ if (type_has_pointers(type_array_get_element_type(type)) && + (type_array_is_decl_as_ptr(type) || !current_structure)) + { + print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP); + print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); + *typestring_offset += 2; +- write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, type, typestring_offset); ++ write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, declspec, typestring_offset); + print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); + *typestring_offset += 1; + } +@@ -3048,7 +3073,7 @@ static const var_t *find_array_or_string_in_struct(const type_t *type) + return NULL; + + last_field = LIST_ENTRY( list_tail(fields), const var_t, entry ); +- ft = last_field->type; ++ ft = last_field->declspec.type; + + if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft)) + return last_field; +@@ -3071,7 +3096,7 @@ static void write_struct_members(FILE *file, const type_t *type, + + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + { +- type_t *ft = field->type; ++ type_t *ft = field->declspec.type; + unsigned int align = 0; + unsigned int size = type_memsize_and_alignment(ft, &align); + align = clamp_align(align); +@@ -3100,7 +3125,7 @@ static void write_struct_members(FILE *file, const type_t *type, + offset = ROUND_SIZE(offset, align); + *typestring_offset += 1; + } +- write_member_type(file, type, is_complex, field->attrs, field->type, corroff, ++ write_member_type(file, type, is_complex, field->attrs, field->declspec.type, corroff, + typestring_offset); + offset += size; + } +@@ -3118,9 +3143,10 @@ static void write_struct_members(FILE *file, const type_t *type, + write_end(file, typestring_offset); + } + +-static unsigned int write_struct_tfs(FILE *file, type_t *type, ++static unsigned int write_struct_tfs(FILE *file, const decl_spec_t *declspec, + const char *name, unsigned int *tfsoff) + { ++ type_t *type = declspec->type; + const type_t *save_current_structure = current_structure; + unsigned int total_size; + const var_t *array; +@@ -3143,15 +3169,15 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, + name, USHRT_MAX, total_size - USHRT_MAX); + + if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) +- write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff); ++ write_embedded_types(file, f->attrs, &f->declspec, f->name, FALSE, tfsoff); + + array = find_array_or_string_in_struct(type); +- if (array && !processed(array->type)) ++ if (array && !processed(array->declspec.type)) + { +- if(is_string_type(array->attrs, array->type)) +- write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff); ++ if(is_string_type(array->attrs, array->declspec.type)) ++ write_string_tfs(file, array->attrs, &array->declspec, TYPE_CONTEXT_CONTAINER, array->name, tfsoff); + else +- write_array_tfs(file, array->attrs, array->type, array->name, tfsoff); ++ write_array_tfs(file, array->attrs, &array->declspec, array->name, tfsoff); + } + + corroff = *tfsoff; +@@ -3159,7 +3185,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, + + start_offset = *tfsoff; + update_tfsoff(type, start_offset, file); +- print_start_tfs_comment(file, type, start_offset); ++ print_start_tfs_comment(file, declspec, start_offset); + print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); + print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size); +@@ -3167,7 +3193,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, + + if (array) + { +- unsigned int absoff = array->type->typestring_offset; ++ unsigned int absoff = array->declspec.type->typestring_offset; + short reloff = absoff - *tfsoff; + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", + reloff, reloff, absoff); +@@ -3198,7 +3224,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, + print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP); + print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); + *tfsoff += 2; +- write_pointer_description(file, NULL, type, tfsoff); ++ write_pointer_description(file, NULL, declspec, tfsoff); + print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); + *tfsoff += 1; + } +@@ -3213,15 +3239,16 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, + type->ptrdesc = *tfsoff; + if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) + { +- type_t *ft = f->type; ++ const decl_spec_t *fds = &f->declspec; ++ type_t *ft = fds->type; + switch (typegen_detect_type(ft, f->attrs, TDT_IGNORE_STRINGS)) + { + case TGT_POINTER: + if (is_string_type(f->attrs, ft)) +- write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff); ++ write_string_tfs(file, f->attrs, fds, TYPE_CONTEXT_CONTAINER, f->name, tfsoff); + else +- write_pointer_tfs(file, f->attrs, ft, +- type_pointer_get_ref(ft)->typestring_offset, ++ write_pointer_tfs(file, f->attrs, fds, ++ type_pointer_get_ref_type(ft)->typestring_offset, + TYPE_CONTEXT_CONTAINER, tfsoff); + break; + case TGT_ARRAY: +@@ -3283,8 +3310,9 @@ static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff) + } + + static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, +- type_t *type, unsigned int *tfsoff) ++ const decl_spec_t *declspec, unsigned int *tfsoff) + { ++ type_t* type = declspec->type; + unsigned int start_offset; + unsigned int size; + var_list_t *fields; +@@ -3309,17 +3337,17 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, + expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); + if (cases) + nbranch += list_count(cases); +- if (f->type) +- write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff); ++ if (f->declspec.type) ++ write_embedded_types(file, f->attrs, &f->declspec, f->name, TRUE, tfsoff); + } + + start_offset = *tfsoff; + update_tfsoff(type, start_offset, file); +- print_start_tfs_comment(file, type, start_offset); ++ print_start_tfs_comment(file, declspec, start_offset); + if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) + { + const var_t *sv = type_union_get_switch_value(type); +- const type_t *st = sv->type; ++ const type_t *st = sv->declspec.type; + unsigned int align = 0; + unsigned char fc; + +@@ -3351,8 +3379,8 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, + type_memsize_and_alignment(st, &align); + if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) + { +- if (f->type) +- type_memsize_and_alignment(f->type, &align); ++ if (f->declspec.type) ++ type_memsize_and_alignment(f->declspec.type, &align); + } + + print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION); +@@ -3407,7 +3435,7 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, + + if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) + { +- type_t *ft = f->type; ++ type_t *ft = f->declspec.type; + expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); + int deflt = is_attr(f->attrs, ATTR_DEFAULT); + expr_t *c; +@@ -3448,16 +3476,17 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, + return start_offset; + } + +-static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type, ++static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + unsigned int *typeformat_offset) + { + unsigned int i; ++ type_t *type = declspec->type; + unsigned int start_offset = *typeformat_offset; + expr_t *iid = get_attrp(attrs, ATTR_IIDIS); + + if (!iid && processed(type)) return type->typestring_offset; + +- print_start_tfs_comment(file, type, start_offset); ++ print_start_tfs_comment(file, declspec, start_offset); + update_tfsoff(type, start_offset, file); + + if (iid) +@@ -3469,7 +3498,7 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t + } + else + { +- const type_t *base = is_ptr(type) ? type_pointer_get_ref(type) : type; ++ const type_t *base = is_ptr(type) ? type_pointer_get_ref_type(type) : type; + const UUID *uuid = get_attrp(base->attrs, ATTR_UUID); + + if (! uuid) +@@ -3493,18 +3522,19 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t + + static unsigned int write_contexthandle_tfs(FILE *file, + const attr_list_t *attrs, +- type_t *type, +- int toplevel_param, ++ const decl_spec_t *declspec, ++ enum type_context context, + unsigned int *typeformat_offset) + { ++ type_t *type = declspec->type; + unsigned int start_offset = *typeformat_offset; +- unsigned char flags = get_contexthandle_flags( current_iface, attrs, type ); ++ unsigned char flags = get_contexthandle_flags( current_iface, attrs, type, context == TYPE_CONTEXT_RETVAL ); + +- print_start_tfs_comment(file, type, start_offset); ++ print_start_tfs_comment(file, declspec, start_offset); + + if (flags & 0x80) /* via ptr */ + { +- int pointer_type = get_pointer_fc( type, attrs, toplevel_param ); ++ int pointer_type = get_pointer_fc( type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM ); + if (!pointer_type) pointer_type = FC_RP; + *typeformat_offset += 4; + print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) ); +@@ -3514,8 +3544,7 @@ static unsigned int write_contexthandle_tfs(FILE *file, + + print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", FC_BIND_CONTEXT); + print_file(file, 2, "0x%x,\t/* Context flags: ", flags); +- /* return and can't be null values overlap */ +- if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL)) ++ if (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) + print_file(file, 0, "can't be null, "); + if (flags & NDR_CONTEXT_HANDLE_SERIALIZE) + print_file(file, 0, "serialize, "); +@@ -3523,13 +3552,13 @@ static unsigned int write_contexthandle_tfs(FILE *file, + print_file(file, 0, "no serialize, "); + if (flags & NDR_STRICT_CONTEXT_HANDLE) + print_file(file, 0, "strict, "); +- if ((flags & 0x21) == 0x20) +- print_file(file, 0, "out, "); +- if ((flags & 0x21) == 0x21) ++ if (flags & HANDLE_PARAM_IS_RETURN) + print_file(file, 0, "return, "); +- if (flags & 0x40) ++ if (flags & HANDLE_PARAM_IS_OUT) ++ print_file(file, 0, "out, "); ++ if (flags & HANDLE_PARAM_IS_IN) + print_file(file, 0, "in, "); +- if (flags & 0x80) ++ if (flags & HANDLE_PARAM_IS_VIA_PTR) + print_file(file, 0, "via ptr, "); + print_file(file, 0, "*/\n"); + print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type )); +@@ -3568,24 +3597,23 @@ static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs, + return start_offset; + } + +-static unsigned int write_type_tfs(FILE *file, int indent, +- const attr_list_t *attrs, type_t *type, +- const char *name, ++static unsigned int write_type_tfs(FILE *file, const attr_list_t *attrs, ++ const decl_spec_t *declspec, const char *name, + enum type_context context, + unsigned int *typeformat_offset) + { + unsigned int offset; ++ type_t *type = declspec->type; + + switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES)) + { + case TGT_CTXT_HANDLE: + case TGT_CTXT_HANDLE_POINTER: +- return write_contexthandle_tfs(file, attrs, type, +- context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset); ++ return write_contexthandle_tfs(file, attrs, declspec, context, typeformat_offset); + case TGT_USER_TYPE: +- return write_user_tfs(file, type, typeformat_offset); ++ return write_user_tfs(file, declspec, typeformat_offset); + case TGT_STRING: +- return write_string_tfs(file, attrs, type, context, name, typeformat_offset); ++ return write_string_tfs(file, attrs, declspec, context, name, typeformat_offset); + case TGT_ARRAY: + { + unsigned int off; +@@ -3593,15 +3621,14 @@ static unsigned int write_type_tfs(FILE *file, int indent, + if ((context != TYPE_CONTEXT_CONTAINER && + context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) || + !is_conformant_array(type) || type_array_is_decl_as_ptr(type)) +- off = write_array_tfs(file, attrs, type, name, typeformat_offset); ++ off = write_array_tfs(file, attrs, declspec, name, typeformat_offset); + else + off = 0; + if (context != TYPE_CONTEXT_CONTAINER && + context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) + { + int ptr_type; +- ptr_type = get_pointer_fc(type, attrs, +- context == TYPE_CONTEXT_TOPLEVELPARAM); ++ ptr_type = get_pointer_fc_context(type, attrs, context); + if (ptr_type != FC_RP || type_array_is_decl_as_ptr(type)) + { + unsigned int absoff = type->typestring_offset; +@@ -3615,14 +3642,14 @@ static unsigned int write_type_tfs(FILE *file, int indent, + if (ptr_type != FC_RP) update_tfsoff( type, off, file ); + *typeformat_offset += 4; + } +- type->details.array.ptr_tfsoff = off; ++ type_get_details(type)->array.ptr_tfsoff = off; + } + return off; + } + case TGT_STRUCT: +- return write_struct_tfs(file, type, name, typeformat_offset); ++ return write_struct_tfs(file, declspec, name, typeformat_offset); + case TGT_UNION: +- return write_union_tfs(file, attrs, type, typeformat_offset); ++ return write_union_tfs(file, attrs, declspec, typeformat_offset); + case TGT_ENUM: + case TGT_BASIC: + /* nothing to do */ +@@ -3635,11 +3662,11 @@ static unsigned int write_type_tfs(FILE *file, int indent, + return write_range_tfs(file, attrs, type, range_list, typeformat_offset); + } + case TGT_IFACE_POINTER: +- return write_ip_tfs(file, attrs, type, typeformat_offset); ++ return write_ip_tfs(file, attrs, declspec, typeformat_offset); + case TGT_POINTER: + { + enum type_context ref_context; +- type_t *ref = type_pointer_get_ref(type); ++ const decl_spec_t *ref = type_pointer_get_ref(type); + + if (context == TYPE_CONTEXT_TOPLEVELPARAM) + ref_context = TYPE_CONTEXT_PARAM; +@@ -3648,22 +3675,22 @@ static unsigned int write_type_tfs(FILE *file, int indent, + else + ref_context = context; + +- if (is_string_type(attrs, ref)) ++ if (is_string_type(attrs, ref->type)) + { + if (context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) +- write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset); ++ write_pointer_tfs(file, attrs, declspec, *typeformat_offset + 4, context, typeformat_offset); + +- offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset); ++ offset = write_type_tfs(file, attrs, ref, name, ref_context, typeformat_offset); + if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) + return 0; + return offset; + } + +- offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name, ++ offset = write_type_tfs( file, attrs, type_pointer_get_ref(type), name, + ref_context, typeformat_offset); + if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) + return 0; +- return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset); ++ return write_pointer_tfs(file, attrs, declspec, offset, context, typeformat_offset); + } + case TGT_INVALID: + break; +@@ -3672,10 +3699,10 @@ static unsigned int write_type_tfs(FILE *file, int indent, + return 0; + } + +-static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, ++static int write_embedded_types(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec, + const char *name, int write_ptr, unsigned int *tfsoff) + { +- return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff); ++ return write_type_tfs(file, attrs, declspec, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff); + } + + static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset) +@@ -3693,21 +3720,21 @@ static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned in + { + const var_t *func = stmt->u.var; + +- if(stmt->u.var->stgclass != STG_NONE +- || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION) ++ if(stmt->u.var->declspec.stgclass != STG_NONE ++ || type_get_type_detect_alias(stmt->u.var->declspec.type) != TYPE_FUNCTION) + continue; + + current_func = func; + if (is_local(func->attrs)) continue; + +- var = type_function_get_retval(func->type); +- if (!is_void(var->type)) +- var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name, +- TYPE_CONTEXT_PARAM, offset); ++ var = type_function_get_retval(func->declspec.type); ++ if (!is_void(var->declspec.type)) ++ var->typestring_offset = write_type_tfs( file, var->attrs, &var->declspec, func->name, ++ TYPE_CONTEXT_RETVAL, offset); + +- if (type_get_function_args(func->type)) +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), var_t, entry ) +- var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name, ++ if (type_function_get_args(func->declspec.type)) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), var_t, entry ) ++ var->typestring_offset = write_type_tfs( file, var->attrs, &var->declspec, var->name, + TYPE_CONTEXT_TOPLEVELPARAM, offset ); + break; + +@@ -3719,9 +3746,12 @@ static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned in + { + if (is_attr(type_entry->type->attrs, ATTR_ENCODE) + || is_attr(type_entry->type->attrs, ATTR_DECODE)) +- type_entry->type->typestring_offset = write_type_tfs( file, 2, +- type_entry->type->attrs, type_entry->type, type_entry->type->name, ++ { ++ decl_spec_t ds; ++ type_entry->type->typestring_offset = write_type_tfs( file, ++ type_entry->type->attrs, init_declspec(&ds, type_entry->type), type_entry->type->name, + TYPE_CONTEXT_CONTAINER, offset); ++ } + } + break; + } +@@ -3842,7 +3872,7 @@ static unsigned int get_required_buffer_size_type( + case TGT_POINTER: + { + unsigned int size, align; +- const type_t *ref = type_pointer_get_ref(type); ++ const type_t *ref = type_pointer_get_ref_type(type); + if (is_string_type( attrs, ref )) break; + if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break; + if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP) +@@ -3862,7 +3892,7 @@ static unsigned int get_required_buffer_size_type( + case FC_SMFARRAY: + case FC_LGFARRAY: + return type_array_get_dim(type) * +- get_required_buffer_size_type(type_array_get_element(type), name, ++ get_required_buffer_size_type(type_array_get_element_type(type), name, + NULL, FALSE, alignment); + } + } +@@ -3893,8 +3923,8 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali + return 20; + } + +- if (!is_string_type(var->attrs, var->type)) +- return get_required_buffer_size_type(var->type, var->name, ++ if (!is_string_type(var->attrs, var->declspec.type)) ++ return get_required_buffer_size_type(var->declspec.type, var->name, + var->attrs, TRUE, alignment); + } + return 0; +@@ -3905,19 +3935,19 @@ static unsigned int get_function_buffer_size( const var_t *func, enum pass pass + const var_t *var; + unsigned int total_size = 0, alignment; + +- if (type_get_function_args(func->type)) ++ if (type_function_get_args(func->declspec.type)) + { +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + { + total_size += get_required_buffer_size(var, &alignment, pass); + total_size += alignment; + } + } + +- if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type))) ++ if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->declspec.type))) + { + var_t v = *func; +- v.type = type_function_get_rettype(func->type); ++ v.declspec.type = type_function_get_rettype(func->declspec.type); + total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN); + total_size += alignment; + } +@@ -3953,9 +3983,9 @@ static void print_phase_function(FILE *file, int indent, const char *type, + print_file(file, indent, "&__frame->_StubMsg,\n"); + print_file(file, indent, "%s%s%s%s%s,\n", + (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)", +- (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "", ++ (phase == PHASE_UNMARSHAL || decl_indirect(var->declspec.type)) ? "&" : "", + local_var_prefix, +- (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "", ++ (phase == PHASE_UNMARSHAL && decl_indirect(var->declspec.type)) ? "_p_" : "", + var->name); + print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n", + type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");"); +@@ -3968,7 +3998,8 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, + enum remoting_phase phase, enum pass pass, const var_t *var, + const char *varname) + { +- type_t *type = var->type; ++ const decl_spec_t *declspec = &var->declspec; ++ type_t *type = declspec->type; + unsigned int alignment = 0; + + /* no work to do for other phases, buffer sizing is done elsewhere */ +@@ -3999,8 +4030,8 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, + } + else + { +- const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type; +- switch (get_basic_fc(ref)) ++ const decl_spec_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : declspec; ++ switch (get_basic_fc(ref->type)) + { + case FC_BYTE: + case FC_CHAR: +@@ -4037,7 +4068,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, + + default: + error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", +- var->name, get_basic_fc(ref)); ++ var->name, get_basic_fc(ref->type)); + } + + if (phase == PHASE_MARSHAL && alignment > 1) +@@ -4048,7 +4079,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, + if (phase == PHASE_MARSHAL) + { + print_file(file, indent, "*("); +- write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); ++ write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL); + if (is_ptr(type)) + fprintf(file, " *)__frame->_StubMsg.Buffer = *"); + else +@@ -4059,7 +4090,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, + else if (phase == PHASE_UNMARSHAL) + { + print_file(file, indent, "if (__frame->_StubMsg.Buffer + sizeof("); +- write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); ++ write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL); + fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n"); + print_file(file, indent, "{\n"); + print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); +@@ -4071,12 +4102,12 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, + fprintf(file, " = ("); + else + fprintf(file, " = *("); +- write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); ++ write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL); + fprintf(file, " *)__frame->_StubMsg.Buffer;\n"); + } + + print_file(file, indent, "__frame->_StubMsg.Buffer += sizeof("); +- write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); ++ write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL); + fprintf(file, ");\n"); + } + } +@@ -4092,7 +4123,7 @@ expr_t *get_size_is_expr(const type_t *t, const char *name) + { + expr_t *x = NULL; + +- for ( ; is_array(t); t = type_array_get_element(t)) ++ for ( ; is_array(t); t = type_array_get_element_type(t)) + if (type_array_has_conformance(t) && + type_array_get_conformance(t)->type != EXPR_VOID) + { +@@ -4110,7 +4141,7 @@ expr_t *get_size_is_expr(const type_t *t, const char *name) + void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix, + enum remoting_phase phase, const var_t *var, int valid_variance) + { +- const type_t *type = var->type; ++ const type_t *type = var->declspec.type; + /* get fundamental type for the argument */ + for (;;) + { +@@ -4162,7 +4193,7 @@ void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local + break; + } + case TGT_POINTER: +- type = type_pointer_get_ref(type); ++ type = type_pointer_get_ref_type(type); + continue; + case TGT_INVALID: + case TGT_USER_TYPE: +@@ -4184,7 +4215,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const + { + int in_attr, out_attr, pointer_type; + const char *type_str = NULL; +- const type_t *type = var->type; ++ const type_t *type = var->declspec.type; + unsigned int alignment, start_offset = type->typestring_offset; + + if (is_ptr(type) || is_array(type)) +@@ -4237,19 +4268,20 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const + print_file(file, indent, "NdrServerContextNewMarshall(\n"); + print_file(file, indent + 1, "&__frame->_StubMsg,\n"); + print_file(file, indent + 1, "(NDR_SCONTEXT)%s%s,\n", local_var_prefix, var->name); +- print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type)); ++ print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->declspec.type)); + print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); + } + } + else if (phase == PHASE_UNMARSHAL) + { +- if (pass == PASS_OUT) ++ if (pass == PASS_OUT || pass == PASS_RETURN) + { + if (!in_attr) + print_file(file, indent, "*%s%s = 0;\n", local_var_prefix, var->name); + print_file(file, indent, "NdrClientContextUnmarshall(\n"); + print_file(file, indent + 1, "&__frame->_StubMsg,\n"); +- print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s,\n", local_var_prefix, var->name); ++ print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s%s,\n", ++ pass == PASS_RETURN ? "&" : "", local_var_prefix, var->name); + print_file(file, indent + 1, "__frame->_Handle);\n"); + } + else +@@ -4343,10 +4375,10 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const + ((tc == FC_SMVARRAY || tc == FC_LGVARRAY) && in_attr) || + (tc == FC_CARRAY && !in_attr)) + { +- if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff) ++ if (type_array_is_decl_as_ptr(type) && type_get_const_details(type)->array.ptr_tfsoff) + { + print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, +- type->details.array.ptr_tfsoff); ++ type_get_const_details(type)->array.ptr_tfsoff); + break; + } + print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); +@@ -4380,9 +4412,9 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const + range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry); + + print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name); +- write_type_decl(file, var->type, NULL); ++ write_declspec_decl(file, &var->declspec, NULL); + fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name); +- write_type_decl(file, var->type, NULL); ++ write_declspec_decl(file, &var->declspec, NULL); + fprintf(file, ")0x%x))\n", range_max->cval); + print_file(file, indent, "{\n"); + print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n"); +@@ -4428,7 +4460,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const + } + case TGT_POINTER: + { +- const type_t *ref = type_pointer_get_ref(type); ++ const type_t *ref = type_pointer_get_ref_type(type); + if (pointer_type == FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES)) + { + case TGT_BASIC: +@@ -4549,14 +4581,14 @@ void write_remoting_arguments(FILE *file, int indent, const var_t *func, const c + if (pass == PASS_RETURN) + { + write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, +- type_function_get_retval(func->type) ); ++ type_function_get_retval(func->declspec.type) ); + } + else + { + const var_t *var; +- if (!type_get_function_args(func->type)) ++ if (!type_function_get_args(func->declspec.type)) + return; +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var ); + } + } +@@ -4597,57 +4629,62 @@ void declare_stub_args( FILE *file, int indent, const var_t *func ) + { + int in_attr, out_attr; + int i = 0; +- const var_t *var = type_function_get_retval(func->type); ++ const var_t *var = type_function_get_retval(func->declspec.type); + + /* declare return value */ +- if (!is_void(var->type)) ++ if (!is_void(var->declspec.type)) + { +- print_file(file, indent, "%s", ""); +- write_type_decl(file, var->type, var->name); +- fprintf(file, ";\n"); ++ if (is_context_handle(var->declspec.type)) ++ print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); ++ else ++ { ++ print_file(file, indent, "%s", ""); ++ write_declspec_decl(file, &var->declspec, var->name); ++ fprintf(file, ";\n"); ++ } + } + +- if (!type_get_function_args(func->type)) ++ if (!type_function_get_args(func->declspec.type)) + return; + +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + { + in_attr = is_attr(var->attrs, ATTR_IN); + out_attr = is_attr(var->attrs, ATTR_OUT); + if (!out_attr && !in_attr) + in_attr = 1; + +- if (is_context_handle(var->type)) ++ if (is_context_handle(var->declspec.type)) + print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); + else + { +- if (!in_attr && !is_conformant_array(var->type)) ++ if (!in_attr && !is_conformant_array(var->declspec.type)) + { +- type_t *type_to_print; ++ const decl_spec_t *declspec_to_print; + char name[16]; + print_file(file, indent, "%s", ""); +- if (type_get_type(var->type) == TYPE_ARRAY && +- !type_array_is_decl_as_ptr(var->type)) +- type_to_print = var->type; ++ if (type_get_type(var->declspec.type) == TYPE_ARRAY && ++ !type_array_is_decl_as_ptr(var->declspec.type)) ++ declspec_to_print = &var->declspec; + else +- type_to_print = type_pointer_get_ref(var->type); ++ declspec_to_print = type_pointer_get_ref(var->declspec.type); + sprintf(name, "_W%u", i++); +- write_type_decl(file, type_to_print, name); ++ write_declspec_decl(file, declspec_to_print, name); + fprintf(file, ";\n"); + } + + print_file(file, indent, "%s", ""); +- write_type_decl_left(file, var->type); ++ write_declspec_decl_left(file, &var->declspec); + fprintf(file, " "); +- if (type_get_type(var->type) == TYPE_ARRAY && +- !type_array_is_decl_as_ptr(var->type)) { ++ if (type_get_type(var->declspec.type) == TYPE_ARRAY && ++ !type_array_is_decl_as_ptr(var->declspec.type)) { + fprintf(file, "(*%s)", var->name); + } else + fprintf(file, "%s", var->name); +- write_type_right(file, var->type, FALSE); ++ write_type_right(file, var->declspec.type, FALSE); + fprintf(file, ";\n"); + +- if (decl_indirect(var->type)) ++ if (decl_indirect(var->declspec.type)) + print_file(file, indent, "void *_p_%s;\n", var->name); + } + } +@@ -4661,10 +4698,10 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char + const var_t *var; + type_t *ref; + +- if (!type_get_function_args(func->type)) ++ if (!type_function_get_args(func->declspec.type)) + return; + +- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) ++ LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + { + in_attr = is_attr(var->attrs, ATTR_IN); + out_attr = is_attr(var->attrs, ATTR_OUT); +@@ -4675,7 +4712,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char + { + print_file(file, indent, "%s%s", local_var_prefix, var->name); + +- switch (typegen_detect_type(var->type, var->attrs, TDT_IGNORE_STRINGS)) ++ switch (typegen_detect_type(var->declspec.type, var->attrs, TDT_IGNORE_STRINGS)) + { + case TGT_CTXT_HANDLE_POINTER: + fprintf(file, " = NdrContextHandleInitialize(\n"); +@@ -4684,15 +4721,15 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char + var->typestring_offset); + break; + case TGT_ARRAY: +- if (type_array_has_conformance(var->type)) ++ if (type_array_has_conformance(var->declspec.type)) + { + unsigned int size; + type_t *type; + + fprintf(file, " = NdrAllocate(&__frame->_StubMsg, "); +- for (type = var->type; ++ for (type = var->declspec.type; + is_array(type) && type_array_has_conformance(type); +- type = type_array_get_element(type)) ++ type = type_array_get_element_type(type)) + { + write_expr(file, type_array_get_conformance(type), TRUE, + TRUE, NULL, NULL, local_var_prefix); +@@ -4702,9 +4739,9 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char + fprintf(file, "%u);\n", size); + + print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name); +- for (type = var->type; ++ for (type = var->declspec.type; + is_array(type) && type_array_has_conformance(type); +- type = type_array_get_element(type)) ++ type = type_array_get_element_type(type)) + { + write_expr(file, type_array_get_conformance(type), TRUE, + TRUE, NULL, NULL, local_var_prefix); +@@ -4718,7 +4755,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char + break; + case TGT_POINTER: + fprintf(file, " = &%s_W%u;\n", local_var_prefix, i); +- ref = type_pointer_get_ref(var->type); ++ ref = type_pointer_get_ref_type(var->declspec.type); + switch (typegen_detect_type(ref, var->attrs, TDT_IGNORE_STRINGS)) + { + case TGT_BASIC: +@@ -4738,7 +4775,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char + print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i); + break; + } +- ref = type_array_get_element(ref); ++ ref = type_array_get_element_type(ref); + /* fall through */ + case TGT_STRUCT: + case TGT_UNION: +@@ -4771,14 +4808,14 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun + const char *var_decl, int add_retval ) + { + var_t *retval = type_function_get_retval( func ); +- const var_list_t *args = type_get_function_args( func ); ++ const var_list_t *args = type_function_get_args( func ); + const var_t *arg; + int needs_packing; + unsigned int align = 0; + + if (args) + LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) +- if (!is_array( arg->type )) type_memsize_and_alignment( arg->type, &align ); ++ if (!is_array( arg->declspec.type )) type_memsize_and_alignment( arg->declspec.type, &align ); + + needs_packing = (align > pointer_size); + +@@ -4790,26 +4827,26 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun + if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) + { + print_file(file, 2, "%s", ""); +- write_type_left( file, (type_t *)arg->type, NAME_DEFAULT, TRUE ); +- if (needs_space_after( arg->type )) fputc( ' ', file ); +- if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); ++ write_declspec_left( file, &arg->declspec, NAME_DEFAULT, TRUE ); ++ 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 ); + + /* FIXME: should check for large args being passed by pointer */ + align = 0; +- if (is_array( arg->type ) || is_ptr( arg->type )) align = pointer_size; +- else type_memsize_and_alignment( arg->type, &align ); ++ if (is_array( arg->declspec.type ) || is_ptr( arg->declspec.type )) align = pointer_size; ++ else type_memsize_and_alignment( arg->declspec.type, &align ); + + if (align >= pointer_size) + fprintf( file, "%s;\n", arg->name ); + else + fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size ); + } +- if (add_retval && !is_void( retval->type )) ++ if (add_retval && !is_void( retval->declspec.type )) + { + print_file(file, 2, "%s", ""); +- write_type_decl( file, retval->type, retval->name ); +- if (is_array( retval->type ) || is_ptr( retval->type ) || +- type_memsize( retval->type ) == pointer_size) ++ write_declspec_decl( file, &retval->declspec, retval->name ); ++ if (is_array( retval->declspec.type ) || is_ptr( retval->declspec.type ) || ++ type_memsize( retval->declspec.type ) == pointer_size) + fprintf( file, ";\n" ); + else + fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size ); +@@ -4821,7 +4858,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun + + void write_pointer_checks( FILE *file, int indent, const var_t *func ) + { +- const var_list_t *args = type_get_function_args( func->type ); ++ const var_list_t *args = type_function_get_args( func->declspec.type ); + const var_t *var; + + if (!args) return; +@@ -4854,10 +4891,11 @@ int write_expr_eval_routines(FILE *file, const char *iface) + } + else + { ++ decl_spec_t declspec; + print_file(file, 1, "%s", ""); +- write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); ++ write_declspec_left(file, init_declspec(&declspec, (type_t*)eval->cont_type), NAME_DEFAULT, TRUE); + fprintf(file, " *%s = (", var_name); +- write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); ++ write_declspec_left(file, init_declspec(&declspec, (type_t*)eval->cont_type), NAME_DEFAULT, TRUE); + fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); + } + print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ +@@ -4951,9 +4989,10 @@ error: + void write_client_call_routine( FILE *file, const type_t *iface, const var_t *func, + const char *prefix, unsigned int proc_offset ) + { +- type_t *rettype = type_function_get_rettype( func->type ); ++ const decl_spec_t *retdeclspec = type_function_get_retdeclspec(func->declspec.type); ++ type_t *rettype = retdeclspec->type; + int has_ret = !is_void( rettype ); +- const var_list_t *args = type_get_function_args( func->type ); ++ const var_list_t *args = type_function_get_args( func->declspec.type ); + const var_t *arg; + int len, needs_params = 0; + +@@ -4964,7 +5003,7 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu + if (needs_params) + { + if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n" ); +- write_func_param_struct( file, iface, func->type, "__params", FALSE ); ++ write_func_param_struct( file, iface, func->declspec.type, "__params", FALSE ); + if (is_object( iface )) print_file( file, 1, "__params.This = This;\n" ); + if (args) + LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) +@@ -5001,7 +5040,7 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu + if (has_ret) + { + print_file( file, 1, "return (" ); +- write_type_decl_left(file, rettype); ++ write_declspec_decl_left(file, retdeclspec); + fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" ); + } + print_file( file, 0, "}\n\n"); +@@ -5029,7 +5068,7 @@ void write_exceptions( FILE *file ) + fprintf( file, " EXCEPTION_REGISTRATION_RECORD frame; \\n"); + fprintf( file, " __filter_func filter; \\n"); + fprintf( file, " __finally_func finally; \\n"); +- fprintf( file, " sigjmp_buf jmp; \\n"); ++ fprintf( file, " __wine_jmp_buf jmp; \\n"); + fprintf( file, " DWORD code; \\n"); + fprintf( file, " unsigned char abnormal_termination; \\n"); + fprintf( file, " unsigned char filter_level; \\n"); +@@ -5049,13 +5088,13 @@ void write_exceptions( FILE *file ) + fprintf( file, " __wine_pop_frame( &exc_frame->frame );\n"); + fprintf( file, " }\n"); + fprintf( file, " exc_frame->filter_level = 0;\n"); +- fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n"); ++ fprintf( file, " __wine_longjmp( &exc_frame->jmp, 1 );\n"); + fprintf( file, "}\n"); + fprintf( file, "\n"); +- fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n"); +- fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); +- fprintf( file, " CONTEXT *context,\n"); +- fprintf( file, " EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n"); ++ fprintf( file, "static DWORD __cdecl __widl_exception_handler( EXCEPTION_RECORD *record,\n"); ++ fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); ++ fprintf( file, " CONTEXT *context,\n"); ++ fprintf( file, " EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n"); + fprintf( file, "{\n"); + fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)frame;\n"); + fprintf( file, "\n"); +@@ -5075,7 +5114,7 @@ void write_exceptions( FILE *file ) + fprintf( file, "}\n"); + fprintf( file, "\n"); + fprintf( file, "#define RpcTryExcept \\n"); +- fprintf( file, " if (!sigsetjmp( __frame->jmp, 0 )) \\n"); ++ fprintf( file, " if (!__wine_setjmpex( &__frame->jmp, &__frame->frame )) \\n"); + fprintf( file, " { \\n"); + fprintf( file, " if (!__frame->finally_level) \\n" ); + fprintf( file, " __wine_push_frame( &__frame->frame ); \\n"); +diff --git a/mingw-w64-tools/widl/src/typelib.c b/mingw-w64-tools/widl/src/typelib.c +index 9b1de2c8..2c2b1276 100644 +--- a/mingw-w64-tools/widl/src/typelib.c ++++ b/mingw-w64-tools/widl/src/typelib.c +@@ -97,9 +97,9 @@ static unsigned short builtin_vt(const type_t *t) + { + const type_t *elem_type; + if (is_array(t)) +- elem_type = type_array_get_element(t); ++ elem_type = type_array_get_element_type(t); + else +- elem_type = type_pointer_get_ref(t); ++ elem_type = type_pointer_get_ref_type(t); + if (type_get_type(elem_type) == TYPE_BASIC) + { + switch (type_basic_get_type(elem_type)) +@@ -129,7 +129,8 @@ unsigned short get_type_vt(type_t *t) + if (vt) return vt; + } + +- if (type_is_alias(t) && is_attr(t->attrs, ATTR_PUBLIC)) ++ if (type_is_alias(t) && ++ (is_attr(t->attrs, ATTR_PUBLIC) || is_attr(t->attrs, ATTR_WIREMARSHAL))) + return VT_USERDEFINED; + + switch (type_get_type(t)) { +@@ -169,7 +170,7 @@ unsigned short get_type_vt(type_t *t) + else + return VT_I8; + case TYPE_BASIC_INT3264: +- if (typelib_kind == SYS_WIN64) ++ if (pointer_size == 8) + { + if (type_basic_get_sign(t) > 0) + return VT_UI8; +@@ -198,7 +199,7 @@ unsigned short get_type_vt(type_t *t) + case TYPE_ARRAY: + if (type_array_is_decl_as_ptr(t)) + { +- if (match(type_array_get_element(t)->name, "SAFEARRAY")) ++ if (match(type_array_get_element_type(t)->name, "SAFEARRAY")) + return VT_SAFEARRAY; + return VT_PTR; + } +diff --git a/mingw-w64-tools/widl/src/typetree.c b/mingw-w64-tools/widl/src/typetree.c +index b93806be..f52b785f 100644 +--- a/mingw-w64-tools/widl/src/typetree.c ++++ b/mingw-w64-tools/widl/src/typetree.c +@@ -30,12 +30,16 @@ + #include "typetree.h" + #include "header.h" + +-type_t *duptype(type_t *t, int dupname) ++/* this function is only used in declare_var in parser.y, see FIXME note */ ++type_t *dup_pointer_type(type_t *t) + { +- type_t *d = alloc_type(); ++ type_t *d; + ++ assert(is_ptr(t) && t->details.pointer.def_fc != FC_RP); ++ ++ d = alloc_type(); + *d = *t; +- if (dupname && t->name) ++ if (t->name) + d->name = xstrdup(t->name); + + return d; +@@ -49,7 +53,6 @@ type_t *make_type(enum type_type type) + t->type_type = type; + t->attrs = NULL; + t->c_name = NULL; +- t->orig = NULL; + memset(&t->details, 0, sizeof(t->details)); + t->typestring_offset = 0; + t->ptrdesc = 0; +@@ -137,7 +140,7 @@ type_t *type_new_function(var_list_t *args) + if (args) + { + arg = LIST_ENTRY(list_head(args), var_t, entry); +- if (list_count(args) == 1 && !arg->name && arg->type && type_get_type(arg->type) == TYPE_VOID) ++ if (list_count(args) == 1 && !arg->name && arg->declspec.type && type_get_type(arg->declspec.type) == TYPE_VOID) + { + list_remove(&arg->entry); + free(arg); +@@ -147,7 +150,7 @@ type_t *type_new_function(var_list_t *args) + } + if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry) + { +- if (arg->type && type_get_type(arg->type) == TYPE_VOID) ++ if (arg->declspec.type && type_get_type(arg->declspec.type) == TYPE_VOID) + error_loc("argument '%s' has void type\n", arg->name); + if (!arg->name) + { +@@ -178,35 +181,29 @@ type_t *type_new_function(var_list_t *args) + return t; + } + +-type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs) ++type_t *type_new_pointer(unsigned char pointer_default, type_t *ref) + { + type_t *t = make_type(TYPE_POINTER); + t->details.pointer.def_fc = pointer_default; +- t->details.pointer.ref = ref; +- t->attrs = attrs; ++ t->details.pointer.ref.type = ref; + return t; + } + +-type_t *type_new_alias(type_t *t, const char *name) ++type_t *type_new_alias(const decl_spec_t *ds, const char *name) + { +- type_t *a = duptype(t, 0); +- ++ type_t *a = make_type(ds->type->type_type); + a->name = xstrdup(name); + a->attrs = NULL; +- a->orig = t; ++ a->details.alias.aliasee = *ds; + a->is_alias = TRUE; +- /* for pointer types */ +- a->details = t->details; +- init_loc_info(&a->loc_info); +- + return a; + } + + type_t *type_new_module(char *name) + { + type_t *type = get_type(TYPE_MODULE, name, NULL, 0); +- if (type->type_type != TYPE_MODULE || type->defined) +- error_loc("%s: redefinition error; original definition was at %s:%d\n", ++ if (type->type_type != TYPE_MODULE || type_is_defined(type)) ++ error_loc("BAZ %s: redefinition error; original definition was at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + type->name = name; + return type; +@@ -215,15 +212,15 @@ type_t *type_new_module(char *name) + type_t *type_new_coclass(char *name) + { + type_t *type = get_type(TYPE_COCLASS, name, NULL, 0); +- if (type->type_type != TYPE_COCLASS || type->defined) +- error_loc("%s: redefinition error; original definition was at %s:%d\n", ++ if (type->type_type != TYPE_COCLASS || type_is_defined(type)) ++ error_loc("BING %s: redefinition error; original definition was at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + type->name = name; + return type; + } + + +-type_t *type_new_array(const char *name, type_t *element, int declptr, ++type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr, + unsigned int dim, expr_t *size_is, expr_t *length_is, + unsigned char ptr_default_fc) + { +@@ -235,7 +232,9 @@ type_t *type_new_array(const char *name, type_t *element, int declptr, + t->details.array.size_is = size_is; + else + t->details.array.dim = dim; +- t->details.array.elem = element; ++ if (element) { ++ t->details.array.elem = *element; ++ } + t->details.array.ptr_def_fc = ptr_default_fc; + return t; + } +@@ -273,80 +272,99 @@ type_t *type_new_void(void) + + type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums) + { +- type_t *tag_type = name ? find_type(name, namespace, tsENUM) : NULL; +- type_t *t = make_type(TYPE_ENUM); +- t->name = name; +- t->namespace = namespace; +- +- if (tag_type && tag_type->details.enumeration) +- t->details.enumeration = tag_type->details.enumeration; +- else if (defined) ++ type_t *t = NULL; ++ ++ if (name) ++ t = find_type(name, namespace, tsENUM); ++ ++ if (!t) + { +- t->details.enumeration = xmalloc(sizeof(*t->details.enumeration)); +- t->details.enumeration->enums = enums; +- t->defined = TRUE; ++ t = make_type(TYPE_ENUM); ++ t->name = name; ++ t->namespace = namespace; ++ if (name) ++ reg_type(t, name, namespace, tsENUM); + } + +- if (name) ++ if (!type_is_defined(t)) + { + if (defined) +- reg_type(t, name, namespace, tsENUM); ++ { ++ t->details.enumeration = xmalloc(sizeof(*t->details.enumeration)); ++ t->details.enumeration->enums = enums; ++ t->defined = TRUE; ++ } + else ++ { + add_incomplete(t); ++ } + } ++ + return t; + } + + type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields) + { +- type_t *tag_type = name ? find_type(name, namespace, tsSTRUCT) : NULL; +- type_t *t; +- +- /* avoid creating duplicate typelib type entries */ +- if (tag_type && do_typelib) return tag_type; ++ type_t *t = NULL; + +- t = make_type(TYPE_STRUCT); +- t->name = name; +- t->namespace = namespace; ++ if (name) ++ t = find_type(name, namespace, tsSTRUCT); + +- if (tag_type && tag_type->details.structure) +- t->details.structure = tag_type->details.structure; +- else if (defined) ++ if (!t) + { +- t->details.structure = xmalloc(sizeof(*t->details.structure)); +- t->details.structure->fields = fields; +- t->defined = TRUE; ++ t = make_type(TYPE_STRUCT); ++ t->name = name; ++ t->namespace = namespace; ++ if (name) ++ reg_type(t, name, namespace, tsSTRUCT); + } +- if (name) ++ ++ if (!type_is_defined(t)) + { + if (defined) +- reg_type(t, name, namespace, tsSTRUCT); ++ { ++ t->details.structure = xmalloc(sizeof(*t->details.structure)); ++ t->details.structure->fields = fields; ++ t->defined = TRUE; ++ } + else ++ { + add_incomplete(t); ++ } + } ++ + return t; + } + + type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields) + { +- type_t *tag_type = name ? find_type(name, NULL, tsUNION) : NULL; +- type_t *t = make_type(TYPE_UNION); +- t->name = name; +- if (tag_type && tag_type->details.structure) +- t->details.structure = tag_type->details.structure; +- else if (defined) ++ type_t *t = NULL; ++ ++ if (name) ++ t = find_type(name, NULL, tsUNION); ++ ++ if (!t) + { +- t->details.structure = xmalloc(sizeof(*t->details.structure)); +- t->details.structure->fields = fields; +- t->defined = TRUE; ++ t = make_type(TYPE_UNION); ++ t->name = name; ++ if (name) ++ reg_type(t, name, NULL, tsUNION); + } +- if (name) ++ ++ if (!type_is_defined(t)) + { + if (defined) +- reg_type(t, name, NULL, tsUNION); ++ { ++ t->details.structure = xmalloc(sizeof(*t->details.structure)); ++ t->details.structure->fields = fields; ++ t->defined = TRUE; ++ } + else ++ { + add_incomplete(t); ++ } + } ++ + return t; + } + +@@ -354,7 +372,7 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio + { + type_t *t = get_type(TYPE_ENCAPSULATED_UNION, name, NULL, tsUNION); + if (!union_field) union_field = make_var( xstrdup("tagged_union") ); +- union_field->type = type_new_nonencapsulated_union(NULL, TRUE, cases); ++ union_field->declspec.type = type_new_nonencapsulated_union(NULL, TRUE, cases); + t->details.structure = xmalloc(sizeof(*t->details.structure)); + t->details.structure->fields = append_var( NULL, switch_field ); + t->details.structure->fields = append_var( t->details.structure->fields, union_field ); +@@ -430,7 +448,7 @@ static int compute_method_indexes(type_t *iface) + { + var_t *func = stmt->u.var; + if (!is_callas(func->attrs)) +- func->type->details.function->idx = idx++; ++ func->declspec.type->details.function->idx = idx++; + } + + return idx; +@@ -438,6 +456,7 @@ static int compute_method_indexes(type_t *iface) + + void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts) + { ++ assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE); + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = NULL; + iface->details.iface->disp_methods = NULL; +@@ -451,6 +470,7 @@ void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stm + + void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods) + { ++ assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE); + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = props; + iface->details.iface->disp_methods = methods; +@@ -465,6 +485,7 @@ void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *met + + void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface) + { ++ assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE); + dispiface->details.iface = xmalloc(sizeof(*dispiface->details.iface)); + dispiface->details.iface->disp_props = NULL; + dispiface->details.iface->disp_methods = NULL; +@@ -479,6 +500,7 @@ void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface) + + void type_module_define(type_t *module, statement_list_t *stmts) + { ++ assert(type_get_type_detect_alias(module) == TYPE_MODULE); + if (module->details.module) error_loc("multiple definition error\n"); + module->details.module = xmalloc(sizeof(*module->details.module)); + module->details.module->stmts = stmts; +@@ -487,6 +509,7 @@ void type_module_define(type_t *module, statement_list_t *stmts) + + type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces) + { ++ assert(type_get_type_detect_alias(coclass) == TYPE_COCLASS); + coclass->details.coclass.ifaces = ifaces; + coclass->defined = TRUE; + return coclass; +diff --git a/mingw-w64-tools/widl/src/typetree.h b/mingw-w64-tools/widl/src/typetree.h +index fc134cd5..96fcae8d 100644 +--- a/mingw-w64-tools/widl/src/typetree.h ++++ b/mingw-w64-tools/widl/src/typetree.h +@@ -30,10 +30,10 @@ enum name_type { + }; + + type_t *type_new_function(var_list_t *args); +-type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs); +-type_t *type_new_alias(type_t *t, const char *name); ++type_t *type_new_pointer(unsigned char pointer_default, type_t *ref); ++type_t *type_new_alias(const decl_spec_t *aliasee, const char *name); + type_t *type_new_module(char *name); +-type_t *type_new_array(const char *name, type_t *element, int declptr, ++type_t *type_new_array(const char* name, const decl_spec_t *element, int declptr, + unsigned int dim, expr_t *size_is, expr_t *length_is, + unsigned char ptr_default_fc); + type_t *type_new_basic(enum type_basic_type basic_type); +@@ -53,14 +53,38 @@ type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces); + int type_is_equal(const type_t *type1, const type_t *type2); + const char *type_get_name(const type_t *type, enum name_type name_type); + +-/* FIXME: shouldn't need to export this */ +-type_t *duptype(type_t *t, int dupname); ++/* copy pointer type to deal with need for duplicate typeformat strings */ ++type_t *dup_pointer_type(type_t *t); ++ ++#define STATEMENTS_FOR_EACH_FUNC(stmt, stmts) \ ++ if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) \ ++ if (stmt->type == STMT_DECLARATION && stmt->u.var->declspec.stgclass == STG_NONE && \ ++ type_get_type_detect_alias(stmt->u.var->declspec.type) == TYPE_FUNCTION) ++ ++static inline enum type_type type_get_type_detect_alias(const type_t *type) ++{ ++ if (type->is_alias) ++ return TYPE_ALIAS; ++ return type->type_type; ++} ++ ++static inline int statements_has_func(const statement_list_t *stmts) ++{ ++ const statement_t *stmt; ++ int has_func = 0; ++ STATEMENTS_FOR_EACH_FUNC(stmt, stmts) ++ { ++ has_func = 1; ++ break; ++ } ++ return has_func; ++} + + /* un-alias the type until finding the non-alias type */ + static inline type_t *type_get_real_type(const type_t *type) + { + if (type->is_alias) +- return type_get_real_type(type->orig); ++ return type_get_real_type(type->details.alias.aliasee.type); + else + return (type_t *)type; + } +@@ -105,9 +129,14 @@ static inline var_t *type_function_get_retval(const type_t *type) + return type->details.function->retval; + } + ++static inline const decl_spec_t *type_function_get_retdeclspec(const type_t *type) ++{ ++ return &type_function_get_retval(type)->declspec; ++} ++ + static inline type_t *type_function_get_rettype(const type_t *type) + { +- return type_function_get_retval(type)->type; ++ return type_function_get_retdeclspec(type)->type; + } + + static inline var_list_t *type_enum_get_values(const type_t *type) +@@ -142,7 +171,7 @@ static inline var_list_t *type_union_get_cases(const type_t *type) + if (type_type == TYPE_ENCAPSULATED_UNION) + { + const var_t *uv = LIST_ENTRY(list_tail(type->details.structure->fields), const var_t, entry); +- return uv->type->details.structure->fields; ++ return uv->declspec.type->details.structure->fields; + } + else + return type->details.structure->fields; +@@ -250,11 +279,16 @@ static inline expr_t *type_array_get_variance(const type_t *type) + return type->details.array.length_is; + } + +-static inline type_t *type_array_get_element(const type_t *type) ++static inline const decl_spec_t *type_array_get_element(const type_t *type) + { + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_ARRAY); +- return type->details.array.elem; ++ return &type->details.array.elem; ++} ++ ++static inline type_t *type_array_get_element_type(const type_t *type) ++{ ++ return type_array_get_element(type)->type; + } + + static inline int type_array_is_decl_as_ptr(const type_t *type) +@@ -276,10 +310,15 @@ static inline int type_is_alias(const type_t *type) + return type->is_alias; + } + +-static inline type_t *type_alias_get_aliasee(const type_t *type) ++static inline const decl_spec_t *type_alias_get_aliasee(const type_t *type) + { + assert(type_is_alias(type)); +- return type->orig; ++ return &type->details.alias.aliasee; ++} ++ ++static inline type_t *type_alias_get_aliasee_type(const type_t *type) ++{ ++ return type_alias_get_aliasee(type)->type; + } + + static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) +@@ -289,11 +328,16 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) + return type->details.coclass.ifaces; + } + +-static inline type_t *type_pointer_get_ref(const type_t *type) ++static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) + { + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_POINTER); +- return type->details.pointer.ref; ++ return &type->details.pointer.ref; ++} ++ ++static inline type_t *type_pointer_get_ref_type(const type_t *type) ++{ ++ return type_pointer_get_ref(type)->type; + } + + static inline unsigned char type_pointer_get_default_fc(const type_t *type) +@@ -317,4 +361,54 @@ static inline const expr_t *type_bitfield_get_bits(const type_t *type) + return type->details.bitfield.bits; + } + ++/* gets pointer to details_t union with the assumption the caller wants to write to it ++ * so assert if we're actually dealing with an alias and writing to the details would ++ * overwrite the alias_details ++ */ ++static inline details_t *type_get_details(type_t* type) ++{ ++ assert(!type_is_alias(type)); ++ return &type->details; ++} ++ ++/* const overload of type_get_details */ ++ ++static inline const details_t *type_get_const_details(const type_t* type) ++{ ++ assert(!type_is_alias(type)); ++ return &type->details; ++} ++ ++static inline int type_is_pointerish(const type_t *type) ++{ ++ type = type_get_real_type(type); ++ return type_get_type(type) == TYPE_ARRAY || type_get_type(type) == TYPE_POINTER; ++} ++ ++static inline type_t * type_get_pointer_chain_tail(const type_t *type) ++{ ++ type_t *pointee = NULL; ++ type_t *pointer = type_get_real_type(type); ++ ++ if (type_get_type(pointer) == TYPE_ARRAY) ++ { ++ pointee = type_array_get_element_type(pointer); ++ } ++ else if (type_get_type(pointer) == TYPE_POINTER) ++ { ++ pointee = type_pointer_get_ref_type(pointer); ++ } ++ else ++ { ++ assert(FALSE); ++ } ++ ++ if (type_is_pointerish(pointee)) ++ { ++ return type_get_pointer_chain_tail(pointee); ++ } ++ ++ return pointee; ++} ++ + #endif /* WIDL_TYPE_TREE_H */ +diff --git a/mingw-w64-tools/widl/src/widl.c b/mingw-w64-tools/widl/src/widl.c +index 1af42509..8542e518 100644 +--- a/mingw-w64-tools/widl/src/widl.c ++++ b/mingw-w64-tools/widl/src/widl.c +@@ -44,11 +44,6 @@ + #include "header.h" + #include "pathtools.h" + +-/* future options to reserve characters for: */ +-/* A = ACF input filename */ +-/* J = do not search standard include path */ +-/* w = select win16/win32 output (?) */ +- + static const char usage[] = + "Usage: widl [options...] infile.idl\n" + " or: widl [options...] --dlldata-only name1 [name2...]\n" +@@ -64,7 +59,7 @@ static const char usage[] = + " -H file Name of header file (default is infile.h)\n" + " -I path Set include search dir to path (multiple -I allowed)\n" + " --local-stubs=file Write empty stubs for call_as/local methods to file\n" +-" -m32, -m64 Set the kind of typelib to build (Win32 or Win64)\n" ++" -m32, -m64 Set the target architecture (Win32 or Win64)\n" + " -N Do not preprocess input\n" + " --oldnames Use old naming conventions\n" + " -o, --output=NAME Set the output file name\n" +@@ -82,8 +77,7 @@ static const char usage[] = + " -u Generate interface identifiers file\n" + " -V Print version and exit\n" + " -W Enable pedantic warnings\n" +-" --win32 Only generate 32-bit code\n" +-" --win64 Only generate 64-bit code\n" ++" --win32, --win64 Set the target architecture (Win32 or Win64)\n" + " --win32-align n Set win32 structure alignment to 'n'\n" + " --win64-align n Set win64 structure alignment to 'n'\n" + "Debug level 'n' is a bitmask with following meaning:\n" +@@ -98,6 +92,20 @@ static const char usage[] = + static const char version_string[] = "Wine IDL Compiler version " PACKAGE_VERSION "\n" + "Copyright 2002 Ove Kaaven\n"; + ++#ifdef __i386__ ++enum target_cpu target_cpu = CPU_x86; ++#elif defined(__x86_64__) ++enum target_cpu target_cpu = CPU_x86_64; ++#elif defined(__powerpc__) ++enum target_cpu target_cpu = CPU_POWERPC; ++#elif defined(__arm__) ++enum target_cpu target_cpu = CPU_ARM; ++#elif defined(__aarch64__) ++enum target_cpu target_cpu = CPU_ARM64; ++#else ++#error Unsupported CPU ++#endif ++ + int debuglevel = DEBUGLEVEL_NONE; + int parser_debug, yy_flex_debug; + +@@ -114,8 +122,6 @@ int do_idfile = 0; + int do_dlldata = 0; + static int no_preprocess = 0; + int old_names = 0; +-int do_win32 = 1; +-int do_win64 = 1; + int win32_packing = 8; + int win64_packing = 8; + int winrt_mode = 0; +@@ -148,7 +154,6 @@ int line_number = 1; + static FILE *idfile; + + unsigned int pointer_size = 0; +-syskind_t typelib_kind = sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32; + + time_t now; + +@@ -188,6 +193,7 @@ static const struct option long_options[] = { + { "prefix-client", 1, NULL, PREFIX_CLIENT_OPTION }, + { "prefix-server", 1, NULL, PREFIX_SERVER_OPTION }, + { "robust", 0, NULL, ROBUST_OPTION }, ++ { "target", 0, NULL, 'b' }, + { "winrt", 0, NULL, RT_OPTION }, + { "win32", 0, NULL, WIN32_OPTION }, + { "win64", 0, NULL, WIN64_OPTION }, +@@ -269,20 +275,25 @@ static void set_target( const char *target ) + { + static const struct + { +- const char *name; +- syskind_t kind; ++ const char *name; ++ enum target_cpu cpu; + } cpu_names[] = + { +- { "i386", SYS_WIN32 }, +- { "i486", SYS_WIN32 }, +- { "i586", SYS_WIN32 }, +- { "i686", SYS_WIN32 }, +- { "i786", SYS_WIN32 }, +- { "amd64", SYS_WIN64 }, +- { "x86_64", SYS_WIN64 }, +- { "powerpc", SYS_WIN32 }, +- { "arm", SYS_WIN32 }, +- { "aarch64", SYS_WIN64 } ++ { "i386", CPU_x86 }, ++ { "i486", CPU_x86 }, ++ { "i586", CPU_x86 }, ++ { "i686", CPU_x86 }, ++ { "i786", CPU_x86 }, ++ { "amd64", CPU_x86_64 }, ++ { "x86_64", CPU_x86_64 }, ++ { "powerpc", CPU_POWERPC }, ++ { "arm", CPU_ARM }, ++ { "armv5", CPU_ARM }, ++ { "armv6", CPU_ARM }, ++ { "armv7", CPU_ARM }, ++ { "armv7a", CPU_ARM }, ++ { "arm64", CPU_ARM64 }, ++ { "aarch64", CPU_ARM64 }, + }; + + unsigned int i; +@@ -296,7 +307,7 @@ static void set_target( const char *target ) + { + if (!strcmp( cpu_names[i].name, spec )) + { +- typelib_kind = cpu_names[i].kind; ++ target_cpu = cpu_names[i].cpu; + free( spec ); + return; + } +@@ -484,6 +495,7 @@ static void write_id_data_stmts(const statement_list_t *stmts) + uuid = get_attrp(type->attrs, ATTR_UUID); + write_id_guid(idfile, "IID", is_attr(type->attrs, ATTR_DISPINTERFACE) ? "DIID" : "IID", + type->name, uuid); ++ assert(type_get_type_detect_alias(type) == TYPE_INTERFACE); + if (type->details.iface->async_iface) + { + uuid = get_attrp(type->details.iface->async_iface->attrs, ATTR_UUID); +@@ -606,12 +618,10 @@ int main(int argc,char *argv[]) + use_abi_namespace = 1; + break; + case WIN32_OPTION: +- do_win32 = 1; +- do_win64 = 0; ++ pointer_size = 4; + break; + case WIN64_OPTION: +- do_win32 = 0; +- do_win64 = 1; ++ pointer_size = 8; + break; + case WIN32_ALIGN_OPTION: + win32_packing = strtol(optarg, NULL, 0); +@@ -664,8 +674,8 @@ int main(int argc,char *argv[]) + wpp_add_include_path(optarg); + break; + case 'm': +- if (!strcmp( optarg, "32" )) typelib_kind = SYS_WIN32; +- else if (!strcmp( optarg, "64" )) typelib_kind = SYS_WIN64; ++ if (!strcmp( optarg, "32" )) pointer_size = 4; ++ else if (!strcmp( optarg, "64" )) pointer_size = 8; + break; + case 'N': + no_preprocess = 1; +@@ -726,6 +736,7 @@ int main(int argc,char *argv[]) + } + + #ifdef DEFAULT_INCLUDE_DIR ++ wpp_add_include_path(DEFAULT_INCLUDE_DIR); + char exe_path[PATH_MAX]; + get_executable_path (argv[0], &exe_path[0], sizeof (exe_path) / sizeof (exe_path[0])); + char * rel_to_includedir = get_relative_path (DEFAULT_BINDIR, DEFAULT_INCLUDE_DIR); +@@ -739,6 +750,26 @@ int main(int argc,char *argv[]) + wpp_add_include_path(relocated_default_include_dir); + #endif + ++ switch (target_cpu) ++ { ++ case CPU_x86: ++ if (pointer_size == 8) target_cpu = CPU_x86_64; ++ else pointer_size = 4; ++ break; ++ case CPU_x86_64: ++ if (pointer_size == 4) target_cpu = CPU_x86; ++ else pointer_size = 8; ++ break; ++ case CPU_ARM64: ++ if (pointer_size == 4) error( "Cannot build 32-bit code for this CPU\n" ); ++ pointer_size = 8; ++ break; ++ default: ++ if (pointer_size == 8) error( "Cannot build 64-bit code for this CPU\n" ); ++ pointer_size = 4; ++ break; ++ } ++ + /* if nothing specified, try to guess output type from the output file name */ + if (output_name && do_everything && !do_header && !do_typelib && !do_proxies && + !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata) +diff --git a/mingw-w64-tools/widl/src/widl.h b/mingw-w64-tools/widl/src/widl.h +index 118e2245..4f4252e3 100644 +--- a/mingw-w64-tools/widl/src/widl.h ++++ b/mingw-w64-tools/widl/src/widl.h +@@ -45,8 +45,6 @@ extern int do_regscript; + extern int do_idfile; + extern int do_dlldata; + extern int old_names; +-extern int do_win32; +-extern int do_win64; + extern int win32_packing; + extern int win64_packing; + extern int winrt_mode; +@@ -76,6 +74,13 @@ extern time_t now; + extern int line_number; + extern int char_number; + ++enum target_cpu ++{ ++ CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_LAST = CPU_ARM64 ++}; ++ ++extern enum target_cpu target_cpu; ++ + enum stub_mode + { + MODE_Os, /* inline stubs */ +diff --git a/mingw-w64-tools/widl/src/widltypes.h b/mingw-w64-tools/widl/src/widltypes.h +index 08584de5..b9c5a07d 100644 +--- a/mingw-w64-tools/widl/src/widltypes.h ++++ b/mingw-w64-tools/widl/src/widltypes.h +@@ -40,6 +40,7 @@ typedef struct _attr_t attr_t; + typedef struct _expr_t expr_t; + typedef struct _type_t type_t; + typedef struct _var_t var_t; ++typedef struct _decl_spec_t decl_spec_t; + typedef struct _declarator_t declarator_t; + typedef struct _ifref_t ifref_t; + typedef struct _typelib_entry_t typelib_entry_t; +@@ -80,7 +81,6 @@ enum attr_type + ATTR_CASE, + ATTR_CODE, + ATTR_COMMSTATUS, +- ATTR_CONST, /* const pseudo-attribute */ + ATTR_CONTEXTHANDLE, + ATTR_CONTROL, + ATTR_DECODE, +@@ -115,7 +115,6 @@ enum attr_type + ATTR_IMMEDIATEBIND, + ATTR_IMPLICIT_HANDLE, + ATTR_IN, +- ATTR_INLINE, + ATTR_INPUTSYNC, + ATTR_LENGTHIS, + ATTR_LIBLCID, +@@ -234,6 +233,18 @@ enum storage_class + STG_REGISTER, + }; + ++enum type_qualifier ++{ ++ TYPE_QUALIFIER_NONE = 0, ++ TYPE_QUALIFIER_CONST = 1, ++}; ++ ++enum function_specifier ++{ ++ FUNCTION_SPECIFIER_NONE, ++ FUNCTION_SPECIFIER_INLINE, ++}; ++ + enum statement_type + { + STMT_LIBRARY, +@@ -293,6 +304,14 @@ struct str_list_entry_t + struct list entry; + }; + ++struct _decl_spec_t ++{ ++ type_t *type; ++ enum storage_class stgclass; ++ enum type_qualifier typequalifier; ++ enum function_specifier funcspecifier; ++}; ++ + struct _attr_t { + enum attr_type type; + union { +@@ -356,7 +375,7 @@ struct array_details + { + expr_t *size_is; + expr_t *length_is; +- struct _type_t *elem; ++ struct _decl_spec_t elem; + unsigned int dim; + unsigned char ptr_def_fc; + unsigned char declptr; /* if declared as a pointer */ +@@ -376,7 +395,7 @@ struct basic_details + + struct pointer_details + { +- struct _type_t *ref; ++ struct _decl_spec_t ref; + unsigned char def_fc; + }; + +@@ -386,6 +405,11 @@ struct bitfield_details + const expr_t *bits; + }; + ++struct alias_details ++{ ++ struct _decl_spec_t aliasee; ++}; ++ + #define HASHMAX 64 + + struct namespace { +@@ -414,26 +438,28 @@ enum type_type + TYPE_BITFIELD, + }; + ++typedef union _details_t ++{ ++ struct struct_details *structure; ++ struct enumeration_details *enumeration; ++ struct func_details *function; ++ struct iface_details *iface; ++ struct module_details *module; ++ struct array_details array; ++ struct coclass_details coclass; ++ struct basic_details basic; ++ struct pointer_details pointer; ++ struct bitfield_details bitfield; ++ struct alias_details alias; ++} details_t; ++ + struct _type_t { + const char *name; + struct namespace *namespace; + enum type_type type_type; + attr_list_t *attrs; +- union +- { +- struct struct_details *structure; +- struct enumeration_details *enumeration; +- struct func_details *function; +- struct iface_details *iface; +- struct module_details *module; +- struct array_details array; +- struct coclass_details coclass; +- struct basic_details basic; +- struct pointer_details pointer; +- struct bitfield_details bitfield; +- } details; ++ details_t details; + const char *c_name; +- type_t *orig; /* dup'd types */ + unsigned int typestring_offset; + unsigned int ptrdesc; /* used for complex structs */ + int typelib_idx; +@@ -449,14 +475,20 @@ struct _type_t { + + struct _var_t { + char *name; +- type_t *type; ++ decl_spec_t declspec; + attr_list_t *attrs; + expr_t *eval; +- enum storage_class stgclass; + unsigned int procstring_offset; + unsigned int typestring_offset; + + struct _loc_info_t loc_info; ++ /* this flag indicates that this var's type (or pointed to type in the case of ++ * array or pointer) was not fully defined at the time of declaration. ++ * If this flag is set to TRUE then the type definition will not be written for this var ++ * If this flag is set to FALSE then the type definition will only be written if it has not ++ * been written yet (determined by the type_t's 'written' flag) ++ */ ++ int declonly : 1; + + /* parser-internal */ + struct list entry; +@@ -464,7 +496,7 @@ struct _var_t { + + struct _declarator_t { + var_t *var; +- type_t *type; ++ decl_spec_t declspec; + type_t *func_type; + expr_t *bits; + +@@ -497,6 +529,7 @@ struct _importinfo_t { + }; + + struct _importlib_t { ++ int offset; + char *name; + + int version; +@@ -539,6 +572,13 @@ struct _statement_t { + typelib_t *lib; + type_list_t *type_list; + } u; ++ /* this flag indicates that this statement's type (or pointed to type in the case of ++ * array or pointer) was not fully defined at the time of declaration. ++ * If this flag is set to TRUE then the type definition will not be written for this statement ++ * If this flag is set to FALSE then the type definition will only be written if it has not ++ * been written yet (determined by the type_t's 'written' flag) ++ */ ++ int declonly : 1; + }; + + struct _warning_t { +@@ -553,11 +593,10 @@ typedef enum { + SYS_WIN64 + } syskind_t; + +-extern syskind_t typelib_kind; + extern user_type_list_t user_type_list; + extern context_handle_list_t context_handle_list; + extern generic_handle_list_t generic_handle_list; +-void check_for_additional_prototype_types(const var_list_t *list); ++void check_for_additional_prototype_types(type_t *type); + + void init_types(void); + type_t *alloc_type(void); +@@ -568,6 +607,12 @@ void clear_all_offsets(void); + #define tsSTRUCT 2 + #define tsUNION 3 + ++static inline const char* ts_to_str(int t) ++{ ++ static const char* strings[] = {"tsNULL", "tsENUM", "tsSTRUCT", "tsUNION"}; ++ return strings[t]; ++} ++ + var_t *find_const(const char *name, int f); + type_t *find_type(const char *name, struct namespace *namespace, int t); + type_t *make_type(enum type_type type); +@@ -582,38 +627,18 @@ void init_loc_info(loc_info_t *); + + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix); + +-static inline var_list_t *type_get_function_args(const type_t *func_type) +-{ +- return func_type->details.function->args; +-} +- +-static inline enum type_type type_get_type_detect_alias(const type_t *type) +-{ +- if (type->is_alias) +- return TYPE_ALIAS; +- return type->type_type; +-} +- +-#define STATEMENTS_FOR_EACH_FUNC(stmt, stmts) \ +- if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) \ +- if (stmt->type == STMT_DECLARATION && stmt->u.var->stgclass == STG_NONE && \ +- type_get_type_detect_alias(stmt->u.var->type) == TYPE_FUNCTION) +- +-static inline int statements_has_func(const statement_list_t *stmts) ++static inline int is_global_namespace(const struct namespace *namespace) + { +- const statement_t *stmt; +- int has_func = 0; +- STATEMENTS_FOR_EACH_FUNC(stmt, stmts) +- { +- has_func = 1; +- break; +- } +- return has_func; ++ return !namespace->name; + } + +-static inline int is_global_namespace(const struct namespace *namespace) ++static inline decl_spec_t *init_declspec(decl_spec_t *declspec, type_t *type) + { +- return !namespace->name; ++ declspec->type = type; ++ declspec->stgclass = STG_NONE; ++ declspec->typequalifier=TYPE_QUALIFIER_NONE; ++ declspec->funcspecifier=FUNCTION_SPECIFIER_NONE; ++ return declspec; + } + + #endif +diff --git a/mingw-w64-tools/widl/src/write_msft.c b/mingw-w64-tools/widl/src/write_msft.c +index 88a80d12..da7ce89d 100644 +--- a/mingw-w64-tools/widl/src/write_msft.c ++++ b/mingw-w64-tools/widl/src/write_msft.c +@@ -702,15 +702,15 @@ static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo) + + guid_idx = ctl2_alloc_guid(typelib, &guid); + +- alloc_importfile(typelib, guid_idx, importlib->version&0xffff, +- importlib->version>>16, importlib->name); ++ importlib->offset = alloc_importfile(typelib, guid_idx, importlib->version & 0xffff, ++ importlib->version >> 16, importlib->name); + } + + if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) { + MSFT_ImpInfo impinfo; + + impinfo.flags = importinfo->flags; +- impinfo.oImpFile = 0; ++ impinfo.oImpFile = importlib->offset; + + if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) { + MSFT_GuidEntry guid; +@@ -763,7 +763,7 @@ static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration); + static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion); + static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls); + static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface); +- ++static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef); + + /**************************************************************************** + * encode_type +@@ -862,8 +862,8 @@ static int encode_type( + case VT_PTR: + { + int next_vt; +- for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref(type)) { +- next_vt = get_type_vt(type_pointer_get_ref(type)); ++ for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref_type(type)) { ++ next_vt = get_type_vt(type_pointer_get_ref_type(type)); + if (next_vt != 0) + break; + } +@@ -871,7 +871,7 @@ static int encode_type( + if (next_vt == 0) + next_vt = VT_VOID; + +- encode_type(typelib, next_vt, type_pointer_get_ref(type), ++ encode_type(typelib, next_vt, type_pointer_get_ref_type(type), + &target_type, &child_size); + /* these types already have an implicit pointer, so we don't need to + * add another */ +@@ -912,10 +912,10 @@ static int encode_type( + + case VT_SAFEARRAY: + { +- type_t *element_type = type_alias_get_aliasee(type_array_get_element(type)); ++ type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(type)); + int next_vt = get_type_vt(element_type); + +- encode_type(typelib, next_vt, type_alias_get_aliasee(type_array_get_element(type)), ++ encode_type(typelib, next_vt, type_alias_get_aliasee_type(type_array_get_element_type(type)), + &target_type, &child_size); + + for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { +@@ -966,33 +966,61 @@ static int encode_type( + } + else + { +- /* typedef'd types without public attribute aren't included in the typelib */ +- while (type_is_alias(type) && !is_attr(type->attrs, ATTR_PUBLIC)) +- type = type_alias_get_aliasee(type); ++ /* typedef'd types without public attribute aren't included in the typelib ++ * typedef'd types with a wire_marshal attribute must be included ++ */ ++ while (type_is_alias(type)) ++ { ++ if (is_attr(type->attrs, ATTR_WIREMARSHAL)) ++ { ++ type = get_attrp(type->attrs, ATTR_WIREMARSHAL); ++ break; ++ } ++ else if(!is_attr(type->attrs, ATTR_PUBLIC)) ++ { ++ type = type_alias_get_aliasee_type(type); ++ } ++ else ++ { ++ break; ++ } ++ } + + chat("encode_type: VT_USERDEFINED - adding new type %s, real type %d\n", + type->name, type_get_type(type)); + +- switch (type_get_type(type)) ++ /* we've either fully resolved the typedef down to an actual type or ++ * we must include the typedef because it's a wiremarshal (or public) type ++ */ ++ if (type_is_alias(type)) + { +- case TYPE_STRUCT: +- add_structure_typeinfo(typelib, type); +- break; +- case TYPE_INTERFACE: +- add_interface_typeinfo(typelib, type); +- break; +- case TYPE_ENUM: +- add_enum_typeinfo(typelib, type); +- break; +- case TYPE_UNION: +- add_union_typeinfo(typelib, type); +- break; +- case TYPE_COCLASS: +- add_coclass_typeinfo(typelib, type); +- break; +- default: +- error("encode_type: VT_USERDEFINED - unhandled type %d\n", +- type_get_type(type)); ++ add_typedef_typeinfo(typelib, type); ++ } ++ else ++ { ++ switch (type_get_type(type)) ++ { ++ case TYPE_STRUCT: ++ add_structure_typeinfo(typelib, type); ++ break; ++ case TYPE_INTERFACE: ++ add_interface_typeinfo(typelib, type); ++ break; ++ case TYPE_ENUM: ++ add_enum_typeinfo(typelib, type); ++ break; ++ /* fallthrough */ ++ case TYPE_UNION: ++ case TYPE_ENCAPSULATED_UNION: ++ add_union_typeinfo(typelib, type); ++ break; ++ case TYPE_COCLASS: ++ add_coclass_typeinfo(typelib, type); ++ break; ++ default: ++ error("encode_type: VT_USERDEFINED - unhandled type %d\n", ++ type_get_type(type)); ++ } + } + + typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx]; +@@ -1056,7 +1084,7 @@ static int encode_var( + num_dims = 0; + for (atype = type; + is_array(atype) && !type_array_is_decl_as_ptr(atype); +- atype = type_array_get_element(atype)) ++ atype = type_array_get_element_type(atype)) + ++num_dims; + + chat("array with %d dimensions\n", num_dims); +@@ -1071,7 +1099,7 @@ static int encode_var( + arraydata += 2; + for (atype = type; + is_array(atype) && !type_array_is_decl_as_ptr(atype); +- atype = type_array_get_element(atype)) ++ atype = type_array_get_element_type(atype)) + { + arraydata[0] = type_array_get_dim(atype); + arraydata[1] = 0; +@@ -1093,7 +1121,7 @@ static int encode_var( + vt = get_type_vt(type); + if (vt == VT_PTR) { + type_t *ref = is_ptr(type) ? +- type_pointer_get_ref(type) : type_array_get_element(type); ++ type_pointer_get_ref_type(type) : type_array_get_element_type(type); + int skip_ptr = encode_var(typelib, ref, var, &target_type, &child_size); + + if(skip_ptr == 2) { +@@ -1114,7 +1142,7 @@ static int encode_var( + if (target_type & 0x80000000) { + mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF; + } else if (get_type_vt(ref) == VT_SAFEARRAY) { +- type_t *element_type = type_alias_get_aliasee(type_array_get_element(ref)); ++ type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(ref)); + mix_field = get_type_vt(element_type) | VT_ARRAY | VT_BYREF; + } else { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; +@@ -1204,7 +1232,7 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e + if (type_get_type(type) == TYPE_ENUM) { + vt = VT_I4; + } else if (is_ptr(type)) { +- vt = get_type_vt(type_pointer_get_ref(type)); ++ vt = get_type_vt(type_pointer_get_ref_type(type)); + if (vt == VT_USERDEFINED) + vt = VT_I4; + if (expr->cval) +@@ -1301,8 +1329,8 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) + return S_FALSE; + } + +- if (type_get_function_args(func->type)) +- LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) ++ if (type_function_get_args(func->declspec.type)) ++ LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry ) + { + num_params++; + if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { +@@ -1444,7 +1472,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) + + /* fill out the basic type information */ + typedata[0] = typedata_size | (index << 16); +- encode_var(typeinfo->typelib, type_function_get_rettype(func->type), func, ++ encode_var(typeinfo->typelib, type_function_get_rettype(func->declspec.type), func, + &typedata[1], &decoded_size); + typedata[2] = funcflags; + typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft; +@@ -1471,10 +1499,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) + warning("unknown number of optional attrs\n"); + } + +- if (type_get_function_args(func->type)) ++ if (type_function_get_args(func->declspec.type)) + { + i = 0; +- LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) ++ LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry ) + { + int paramflags = 0; + int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3; +@@ -1482,13 +1510,13 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) + + if(defaultdata) *defaultdata = -1; + +- encode_var(typeinfo->typelib, arg->type, arg, paramdata, &decoded_size); ++ encode_var(typeinfo->typelib, arg->declspec.type, arg, paramdata, &decoded_size); + if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { + switch(attr->type) { + case ATTR_DEFAULTVALUE: + { + paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */ +- write_default_value(typeinfo->typelib, arg->type, (expr_t *)attr->u.pval, defaultdata); ++ write_default_value(typeinfo->typelib, arg->declspec.type, (expr_t *)attr->u.pval, defaultdata); + break; + } + case ATTR_IN: +@@ -1572,10 +1600,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) + if(typeinfo->typekind == TKIND_MODULE) + namedata[9] |= 0x20; + +- if (type_get_function_args(func->type)) ++ if (type_function_get_args(func->declspec.type)) + { + i = 0; +- LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) ++ LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry ) + { + /* don't give the last arg of a [propput*] func a name */ + if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */)) +@@ -1697,8 +1725,8 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) + typeinfo->var_offsets[var_num] = offset; + + /* figure out type widths and whatnot */ +- var_datawidth = type_memsize_and_alignment(var->type, &var_alignment); +- encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_type_size); ++ var_datawidth = type_memsize_and_alignment(var->declspec.type, &var_alignment); ++ encode_var(typeinfo->typelib, var->declspec.type, var, &typedata[1], &var_type_size); + + /* pad out starting position to data width */ + typeinfo->datawidth += var_alignment - 1; +@@ -1977,6 +2005,7 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte + var_t *var; + msft_typeinfo_t *msft_typeinfo; + ++ assert(type_get_type_detect_alias(dispinterface) == TYPE_INTERFACE); + if (-1 < dispinterface->typelib_idx) + return; + +@@ -2181,7 +2210,7 @@ static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef) + if (-1 < tdef->typelib_idx) + return; + +- type = type_alias_get_aliasee(tdef); ++ type = type_alias_get_aliasee_type(tdef); + + if (!type->name || strcmp(tdef->name, type->name) != 0) + { +@@ -2297,6 +2326,7 @@ static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module) + const statement_t *stmt; + msft_typeinfo_t *msft_typeinfo; + ++ assert(type_get_type_detect_alias(module) == TYPE_MODULE); + if (-1 < module->typelib_idx) + return; + +@@ -2364,7 +2394,7 @@ static void add_entry(msft_typelib_t *typelib, const statement_t *stmt) + if (is_attr(type_entry->type->attrs, ATTR_PUBLIC)) + add_typedef_typeinfo(typelib, type_entry->type); + else +- add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type)); ++ add_type_typeinfo(typelib, type_alias_get_aliasee_type(type_entry->type)); + } + break; + } +@@ -2653,8 +2683,6 @@ int create_msft_typelib(typelib_t *typelib) + GUID midl_info_guid = {0xde77ba65,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; + char info_string[128]; + +- pointer_size = (typelib_kind == SYS_WIN64) ? 8 : 4; +- + msft = xmalloc(sizeof(*msft)); + memset(msft, 0, sizeof(*msft)); + msft->typelib = typelib; +@@ -2662,7 +2690,7 @@ int create_msft_typelib(typelib_t *typelib) + ctl2_init_header(msft); + ctl2_init_segdir(msft); + +- msft->typelib_header.varflags |= typelib_kind; ++ msft->typelib_header.varflags |= (pointer_size == 8) ? SYS_WIN64 : SYS_WIN32; + + /* + * The following two calls return an offset or -1 if out of memory. We diff --git a/projects/mingw-w64/build b/projects/mingw-w64/build index 4be660d..faa5997 100644 --- a/projects/mingw-w64/build +++ b/projects/mingw-w64/build @@ -52,6 +52,9 @@ cd /var/tmp/build/builddir/mingw-w64/mingw-w64-pthread make -j[% c("buildconf/num_procs") %] make install
+# patch mingw with widl fixes for #27503 ( https://trac.torproject.org/projects/tor/ticket/27503 ) +patch -p1 -d /var/tmp/build/[% project %]-[% c("version") %] < $rootdir/27503.patch + mkdir -p /var/tmp/build/builddir/mingw-w64/widl32 cd /var/tmp/build/builddir/mingw-w64/widl32 /var/tmp/build/[% project %]-[% c("version") %]/mingw-w64-tools/widl/configure \ diff --git a/projects/mingw-w64/config b/projects/mingw-w64/config index d0268cb..a2f0701 100644 --- a/projects/mingw-w64/config +++ b/projects/mingw-w64/config @@ -35,3 +35,4 @@ input_files: - name: binutils project: binutils - filename: libtool-sort.patch + - filename: 27503.patch