[PATCH] widl: Remove duptype function so type_t* can be directly compared

Richard Pospesel richard at torproject.org
Tue May 14 15:33:04 CDT 2019


Duplicated types made it impossible to avoid multiply defining user-
defined types (structs, enums, unions). The duptype function has been
removed and the remaining code refactored to no longer require it.
User-define types are now no longer duplicated in typetree.c
However, there is a bit of fallout from this:

Various type attributes (ATTR_EXTERN, ATTR_CONST, and ATTR_INLINE)
had to be removed from a type_t's attributes and placed on a
new struct _decl_type which itself owned a type_t. This decl_type_t is
now passed around in many functions previously expecting type_t.

The _type struct now includes a struct typedef_details in its details
union which has the type qualifier (const) info.

The bitfield_details struct also contains a decl_type_t rather than a
raw type_t pointer to correctly handle const bits.

Wine fully builds with these changes to widl, and all of the tests for
rpcrt4.dll and oleaut32.dll run with the same results.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47035
Signed-off-by: Richard Pospesel <richard at torproject.net>
---
As a side-effect, this patch also fixes:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47149
---
 tools/widl/client.c     |  53 ++--
 tools/widl/expr.c       |  14 +-
 tools/widl/header.c     | 248 +++++++++-------
 tools/widl/header.h     |  11 +-
 tools/widl/parser.y     | 415 ++++++++++++++++----------
 tools/widl/proxy.c      |  58 ++--
 tools/widl/server.c     |  19 +-
 tools/widl/typegen.c    | 624 +++++++++++++++++++++-------------------
 tools/widl/typelib.c    |   6 +-
 tools/widl/typetree.c   |  97 ++++---
 tools/widl/typetree.h   |  57 ++--
 tools/widl/widltypes.h  |  61 +++-
 tools/widl/write_msft.c |  56 ++--
 13 files changed, 984 insertions(+), 735 deletions(-)

diff --git a/tools/widl/client.c b/tools/widl/client.c
index fe88f5993c..aecbf3e00f 100644
--- a/tools/widl/client.c
+++ b/tools/widl/client.c
@@ -15,17 +15,17 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include "config.h"
 #include "wine/port.h"
- 
+
 #include <stdio.h>
 #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
 #include <string.h>
 #include <ctype.h>
 
@@ -47,41 +47,44 @@ static void print_client( const char *format, ... )
     va_list va;
     va_start(va, format);
     print(client, indent, format, va);
     va_end(va);
 }
 
 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->decltype.type->attrs, ATTR_CALLCONV);
+    const var_list_t *args = type_get_function_args(func->decltype.type);
+    decl_type_t *retdecltype = type_function_get_retdecltype(func->decltype.type);
 
     if (!callconv) callconv = "__cdecl";
-    write_type_decl_left(client, rettype);
+    write_decltype_decl_left(client, retdecltype);
+    if (func->decltype.funcspecifier == FUNCTION_SPECIFIER_INLINE) {
+        fprintf(client, " inline");
+    }
     fprintf(client, " %s ", callconv);
     fprintf(client, "%s%s(\n", prefix_client, get_name(func));
     indent++;
     if (args)
         write_args(client, args, iface->name, 0, TRUE);
     else
         print_client("void");
     fprintf(client, ")\n");
     indent--;
 }
 
 static void write_function_stub( const type_t *iface, const var_t *func,
                                  int method_count, unsigned int proc_offset )
 {
     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->decltype.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->decltype.type);
 
     if (is_interpreted_func( iface, func ))
     {
         write_client_func_decl( iface, func );
         write_client_call_routine( client, iface, func, iface->name, proc_offset );
         return;
     }
 
@@ -92,17 +95,17 @@ static void write_function_stub( const type_t *iface, const var_t *func,
     if (handle_var)
     {
         if (explicit_fc == FC_BIND_GENERIC)
             print_client("%s %s;\n",
                          get_explicit_generic_handle_type(handle_var)->name, handle_var->name );
         print_client("RPC_BINDING_HANDLE _Handle;\n");
     }
 
-    if (has_ret && decl_indirect(retval->type))
+    if (has_ret && decl_indirect(retval->decltype.type))
     {
         print_client("void *_p_%s;\n", retval->name);
     }
     indent--;
     print_client( "};\n\n" );
 
     print_client( "static void __finally_%s%s(", prefix_client, get_name(func) );
     print_client( " struct __frame_%s%s *__frame )\n{\n", prefix_client, get_name(func) );
@@ -131,28 +134,28 @@ static void write_function_stub( const type_t *iface, const var_t *func,
     fprintf(client, "{\n");
     indent++;
     print_client( "struct __frame_%s%s __f, * const __frame = &__f;\n", prefix_client, get_name(func) );
 
     /* declare return value */
     if (has_ret)
     {
         print_client("%s", "");
-        write_type_decl(client, retval->type, retval->name);
+        write_decltype_decl(client, (decl_type_t*)&retval->decltype, retval->name);
         fprintf(client, ";\n");
     }
     print_client("RPC_MESSAGE _RpcMessage;\n");
 
     if (handle_var)
     {
         print_client( "__frame->_Handle = 0;\n" );
         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->decltype.type))
     {
         print_client("__frame->_p_%s = &%s;\n", retval->name, retval->name);
     }
     fprintf(client, "\n");
 
     print_client( "RpcExceptionInit( 0, __finally_%s%s );\n", prefix_client, get_name(func) );
 
     if (has_full_pointer)
@@ -189,17 +192,17 @@ static void write_function_stub( const type_t *iface, const var_t *func,
                      get_explicit_generic_handle_type(handle_var)->name, handle_var->name);
         fprintf(client, "\n");
         break;
     case FC_BIND_CONTEXT:
     {
         /* 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->decltype.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",
                      is_ch_ptr ? "*" : "", handle_var->name);
         indent--;
         if (is_attr(handle_var->attrs, ATTR_IN) && !is_attr(handle_var->attrs, ATTR_OUT))
         {
             print_client("else\n");
@@ -252,19 +255,19 @@ static void write_function_stub( const type_t *iface, const var_t *func,
 
     /* unmarshall arguments */
     fprintf(client, "\n");
     write_remoting_arguments(client, indent, func, "", PASS_OUT, PHASE_UNMARSHAL);
 
     /* unmarshal return value */
     if (has_ret)
     {
-        if (decl_indirect(retval->type))
+        if (decl_indirect(retval->decltype.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->decltype.type) || is_array(retval->decltype.type))
             print_client("%s = 0;\n", retval->name);
         write_remoting_arguments(client, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL);
     }
 
     indent--;
     print_client("}\n");
     print_client("RpcFinally\n");
     print_client("{\n");
@@ -360,28 +363,28 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
 
     LIST_FOR_EACH_ENTRY( stmt, type_iface_get_stmts(iface), const statement_t, entry )
     {
         switch (stmt->type)
         {
         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->decltype.stgclass != STG_NONE
+                || type_get_type_detect_alias(stmt->u.var->decltype.type) != TYPE_FUNCTION)
                 continue;
             write_function_stub( iface, func, method_count++, *proc_offset );
             *proc_offset += get_size_procformatstring_func( iface, func );
             break;
         }
         case STMT_TYPEDEF:
         {
-            const type_list_t *type_entry;
-            for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next)
-                write_serialize_functions(client, type_entry->type, iface);
+            const typedef_list_t *typedef_entry;
+            for (typedef_entry = stmt->u.typedef_list; typedef_entry; typedef_entry = typedef_entry->next)
+                write_serialize_functions(client, typedef_entry->var->decltype.type, iface);
             break;
         }
         default:
             break;
         }
     }
 }
 
@@ -483,17 +486,17 @@ static void write_clientinterfacedecl(type_t *iface)
 
 
 static void write_implicithandledecl(type_t *iface)
 {
     const var_t *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
 
     if (implicit_handle)
     {
-        write_type_decl( client, implicit_handle->type, implicit_handle->name );
+        write_decltype_decl( client, (decl_type_t*)&implicit_handle->decltype, implicit_handle->name );
         fprintf(client, ";\n\n");
     }
 }
 
 
 static void init_client(void)
 {
     if (client) return;
@@ -527,29 +530,29 @@ static void write_client_ifaces(const statement_list_t *stmts, int expr_eval_rou
 
             fprintf(client, "/*****************************************************************************\n");
             fprintf(client, " * %s interface\n", iface->name);
             fprintf(client, " */\n");
             fprintf(client, "\n");
 
             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->decltype.stgclass == STG_NONE &&
+                    type_get_type_detect_alias(stmt2->u.var->decltype.type) == TYPE_FUNCTION)
                 {
                     needs_stub = 1;
                     break;
                 }
                 if (stmt2->type == STMT_TYPEDEF)
                 {
-                    const type_list_t *type_entry;
-                    for (type_entry = stmt2->u.type_list; type_entry; type_entry = type_entry->next)
+                    const typedef_list_t *typedef_entry;
+                    for (typedef_entry = stmt2->u.typedef_list; typedef_entry; typedef_entry = typedef_entry->next)
                     {
-                        if (is_attr(type_entry->type->attrs, ATTR_ENCODE)
-                            || is_attr(type_entry->type->attrs, ATTR_DECODE))
+                        if (is_attr(typedef_entry->var->decltype.type->attrs, ATTR_ENCODE)
+                            || is_attr(typedef_entry->var->decltype.type->attrs, ATTR_DECODE))
                         {
                             needs_stub = 1;
                             break;
                         }
                     }
                     if (needs_stub)
                         break;
                 }
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index 2ed4aff6ad..48a78c1c0c 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -189,20 +189,20 @@ expr_t *make_exprs(enum expr_type type, char *val)
     return e;
 }
 
 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->decltype.stgclass != STG_NONE && var->decltype.stgclass != STG_REGISTER)
         error_loc("invalid storage class for type expression\n");
 
-    tref = var->type;
+    tref = var->decltype.type;
 
     e = xmalloc(sizeof(expr_t));
     e->type = type;
     e->ref = expr;
     e->u.tref = tref;
     e->is_const = FALSE;
     if (type == EXPR_SIZEOF)
     {
@@ -469,25 +469,25 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
             assert(0);
             break;
         }
     }
 
     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
         if (field->name && !strcmp(identifier, field->name))
         {
-            type = field->type;
+            type = field->decltype.type;
             *found_in_cont_type = 1;
             break;
         }
 
     if (!type)
     {
         var_t *const_var = find_const(identifier, 0);
-        if (const_var) type = const_var->type;
+        if (const_var) type = const_var->decltype.type;
     }
 
     return type;
 }
 
 static int is_valid_member_operand(const type_t *type)
 {
     switch (type_get_type(type))
@@ -575,20 +575,20 @@ 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);
         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 " : "",
                            expr_loc->attr ? expr_loc->attr : "");
         break;
     case EXPR_CAST:
         result = resolve_expression(expr_loc, cont_type, e->ref);
         result.type = e->u.tref;
@@ -660,17 +660,17 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
         result.is_variable = FALSE;
         break;
     }
     case EXPR_ARRAY:
         result = resolve_expression(expr_loc, cont_type, e->ref);
         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",
                                expr_loc->attr ? " for attribute " : "",
                                expr_loc->attr ? expr_loc->attr : "");
         }
         else
             error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
diff --git a/tools/widl/header.c b/tools/widl/header.c
index f618e02f3d..e536c2167c 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -38,17 +38,17 @@
 #include "typelib.h"
 
 static int indentation = 0;
 static int is_object_interface = 0;
 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_def_or_decl(FILE *f, decl_type_t *dt, int field, const char *name);
 
 static void indent(FILE *h, int delta)
 {
   int c;
   if (delta < 0) indentation += delta;
   for (c=0; c<indentation; c++) fprintf(h, "    ");
   if (delta > 0) indentation += delta;
 }
@@ -64,39 +64,39 @@ static void write_line(FILE *f, int delta, const char *fmt, ...)
 }
 
 int is_ptrchain_attr(const var_t *var, enum attr_type t)
 {
     if (is_attr(var->attrs, t))
         return 1;
     else
     {
-        type_t *type = var->type;
+        type_t *type = var->decltype.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;
         }
     }
 }
 
 int is_aliaschain_attr(const type_t *type, enum attr_type attr)
 {
     const type_t *t = type;
     for (;;)
     {
         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;
     }
 }
 
 int is_attr(const attr_list_t *list, enum attr_type t)
 {
     const attr_t *attr;
     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
@@ -115,16 +115,25 @@ void *get_attrp(const attr_list_t *list, enum attr_type t)
 unsigned int get_attrv(const attr_list_t *list, enum attr_type t)
 {
     const attr_t *attr;
     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
         if (attr->type == t) return attr->u.ival;
     return 0;
 }
 
+decl_type_t *get_attrdt(const attr_list_t *list, enum attr_type t)
+{
+    const attr_t *attr;
+    assert(t == ATTR_WIREMARSHAL);
+    if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
+        if (attr->type == t) return (decl_type_t*)&attr->u.dtval;
+    return NULL;
+}
+
 static void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
 {
   if (!uuid) return;
   fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
         "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
         guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
         uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
         uuid->Data4[6], uuid->Data4[7]);
@@ -199,38 +208,38 @@ static void write_fields(FILE *h, var_list_t *fields)
     unsigned nameless_struct_cnt = 0, nameless_struct_i = 0, nameless_union_cnt = 0, nameless_union_i = 0;
     const char *name;
     char buf[32];
     var_t *v;
 
     if (!fields) return;
 
     LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) {
-        if (!v || !v->type) continue;
+        if (!v || !v->decltype.type) continue;
 
-        switch(type_get_type_detect_alias(v->type)) {
+        switch(type_get_type_detect_alias(v->decltype.type)) {
         case TYPE_STRUCT:
         case TYPE_ENCAPSULATED_UNION:
             nameless_struct_cnt++;
             break;
         case TYPE_UNION:
             nameless_union_cnt++;
             break;
         default:
             ;
         }
     }
 
     LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) {
-        if (!v || !v->type) continue;
+        if (!v || !v->decltype.type) continue;
 
         indent(h, 0);
         name = v->name;
 
-        switch(type_get_type_detect_alias(v->type)) {
+        switch(type_get_type_detect_alias(v->decltype.type)) {
         case TYPE_STRUCT:
         case TYPE_ENCAPSULATED_UNION:
             if(!v->name) {
                 fprintf(h, "__C89_NAMELESS ");
                 if(nameless_struct_cnt == 1) {
                     name = "__C89_NAMELESSSTRUCTNAME";
                 }else if(nameless_struct_i < 5 /* # of supporting macros */) {
                     sprintf(buf, "__C89_NAMELESSSTRUCTNAME%d", ++nameless_struct_i);
@@ -247,17 +256,17 @@ static void write_fields(FILE *h, var_list_t *fields)
                     sprintf(buf, "__C89_NAMELESSUNIONNAME%d", ++nameless_union_i);
                     name = buf;
                 }
             }
             break;
         default:
             ;
         }
-        write_type_def_or_decl(h, v->type, TRUE, name);
+        write_type_def_or_decl(h, &v->decltype, TRUE, name);
         fprintf(h, ";\n");
     }
 }
 
 static void write_enums(FILE *h, var_list_t *enums, const char *enum_name)
 {
   var_t *v;
   if (!enums) return;
@@ -289,27 +298,29 @@ static void write_pointer_left(FILE *h, type_t *ref)
 {
     if (needs_space_after(ref))
         fprintf(h, " ");
     if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref))
         fprintf(h, "(");
     fprintf(h, "*");
 }
 
-void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
+void write_decltype_left(FILE* h, decl_type_t *dt, enum name_type name_type, int declonly)
 {
   const char *name;
+  type_t *t = dt->type;
 
   if (!h) return;
 
   name = type_get_name(t, name_type);
 
-  if (is_attr(t->attrs, ATTR_CONST) &&
-      (type_is_alias(t) || !is_ptr(t)))
+  if ((dt->typequalifier == TYPE_QUALIFIER_CONST) &&
+      (type_is_alias(t) || !is_ptr(t))) {
     fprintf(h, "const ");
+  }
 
   if (type_is_alias(t)) fprintf(h, "%s", t->name);
   else {
     switch (type_get_type_detect_alias(t)) {
       case TYPE_ENUM:
         if (!declonly && t->defined && !t->written) {
           if (name) fprintf(h, "enum %s {\n", name);
           else fprintf(h, "enum {\n");
@@ -346,29 +357,33 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
           write_fields(h, type_union_get_cases(t));
           indent(h, -1);
           fprintf(h, "}");
         }
         else fprintf(h, "union %s", t->name ? t->name : "");
         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_decltype_left(h, type_pointer_get_ref(t), name_type, declonly);
+        write_pointer_left(h, type_pointer_get_ref_type(t));
+
+        if (dt->typequalifier == TYPE_QUALIFIER_CONST) {
+          fprintf(h, "const ");
+        }
+
         break;
       }
       case TYPE_ARRAY:
         if (t->name && type_array_is_decl_as_ptr(t))
           fprintf(h, "%s", t->name);
         else
         {
-          write_type_left(h, type_array_get_element(t), name_type, declonly);
+          write_decltype_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:
         if (type_basic_get_type(t) != TYPE_BASIC_INT32 &&
             type_basic_get_type(t) != TYPE_BASIC_INT64 &&
             type_basic_get_type(t) != TYPE_BASIC_LONG &&
             type_basic_get_type(t) != TYPE_BASIC_HYPER)
         {
@@ -418,55 +433,61 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
       case TYPE_MODULE:
       case TYPE_COCLASS:
         fprintf(h, "%s", t->name);
         break;
       case TYPE_VOID:
         fprintf(h, "void");
         break;
       case TYPE_BITFIELD:
-        write_type_left(h, type_bitfield_get_field(t), name_type, declonly);
+          write_decltype_left(h, type_bitfield_get_field(t), name_type, declonly);
         break;
       case TYPE_ALIAS:
       case TYPE_FUNCTION:
         /* handled elsewhere */
         assert(0);
         break;
     }
   }
 }
 
+void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
+{
+  decl_type_t dt;
+  write_decltype_left(h, init_decltype(&dt, t), name_type, declonly);
+}
+
 void write_type_right(FILE *h, type_t *t, int is_field)
 {
   if (!h) return;
   if (type_is_alias(t)) return;
 
   switch (type_get_type(t))
   {
   case TYPE_ARRAY:
   {
-    type_t *elem = type_array_get_element(t);
+    type_t *elemtype = 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))
+      if (!type_is_alias(elemtype) && is_array(elemtype) && !type_array_is_decl_as_ptr(elemtype))
         fprintf(h, ")");
     }
     else
     {
       if (is_conformant_array(t))
         fprintf(h, "[%s]", is_field ? "1" : "");
       else
         fprintf(h, "[%u]", type_array_get_dim(t));
     }
-    write_type_right(h, elem, FALSE);
+    write_type_right(h, elemtype, FALSE);
     break;
   }
   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);
     break;
   }
   case TYPE_BITFIELD:
     fprintf(h, " : %u", type_bitfield_get_bits(t)->cval);
     break;
@@ -480,40 +501,46 @@ void write_type_right(FILE *h, type_t *t, int is_field)
   case TYPE_MODULE:
   case TYPE_COCLASS:
   case TYPE_FUNCTION:
   case TYPE_INTERFACE:
     break;
   }
 }
 
-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, decl_type_t *dt, int is_field, int declonly, const char *name)
 {
+  type_t *t = dt->type;
   type_t *pt = NULL;
+  decl_type_t *dpt = NULL;
   int ptr_level = 0;
 
   if (!h) return;
 
   if (t) {
-    for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++)
+    for (dpt = dt; 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(dt->type) && dt->funcspecifier == FUNCTION_SPECIFIER_INLINE) {
+        fprintf(h, "inline ");
+      }
+      write_decltype_left(h, type_function_get_retdecltype(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);
+    } else {
+      write_decltype_left(h, dt, NAME_DEFAULT, declonly);
+    }
   }
 
   if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
 
   if (t) {
     if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
       const var_list_t *args = type_function_get_args(pt);
 
@@ -524,19 +551,19 @@ static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const c
       else
           fprintf(h, "void");
       fputc(')', h);
     } else
       write_type_right(h, t, is_field);
   }
 }
 
-static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name)
+static void write_type_def_or_decl(FILE *f, decl_type_t *dt, int field, const char *name)
 {
-  write_type_v(f, t, field, FALSE, name);
+  write_type_v(f, dt, field, FALSE, name);
 }
 
 static void write_type_definition(FILE *f, type_t *t)
 {
     int in_namespace = t->namespace && !is_global_namespace(t->namespace);
     int save_written = t->written;
 
     if(in_namespace) {
@@ -555,22 +582,28 @@ static void write_type_definition(FILE *f, type_t *t)
         write_type_left(f, t, NAME_C, FALSE);
         fprintf(f, ";\n");
         fprintf(f, "#endif\n\n");
     }
 }
 
 void write_type_decl(FILE *f, type_t *t, const char *name)
 {
-  write_type_v(f, t, FALSE, TRUE, name);
+  decl_type_t dt;
+  write_decltype_decl(f, init_decltype(&dt, t), name);
 }
 
-void write_type_decl_left(FILE *f, type_t *t)
+void write_decltype_decl(FILE *f, decl_type_t *dt, const char *name)
 {
-  write_type_left(f, t, NAME_DEFAULT, TRUE);
+  write_type_v(f, dt, FALSE, TRUE, name);
+}
+
+void write_decltype_decl_left(FILE *f, decl_type_t *dt)
+{
+  write_decltype_left(f, dt, NAME_DEFAULT, TRUE);
 }
 
 static int user_type_registered(const char *name)
 {
   user_type_t *ut;
   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
     if (!strcmp(name, ut->name))
       return 1;
@@ -597,18 +630,18 @@ static int generic_handle_registered(const char *name)
 
 unsigned int get_context_handle_offset( const type_t *type )
 {
     context_handle_t *ch;
     unsigned int index = 0;
 
     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 )
     {
         if (!strcmp( type->name, ch->name )) return index;
         index++;
     }
     error( "internal error: %s is not registered as a context handle\n", type->name );
@@ -617,18 +650,18 @@ unsigned int get_context_handle_offset( const type_t *type )
 
 unsigned int get_generic_handle_offset( const type_t *type )
 {
     generic_handle_t *gh;
     unsigned int index = 0;
 
     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 )
     {
         if (!strcmp( type->name, gh->name )) return index;
         index++;
     }
     error( "internal error: %s is not registered as a generic handle\n", type->name );
@@ -692,25 +725,25 @@ void check_for_additional_prototype_types(type_t *type)
       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->type);
+        check_for_additional_prototype_types(v->decltype.type);
     }
 
     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 if (is_array(type))
-      type = type_array_get_element(type);
+      type = type_array_get_element_type(type);
     else
       break;
   }
 }
 
 static int write_serialize_function_decl(FILE *header, const type_t *type)
 {
     write_serialize_functions(header, type, NULL);
@@ -722,33 +755,33 @@ static int serializable_exists(FILE *header, const type_t *type)
     return 0;
 }
 
 static int for_each_serializable(const statement_list_t *stmts, FILE *header,
                                  int (*proc)(FILE*, const type_t*))
 {
     statement_t *stmt, *iface_stmt;
     statement_list_t *iface_stmts;
-    const type_list_t *type_entry;
+    const typedef_list_t *typedef_entry;
 
     if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry )
     {
         if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE)
             continue;
 
         iface_stmts = type_iface_get_stmts(stmt->u.type);
         if (iface_stmts) LIST_FOR_EACH_ENTRY( iface_stmt, iface_stmts, statement_t, entry )
         {
             if (iface_stmt->type != STMT_TYPEDEF) continue;
-            for (type_entry = iface_stmt->u.type_list; type_entry; type_entry = type_entry->next)
+            for (typedef_entry = iface_stmt->u.typedef_list; typedef_entry; typedef_entry = typedef_entry->next)
             {
-                if (!is_attr(type_entry->type->attrs, ATTR_ENCODE)
-                    && !is_attr(type_entry->type->attrs, ATTR_DECODE))
+                if (!is_attr(typedef_entry->var->decltype.type->attrs, ATTR_ENCODE)
+                    && !is_attr(typedef_entry->var->decltype.type->attrs, ATTR_DECODE))
                     continue;
-                if (!proc(header, type_entry->type))
+                if (!proc(header, typedef_entry->var->decltype.type))
                     return 0;
             }
         }
     }
 
     return 1;
 }
 
@@ -790,132 +823,132 @@ static void write_typedef(FILE *header, type_t *type)
 {
   fprintf(header, "typedef ");
   write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name);
   fprintf(header, ";\n");
 }
 
 int is_const_decl(const var_t *var)
 {
-  const type_t *t;
+  const decl_type_t *dt;
   /* 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 (dt = &var->decltype; ;)
   {
-    if (is_attr(t->attrs, ATTR_CONST))
+    if (dt->typequalifier == TYPE_QUALIFIER_CONST)
       return TRUE;
-    else if (is_ptr(t))
-      t = type_pointer_get_ref(t);
+    else if (is_ptr(dt->type))
+      dt = type_pointer_get_ref(dt->type);
     else break;
   }
   return FALSE;
 }
 
 static void write_declaration(FILE *header, const var_t *v)
 {
   if (is_const_decl(v) && v->eval)
   {
     fprintf(header, "#define %s (", v->name);
     write_expr(header, v->eval, 0, 1, NULL, NULL, "");
     fprintf(header, ")\n\n");
   }
   else
   {
-    switch (v->stgclass)
+    switch (v->decltype.stgclass)
     {
       case STG_NONE:
       case STG_REGISTER: /* ignored */
         break;
       case STG_STATIC:
         fprintf(header, "static ");
         break;
       case STG_EXTERN:
         fprintf(header, "extern ");
         break;
     }
-    write_type_def_or_decl(header, v->type, FALSE, v->name);
+    write_type_def_or_decl(header, (decl_type_t*)&v->decltype, FALSE, v->name);
     fprintf(header, ";\n\n");
   }
 }
 
 static void write_library(FILE *header, const typelib_t *typelib)
 {
   const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID);
   fprintf(header, "\n");
   write_guid(header, "LIBID", typelib->name, uuid);
   fprintf(header, "\n");
 }
 
 
 const type_t* get_explicit_generic_handle_type(const var_t* var)
 {
     const type_t *t;
-    for (t = var->type;
+    for (t = var->decltype.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;
     return NULL;
 }
 
 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_get_function_args( func->decltype.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->decltype.type ) == TYPE_BASIC && type_basic_get_type( var->decltype.type ) == TYPE_BASIC_HANDLE)
         {
             *explicit_fc = FC_BIND_PRIMITIVE;
             return var;
         }
         if (get_explicit_generic_handle_type( var ))
         {
             *explicit_fc = FC_BIND_GENERIC;
             return var;
         }
-        if (is_context_handle( var->type ))
+        if (is_context_handle( var->decltype.type ))
         {
             *explicit_fc = FC_BIND_CONTEXT;
             return var;
         }
     }
 
     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->decltype.type ) == TYPE_BASIC &&
+            type_basic_get_type( var->decltype.type ) == TYPE_BASIC_HANDLE)
             *implicit_fc = FC_BIND_PRIMITIVE;
         else
             *implicit_fc = FC_BIND_GENERIC;
         return var;
     }
 
     *implicit_fc = FC_AUTO_HANDLE;
     return NULL;
 }
 
 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->decltype.type)))
         return 1;
 
-    if (!type_get_function_args(func->type))
+    if (!type_get_function_args(func->decltype.type))
         return 0;
 
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->decltype.type), const var_t, entry )
         if (is_attr(var->attrs, ATTR_OUT))
             return 1;
 
     return 0;
 }
 
 
 /********** INTERFACES **********/
@@ -985,17 +1018,17 @@ static int is_override_method(const type_t *iface, const type_t *child, const va
   }
   while ((child = type_iface_get_inherit(child)) && child != iface);
 
   return 0;
 }
 
 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->decltype.type));
   return type == TYPE_STRUCT || type == TYPE_UNION ||
          type == TYPE_COCLASS || type == TYPE_INTERFACE;
 }
 
 static char *get_vtbl_entry_name(const type_t *iface, const var_t *func)
 {
   static char buff[255];
   if (is_inherited_method(iface, func))
@@ -1025,30 +1058,30 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t *
 
     if (is_override_method(iface, child, func))
       continue;
 
     if (!is_callas(func->attrs)) {
       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_get_function_args(func->decltype.type))
+          LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->decltype.type), const var_t, entry )
               fprintf(header, ",%s", arg->name);
       fprintf(header, ") ");
 
       if (is_aggregate_return(func))
       {
         fprintf(header, "%s_%s_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support\n", name, get_name(func));
         continue;
       }
 
       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_get_function_args(func->decltype.type))
+          LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->decltype.type), const var_t, entry )
               fprintf(header, ",%s", arg->name);
       fprintf(header, ")\n");
     }
   }
 }
 
 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent)
 {
@@ -1068,29 +1101,29 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
     if (count) {
         if (do_indent)
         {
             fprintf(h, ",\n");
             indent(h, 0);
         }
         else fprintf(h, ",");
     }
-    write_type_decl(h, arg->type, arg->name);
+    write_decltype_decl(h, (decl_type_t*)&arg->decltype, arg->name);
     if (method == 2) {
         const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE);
         if (expr) {
             const var_t *tail_arg;
 
             /* Output default value only if all following arguments also have default value. */
             LIST_FOR_EACH_ENTRY_REV( tail_arg, args, const var_t, entry ) {
                 if(tail_arg == arg) {
                     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->decltype.type) == VT_BSTR && expr->type == EXPR_STRLIT)
                     {
                         bstr = *expr;
                         bstr.type = EXPR_WSTRLIT;
                         expr = &bstr;
                     }
 
                     fprintf(h, " = ");
                     write_expr( h, expr, 0, 1, NULL, NULL, "" );
@@ -1109,67 +1142,67 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
 static void write_cpp_method_def(FILE *header, const type_t *iface)
 {
   const statement_t *stmt;
 
   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(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->decltype.type->attrs, ATTR_CALLCONV);
+      const var_list_t *args = type_get_function_args(func->decltype.type);
       const var_t *arg;
 
       if (!callconv) callconv = "STDMETHODCALLTYPE";
 
       if (is_aggregate_return(func)) {
         fprintf(header, "#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS\n");
 
         indent(header, 0);
         fprintf(header, "virtual ");
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.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_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.type));
         fprintf(header, " *__ret");
         --indentation;
         if (args) {
           fprintf(header, ",\n");
           write_args(header, args, iface->name, 2, TRUE);
         }
         fprintf(header, ") = 0;\n");
 
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.type));
         fprintf(header, " %s %s(\n", callconv, get_name(func));
         write_args(header, args, iface->name, 2, TRUE);
         fprintf(header, ")\n");
         indent(header, 0);
         fprintf(header, "{\n");
         ++indentation;
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.type));
         fprintf(header, " __ret;\n");
         indent(header, 0);
         fprintf(header, "return *%s(&__ret", get_name(func));
         if (args)
             LIST_FOR_EACH_ENTRY(arg, args, const var_t, entry)
                 fprintf(header, ", %s", arg->name);
         fprintf(header, ");\n");
         --indentation;
         indent(header, 0);
         fprintf(header, "}\n");
 
         fprintf(header, "#else\n");
       }
 
       indent(header, 0);
       fprintf(header, "virtual ");
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.type));
       fprintf(header, " %s %s(\n", callconv, get_name(func));
       write_args(header, args, iface->name, 2, TRUE);
       fprintf(header, ") = 0;\n");
 
       if (is_aggregate_return(func))
         fprintf(header, "#endif\n");
       fprintf(header, "\n");
     }
@@ -1196,35 +1229,35 @@ static void write_inline_wrappers(FILE *header, const type_t *iface, const type_
 
     if (is_override_method(iface, child, func))
       continue;
 
     if (!is_callas(func->attrs)) {
       const var_t *arg;
 
       fprintf(header, "static FORCEINLINE ");
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.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_get_function_args(func->decltype.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->decltype.type)) ? "" : "return ",
                 get_vtbl_entry_name(iface, func));
       } else {
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.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_get_function_args(func->decltype.type))
+          LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->decltype.type), const var_t, entry )
               fprintf(header, ",%s", arg->name);
       fprintf(header, ");\n");
       --indentation;
       fprintf(header, "}\n");
     }
   }
 }
 
@@ -1240,39 +1273,39 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char
   {
     const var_t *func = stmt->u.var;
     if (first_iface) {
       indent(header, 0);
       fprintf(header, "/*** %s methods ***/\n", iface->name);
       first_iface = 0;
     }
     if (!is_callas(func->attrs)) {
-      const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
+      const char *callconv = get_attrp(func->decltype.type->attrs, ATTR_CALLCONV);
       if (!callconv) callconv = "STDMETHODCALLTYPE";
       indent(header, 0);
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.type));
       if (is_aggregate_return(func))
         fprintf(header, " *");
       if (is_inherited_method(iface, func))
         fprintf(header, " (%s *%s_%s)(\n", callconv, iface->name, func->name);
       else
         fprintf(header, " (%s *%s)(\n", callconv, get_name(func));
       ++indentation;
       indent(header, 0);
       fprintf(header, "%s *This", name);
       if (is_aggregate_return(func)) {
         fprintf(header, ",\n");
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.type));
         fprintf(header, " *__ret");
       }
       --indentation;
-      if (type_get_function_args(func->type)) {
+      if (type_get_function_args(func->decltype.type)) {
         fprintf(header, ",\n");
-        write_args(header, type_get_function_args(func->type), name, 0, TRUE);
+        write_args(header, type_get_function_args(func->decltype.type), name, 0, TRUE);
       }
       fprintf(header, ");\n");
       fprintf(header, "\n");
     }
   }
 }
 
 static void write_c_method_def(FILE *header, const type_t *iface)
@@ -1289,22 +1322,22 @@ static void write_method_proto(FILE *header, const type_t *iface)
 {
   const statement_t *stmt;
 
   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(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->decltype.type->attrs, ATTR_CALLCONV);
       if (!callconv) callconv = "STDMETHODCALLTYPE";
       /* proxy prototype */
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_decltype_decl_left(header, type_function_get_retdecltype(func->decltype.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_get_function_args(func->decltype.type), iface->name, 1, TRUE);
       fprintf(header, ");\n");
       /* stub prototype */
       fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func));
       fprintf(header, "    IRpcStubBuffer* This,\n");
       fprintf(header, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
       fprintf(header, "    DWORD* pdwStubPhase);\n");
     }
@@ -1327,41 +1360,41 @@ static void write_locals(FILE *fp, const type_t *iface, int body)
     if (cas) {
       const statement_t *stmt2 = NULL;
       STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface))
         if (!strcmp(get_name(stmt2->u.var), cas->name))
           break;
       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_decltype_decl_left(fp, type_function_get_retdecltype(m->decltype.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_get_function_args(m->decltype.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->decltype.type);
           fprintf(fp, "\n{\n");
           fprintf(fp, "    %s\n", comment);
           if (rt->name && strcmp(rt->name, "HRESULT") == 0)
             fprintf(fp, "    return E_NOTIMPL;\n");
           else if (type_get_type(rt) != TYPE_VOID) {
             fprintf(fp, "    ");
             write_type_decl(fp, rt, "rv");
             fprintf(fp, ";\n");
             fprintf(fp, "    memset(&rv, 0, sizeof rv);\n");
             fprintf(fp, "    return rv;\n");
           }
           fprintf(fp, "}\n\n");
         }
         else
           fprintf(fp, ";\n");
         /* stub prototype - use remotable prototype */
-        write_type_decl_left(fp, type_function_get_rettype(func->type));
+        write_decltype_decl_left(fp, type_function_get_retdecltype(func->decltype.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_get_function_args(func->decltype.type), iface->name, 1, TRUE);
         fprintf(fp, ")");
         if (body)
           /* Remotable methods must all return HRESULTs.  */
           fprintf(fp, "\n{\n    %s\n    return E_NOTIMPL;\n}\n\n", comment);
         else
           fprintf(fp, ";\n");
       }
       else
@@ -1397,25 +1430,28 @@ void write_local_stubs(const statement_list_t *stmts)
 
   write_local_stubs_stmts(local_stubs, stmts);
 
   fclose(local_stubs);
 }
 
 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->decltype.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_decltype_decl_left(header, type_function_get_retdecltype(fun->decltype.type));
+  if (fun->decltype.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_get_function_args(fun->decltype.type))
+    write_args(header, type_get_function_args(fun->decltype.type), iface->name, 0, TRUE);
   else
     fprintf(header, "    void");
   fprintf(header, ");\n\n");
 }
 
 static void write_forward(FILE *header, type_t *iface)
 {
   fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->c_name);
@@ -1531,17 +1567,17 @@ static void write_rpc_interface_start(FILE *header, const type_t *iface)
   fprintf(header, "/*****************************************************************************\n");
   fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
   fprintf(header, " */\n");
   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
   fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
   if (var)
   {
       fprintf(header, "extern ");
-      write_type_decl( header, var->type, var->name );
+      write_decltype_decl( header, (decl_type_t*)&var->decltype, var->name );
       fprintf(header, ";\n");
   }
   if (old_names)
   {
       fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
       fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
   }
   else
@@ -1727,30 +1763,30 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
       case STMT_PRAGMA:
         /* not included in header */
         break;
       case STMT_IMPORT:
         /* not processed here */
         break;
       case STMT_TYPEDEF:
       {
-        const type_list_t *type_entry = stmt->u.type_list;
-        for (; type_entry; type_entry = type_entry->next)
-	  write_typedef(header, type_entry->type);
+        const typedef_list_t *typedef_entry = stmt->u.typedef_list;
+        for (; typedef_entry; typedef_entry = typedef_entry->next)
+	        write_typedef(header, typedef_entry->var->decltype.type);
         break;
       }
       case STMT_LIBRARY:
         write_library(header, stmt->u.lib);
         write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE);
         break;
       case STMT_CPPQUOTE:
         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->decltype.type) == TYPE_FUNCTION)
         {
           if (!ignore_funcs)
           {
             int prefixes_differ = strcmp(prefix_client, prefix_server);
 
             if (prefixes_differ)
             {
               fprintf(header, "/* client prototype */\n");
diff --git a/tools/widl/header.h b/tools/widl/header.h
index 0d44b4039f..5a7359c7ac 100644
--- a/tools/widl/header.h
+++ b/tools/widl/header.h
@@ -23,21 +23,24 @@
 
 #include "typetree.h"
 
 extern int is_ptrchain_attr(const var_t *var, enum attr_type t);
 extern int is_aliaschain_attr(const type_t *var, enum attr_type t);
 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 decl_type_t *get_attrdt(const attr_list_t *list, enum attr_type t);
 extern const char* get_name(const var_t *v);
+extern void write_decltype_left(FILE *h, decl_type_t *dt, 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_decltype_decl(FILE *f, decl_type_t *dt, const char *name);\
+extern void write_decltype_decl_left(FILE *f, decl_type_t *dt);
 extern unsigned int get_context_handle_offset( const type_t *type );
 extern unsigned int get_generic_handle_offset( const type_t *type );
 extern int needs_space_after(type_t *t);
 extern int is_object(const type_t *iface);
 extern int is_local(const attr_list_t *list);
 extern int count_methods(const type_t *iface);
 extern int need_stub(const type_t *iface);
 extern int need_proxy(const type_t *iface);
@@ -78,34 +81,34 @@ static inline int is_declptr(const type_t *t)
 
 static inline int is_conformant_array(const type_t *t)
 {
     return is_array(t) && type_array_has_conformance(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)
 {
     return ((is_attr(attrs, ATTR_STRING) || is_aliaschain_attr(type, ATTR_STRING))
             && (last_ptr(type) || last_array(type)));
 }
 
 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;
 }
 
 #endif
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index dd676e9a28..2bffdbab41 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -47,50 +47,45 @@ struct typenode {
 };
 
 struct _import_t
 {
   char *name;
   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);
 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_type_t *make_decl_type(type_t *type, decl_type_t *left, decl_type_t *right, attr_t *attr, enum storage_class stgclass);
+static decl_type_t *make_decl_type2(type_t *type, decl_type_t *left, decl_type_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);
+static attr_t *make_attrdt(enum attr_type type, type_t *val);
 static expr_list_t *append_expr(expr_list_t *list, expr_t *expr);
 static type_t *append_array(type_t *chain, expr_t *expr);
-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl, int top);
-static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls);
+static var_t *declare_var(attr_list_t *attrs, const decl_type_t *decltype, const declarator_t *decl, int top);
+static var_list_t *set_var_types(attr_list_t *attrs, decl_type_t *decltype, declarator_list_t *decls);
 static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface);
 static ifref_t *make_ifref(type_t *iface);
 static var_list_t *append_var_list(var_list_t *list, var_list_t *vars);
 static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *p);
 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 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);
+static type_t *reg_typedefs(decl_type_t *decltype, var_list_t *names, attr_list_t *attrs);
 static type_t *find_type_or_error(const char *name, int t);
 static type_t *find_type_or_error2(char *name, int t);
 
 static var_t *reg_const(var_t *var);
 
 static void push_namespace(const char *name);
 static void pop_namespace(const char *name);
 
@@ -158,17 +153,17 @@ static typelib_t *current_typelib;
 	ifref_list_t *ifref_list;
 	char *str;
 	UUID *uuid;
 	unsigned int num;
 	double dbl;
 	interface_info_t ifinfo;
 	typelib_t *typelib;
 	struct _import_t *import;
-	struct _decl_spec_t *declspec;
+	struct _decl_type_t *decltype;
 	enum storage_class stgclass;
 }
 
 %token <str> aIDENTIFIER aPRAGMA
 %token <str> aKNOWNTYPE
 %token <num> aNUM aHEXNUM
 %token <dbl> aDOUBLE
 %token <str> aSTRING aWSTRING aSQSTRING
@@ -269,17 +264,17 @@ static typelib_t *current_typelib;
 %type <attr> attribute type_qualifier function_specifier acf_attribute
 %type <attr_list> m_attributes attributes attrib_list m_type_qual_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 <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
+%type <decltype> decl_spec decl_spec_no_type m_decl_spec_no_type
 %type <type> inherit interface interfacedef interfacedec
 %type <type> dispinterface dispinterfacehdr dispinterfacedef
 %type <type> module modulehdr moduledef
 %type <str> namespacedef
 %type <type> base_type int_std
 %type <type> enumdef structdef uniondef typedecl
 %type <type> type
 %type <ifref> coclass_int
@@ -592,17 +587,17 @@ attribute:					{ $$ = NULL; }
 	| tUSESGETLASTERROR			{ $$ = make_attr(ATTR_USESGETLASTERROR); }
 	| tUSERMARSHAL '(' type ')'		{ $$ = make_attrp(ATTR_USERMARSHAL, $3); }
 	| tUUID '(' uuid_string ')'		{ $$ = make_attrp(ATTR_UUID, $3); }
 	| tASYNCUUID '(' uuid_string ')'	{ $$ = make_attrp(ATTR_ASYNCUUID, $3); }
 	| tV1ENUM				{ $$ = make_attr(ATTR_V1ENUM); }
 	| tVARARG				{ $$ = make_attr(ATTR_VARARG); }
 	| tVERSION '(' version ')'		{ $$ = make_attrv(ATTR_VERSION, $3); }
 	| tVIPROGID '(' aSTRING ')'		{ $$ = make_attrp(ATTR_VIPROGID, $3); }
-	| tWIREMARSHAL '(' type ')'		{ $$ = make_attrp(ATTR_WIREMARSHAL, $3); }
+	| tWIREMARSHAL '(' type ')'		{ $$ = make_attrdt(ATTR_WIREMARSHAL, $3); }
 	| pointer_type				{ $$ = make_attrv(ATTR_POINTERTYPE, $1); }
 	;
 
 uuid_string:
 	  aUUID
 	| aSTRING				{ if (!is_valid_uuid($1))
 						    error_loc("invalid UUID: %s\n", $1);
 						  $$ = parse_uuid($1); }
@@ -646,20 +641,20 @@ enum_list: enum					{ if (!$1->eval)
                                                     $3->eval = make_exprl(type, last->eval->cval + 1);
                                                   }
                                                   $$ = append_var( $1, $3 );
 						}
 	;
 
 enum:	  ident '=' expr_int_const		{ $$ = reg_const($1);
 						  $$->eval = $3;
-                                                  $$->type = type_new_int(TYPE_BASIC_INT, 0);
+                                                  $$->decltype.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
 	| ident					{ $$ = reg_const($1);
-                                                  $$->type = type_new_int(TYPE_BASIC_INT, 0);
+                                                  $$->decltype.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
 	;
 
 enumdef: tENUM t_ident '{' enums '}'		{ $$ = type_new_enum($2, current_namespace, TRUE, $4); }
 	;
 
 m_exprs:  m_expr                                { $$ = append_expr( NULL, $1 ); }
 	| m_exprs ',' m_expr                    { $$ = append_expr( $1, $3 ); }
@@ -735,17 +730,17 @@ fields:						{ $$ = NULL; }
 	;
 
 field:	  m_attributes decl_spec struct_declarator_list ';'
 						{ const char *first = LIST_ENTRY(list_head($3), declarator_t, entry)->var->name;
 						  check_field_attrs(first, $1);
 						  $$ = set_var_types($1, $2, $3);
 						}
 	| m_attributes uniondef ';'		{ var_t *v = make_var(NULL);
-						  v->type = $2; v->attrs = $1;
+						  v->decltype.type = $2; v->attrs = $1;
 						  $$ = append_var(NULL, v);
 						}
 	;
 
 ne_union_field:
 	  s_field ';'				{ $$ = $1; }
 	| attributes ';'			{ $$ = make_var(NULL); $$->attrs = $1; }
         ;
@@ -759,23 +754,23 @@ union_field:
 	| ';'					{ $$ = NULL; }
         ;
 
 s_field:  m_attributes decl_spec declarator	{ $$ = declare_var(check_field_attrs($3->var->name, $1),
 						                $2, $3, FALSE);
 						  free($3);
 						}
 	| m_attributes structdef		{ var_t *v = make_var(NULL);
-						  v->type = $2; v->attrs = $1;
+						  v->decltype.type = $2; v->attrs = $1;
 						  $$ = v;
 						}
 	;
 
 funcdef: declaration				{ $$ = $1;
-						  if (type_get_type($$->type) != TYPE_FUNCTION)
+						  if (type_get_type($$->decltype.type) != TYPE_FUNCTION)
 						    error_loc("only methods may be declared inside the methods section of a dispinterface\n");
 						  check_function_attrs($$->name, $$->attrs);
 						}
 	;
 
 declaration:
 	  attributes decl_spec init_declarator
 						{ $$ = declare_var($1, $2, $3, FALSE);
@@ -961,29 +956,29 @@ function_specifier:
 type_qualifier:
 	  tCONST				{ $$ = make_attr(ATTR_CONST); }
 	;
 
 m_type_qual_list:				{ $$ = NULL; }
 	| m_type_qual_list type_qualifier	{ $$ = append_attr($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_type($1, $2, NULL, NULL, STG_NONE); }
 	| decl_spec_no_type type m_decl_spec_no_type
-						{ $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); }
+						{ $$ = make_decl_type($2, $1, $3, NULL, STG_NONE); }
 	;
 
 m_decl_spec_no_type:				{ $$ = NULL; }
 	| decl_spec_no_type
 	;
 
 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_type(NULL, $2, NULL, $1, STG_NONE); }
+	| function_specifier m_decl_spec_no_type  { $$ = make_decl_type(NULL, $2, NULL, $1, STG_NONE); }
+	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_type(NULL, $2, NULL, NULL, $1); }
 	;
 
 declarator:
 	  '*' m_type_qual_list declarator %prec PPTR
 						{ $$ = $3; $$->type = append_chain_type($$->type, 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)); }
 	| direct_declarator
@@ -1192,17 +1187,18 @@ acf_attribute
 static void decl_builtin_basic(const char *name, enum type_basic_type type)
 {
   type_t *t = type_new_basic(type);
   reg_type(t, name, NULL, 0);
 }
 
 static void decl_builtin_alias(const char *name, type_t *t)
 {
-  reg_type(type_new_alias(t, name), name, NULL, 0);
+  decl_type_t decltype;
+  reg_type(type_new_alias(init_decltype(&decltype, t), name, &global_namespace), name, &global_namespace, 0);
 }
 
 void init_types(void)
 {
   decl_builtin_basic("byte", TYPE_BASIC_BYTE);
   decl_builtin_basic("wchar_t", TYPE_BASIC_WCHAR);
   decl_builtin_basic("float", TYPE_BASIC_FLOAT);
   decl_builtin_basic("double", TYPE_BASIC_DOUBLE);
@@ -1256,16 +1252,28 @@ static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type
     if (attr->type == type)
     {
       list_remove(&attr->entry);
       return append_attr(dst, attr);
     }
   return dst;
 }
 
+
+static attr_list_t *remove_attr(attr_list_t *lst, enum attr_type type)
+{
+  attr_t *attr;
+  LIST_FOR_EACH_ENTRY(attr, lst, attr_t, entry)
+    if (attr->type == type)
+    {
+      list_remove(&attr->entry);
+    }
+  return lst;
+}
+
 static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list)
 {
   struct list *entry;
 
   if (!old_list) return new_list;
 
   while ((entry = list_head(old_list)))
   {
@@ -1293,65 +1301,104 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter
     if (filter && !filter(new_list, attr)) continue;
     new_attr = xmalloc(sizeof(*new_attr));
     *new_attr = *attr;
     list_add_tail(new_list, &new_attr->entry);
   }
   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_type_t *make_decl_type(type_t *type, decl_type_t *left, decl_type_t *right, attr_t *attr, enum storage_class stgclass)
 {
-  decl_spec_t *declspec = left ? left : right;
-  if (!declspec)
+  enum type_qualifier typequalifier = TYPE_QUALIFIER_NONE;
+  enum function_specifier funcspecifier = FUNCTION_SPECIFIER_NONE;
+
+  assert(attr == NULL || attr->type == ATTR_CONST || attr->type == ATTR_INLINE);
+
+  if (attr != NULL)
   {
-    declspec = xmalloc(sizeof(*declspec));
-    declspec->type = NULL;
-    declspec->attrs = NULL;
-    declspec->stgclass = STG_NONE;
+    if (attr->type == ATTR_CONST)
+      typequalifier = TYPE_QUALIFIER_CONST;
+    else if (attr->type == ATTR_INLINE)
+      funcspecifier = FUNCTION_SPECIFIER_INLINE;
   }
-  declspec->type = type;
-  if (left && declspec != left)
+
+  return make_decl_type2(type, left, right, stgclass, typequalifier, funcspecifier);
+}
+
+static decl_type_t *make_decl_type2(type_t *type, decl_type_t *left, decl_type_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier)
+{
+  decl_type_t *decltype = left ? left : right;
+
+  if (!decltype)
+  {
+    decltype = xmalloc(sizeof(*decltype));
+    decltype->type = NULL;
+    decltype->stgclass = STG_NONE;
+    decltype->typequalifier = TYPE_QUALIFIER_NONE;
+    decltype->funcspecifier = FUNCTION_SPECIFIER_NONE;
+  }
+  decltype->type = type;
+  if (left && decltype != left)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, left->attrs);
-    if (declspec->stgclass == STG_NONE)
-      declspec->stgclass = left->stgclass;
+    if (decltype->stgclass == STG_NONE)
+      decltype->stgclass = left->stgclass;
     else if (left->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (decltype->typequalifier == TYPE_QUALIFIER_NONE)
+      decltype->typequalifier = left->typequalifier;
+    else if (left->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (decltype->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      decltype->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)
+  if (right && decltype != right)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, right->attrs);
-    if (declspec->stgclass == STG_NONE)
-      declspec->stgclass = right->stgclass;
+    if (decltype->stgclass == STG_NONE)
+      decltype->stgclass = right->stgclass;
     else if (right->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (decltype->typequalifier == TYPE_QUALIFIER_NONE)
+      decltype->typequalifier = right->typequalifier;
+    else if (right->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (decltype->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      decltype->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;
+  if (decltype->stgclass == STG_NONE)
+    decltype->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 (decltype->typequalifier == TYPE_QUALIFIER_NONE)
+    decltype->typequalifier = typequalifier;
+  else if (typequalifier != TYPE_QUALIFIER_NONE)
+    error_loc("only one type qualifier can be specified\n");
+
+  if (decltype->funcspecifier == FUNCTION_SPECIFIER_NONE)
+    decltype->funcspecifier = funcspecifier;
+  else if (funcspecifier != FUNCTION_SPECIFIER_NONE)
+    error_loc("only one function specifier can be specified\n");
 
-  return declspec;
+  return decltype;
 }
 
 static attr_t *make_attr(enum attr_type type)
 {
   attr_t *a = xmalloc(sizeof(attr_t));
   a->type = type;
   a->u.ival = 0;
   return a;
@@ -1368,16 +1415,27 @@ static attr_t *make_attrv(enum attr_type type, unsigned int val)
 static attr_t *make_attrp(enum attr_type type, void *val)
 {
   attr_t *a = xmalloc(sizeof(attr_t));
   a->type = type;
   a->u.pval = val;
   return a;
 }
 
+static attr_t *make_attrdt(enum attr_type type, type_t *val)
+{
+  attr_t *a = NULL;
+  assert(type == ATTR_WIREMARSHAL);
+  a = xmalloc(sizeof(attr_t));
+
+  a->type = type;
+  init_decltype(&a->u.dtval, val);
+  return a;
+}
+
 static expr_list_t *append_expr(expr_list_t *list, expr_t *expr)
 {
     if (!expr) return list;
     if (!list)
     {
         list = xmalloc( sizeof(*list) );
         list_init( list );
     }
@@ -1469,38 +1527,47 @@ static int is_allowed_range_type(const type_t *type)
     default:
         return FALSE;
     }
 }
 
 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;
+    decl_type_t *chain_decltype = 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))
         ;
 
     if (is_ptr(chain_type))
-        chain_type->details.pointer.ref = type;
+        chain_decltype = &chain_type->details.pointer.ref;
     else if (is_array(chain_type))
-        chain_type->details.array.elem = type;
+        chain_decltype = &chain_type->details.array.elem;
     else
         assert(0);
 
+    chain_decltype->type = type;
+    /* we need to move the ATTR_CONST attribute off the type of the pointee and onto its decltype
+     * typequalifier on the pointer */
+    if (is_attr(type->attrs, ATTR_CONST)) {
+      type->attrs = remove_attr(type->attrs, ATTR_CONST);
+      chain_decltype->typequalifier = TYPE_QUALIFIER_CONST;
+    }
+
     return chain;
 }
 
 static warning_list_t *append_warning(warning_list_t *list, int num)
 {
     warning_t *entry;
 
     if(!list)
@@ -1509,152 +1576,175 @@ static warning_list_t *append_warning(warning_list_t *list, int num)
         list_init( list );
     }
     entry = xmalloc( sizeof(*entry) );
     entry->num = num;
     list_add_tail( list, &entry->entry );
     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, const decl_type_t *decltype, const declarator_t *decl,
                        int top)
 {
   var_t *v = decl->var;
   expr_list_t *sizes = get_attrp(attrs, ATTR_SIZEIS);
   expr_list_t *lengs = get_attrp(attrs, ATTR_LENGTHIS);
   expr_t *dim;
   type_t **ptype;
   type_t *func_type = decl ? decl->func_type : NULL;
-  type_t *type = decl_spec->type;
+  type_t *type = decltype->type;
 
-  if (is_attr(type->attrs, ATTR_INLINE))
-  {
+
+  if (decltype->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->decltype.funcspecifier = decltype->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 decltype
+   * unless the pointee already has const type qualifier*/
+
+  /* we need to shuffle aroundand tranlate between TYPE_QUALIFEIR_CONST and ATTR_CONST
+   * in this block */
+  if (!decl)
+  {
+    /* simplest case, no pointers to deal with here */
+    v->decltype.typequalifier = decltype->typequalifier;
+  } else if (decl->bits) {
+    /* dealing with a bitfield, just pass it on */
+    v->decltype.type = type_new_bitfield(decltype, decl->bits);
+  }
+  else {
+    /* here we're dealing with a pointerish type chain, so we need to pull
+     * the typequalifier off of the decltype and stick them in the type's attr list
+     */
+    if (decltype->typequalifier == TYPE_QUALIFIER_CONST) {
+      type->attrs = append_attr(type->attrs, make_attr(ATTR_CONST));
+      assert(is_attr(type->attrs, ATTR_CONST));
+    }
+
+    v->decltype.type = append_chain_type(decl->type, type);
+    /* finally pull the ATTR_CONST attribute off the head of the pointerish type chain,
+     * and stick on the var's decltype */
+    if (is_attr(v->decltype.type->attrs, ATTR_CONST)) {
+      v->decltype.type->attrs = remove_attr(v->decltype.type->attrs, ATTR_CONST);
+      v->decltype.typequalifier = TYPE_QUALIFIER_CONST;
+    }
+  }
+
+  v->decltype.stgclass = decltype->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->decltype.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->decltype.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)
-      {
-        /* 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);
       }
     }
     else if (ptr_attr)
        error_loc("%s: pointer attribute applied to non-pointer type\n", v->name);
   }
 
   if (is_attr(v->attrs, ATTR_STRING))
   {
     type_t *t = type;
 
-    if (!is_ptr(v->type) && !is_array(v->type))
+    if (!is_ptr(v->decltype.type) && !is_array(v->decltype.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;
     }
 
     if (type_get_type(t) != TYPE_BASIC &&
         (get_basic_fc(t) != FC_CHAR &&
          get_basic_fc(t) != FC_BYTE &&
          get_basic_fc(t) != FC_WCHAR))
     {
       error_loc("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays\n",
                 v->name);
     }
   }
 
   if (is_attr(v->attrs, ATTR_V1ENUM))
   {
-    if (type_get_type_detect_alias(v->type) != TYPE_ENUM)
+    if (type_get_type_detect_alias(v->decltype.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->decltype.type))
     error_loc("'%s': [range] attribute applied to non-integer type\n",
               v->name);
 
-  ptype = &v->type;
+  ptype = &v->decltype.type;
   if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry)
   {
     if (dim->type != EXPR_VOID)
     {
       if (is_array(*ptype))
       {
         if (!type_array_get_conformance(*ptype) ||
             type_array_get_conformance(*ptype)->type != EXPR_VOID)
           error_loc("%s: cannot specify size_is for an already sized array\n", v->name);
         else
           *ptype = type_new_array((*ptype)->name,
                                   type_array_get_element(*ptype), FALSE,
                                   0, dim, NULL, 0);
       }
       else if (is_ptr(*ptype))
+      {
         *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE,
                                 0, dim, NULL, pointer_default);
+      }
       else
         error_loc("%s: size_is attribute applied to illegal type\n", v->name);
     }
 
     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->decltype.type;
   if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry)
   {
     if (dim->type != EXPR_VOID)
     {
       if (is_array(*ptype))
       {
         *ptype = type_new_array((*ptype)->name,
                                 type_array_get_element(*ptype),
@@ -1663,67 +1753,69 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
                                 type_array_get_conformance(*ptype),
                                 dim, type_array_get_ptr_default_fc(*ptype));
       }
       else
         error_loc("%s: length_is attribute applied to illegal type\n", v->name);
     }
 
     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);
   }
 
   /* v->type is currently pointing to the type on the left-side of the
    * declaration, so we need to fix this up so that it is the return type of the
    * function and make v->type point to the function side of the declaration */
   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->decltype.type;
+    enum type_qualifier typequalifier = v->decltype.typequalifier;
+
+    v->decltype.type = func_type;
+    v->decltype.typequalifier = TYPE_QUALIFIER_NONE;
+    for (ft = v->decltype.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->decltype.type = return_type;
+    ft->details.function->retval->decltype.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->decltype.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->decltype.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;
 }
 
-static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls)
+static var_list_t *set_var_types(attr_list_t *attrs, decl_type_t *decltype, declarator_list_t *decls)
 {
   declarator_t *decl, *next;
   var_list_t *var_list = NULL;
 
   LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry )
   {
-    var_t *var = declare_var(attrs, decl_spec, decl, 0);
+    var_t *var = declare_var(attrs, decltype, decl, 0);
     var_list = append_var(var_list, var);
     free(decl);
   }
-  free(decl_spec);
+  free(decltype);
   return var_list;
 }
 
 static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface)
 {
     if (!iface) return list;
     if (!list)
     {
@@ -1765,32 +1857,33 @@ static var_list_t *append_var_list(var_list_t *list, var_list_t *vars)
     list_move_tail( list, vars );
     return list;
 }
 
 var_t *make_var(char *name)
 {
   var_t *v = xmalloc(sizeof(var_t));
   v->name = name;
-  v->type = NULL;
+  v->decltype.type = NULL;
+  v->decltype.stgclass = STG_NONE;
+  v->decltype.typequalifier = TYPE_QUALIFIER_NONE;
+  v->decltype.funcspecifier = FUNCTION_SPECIFIER_NONE;
   v->attrs = NULL;
   v->eval = NULL;
-  v->stgclass = STG_NONE;
   init_loc_info(&v->loc_info);
   return v;
 }
 
 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->decltype = src->decltype;
   v->attrs = map_attrs(src->attrs, attr_filter);
   v->eval = src->eval;
-  v->stgclass = src->stgclass;
   v->loc_info = src->loc_info;
   return v;
 }
 
 static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *d)
 {
   if (!d) return list;
   if (!list) {
@@ -1808,17 +1901,26 @@ static declarator_t *make_declarator(var_t *var)
   d->type = NULL;
   d->func_type = NULL;
   d->bits = NULL;
   return d;
 }
 
 static type_t *make_safearray(type_t *type)
 {
-  return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0,
+  decl_type_t aliasee_dt;
+  decl_type_t element_dt;
+
+  init_decltype(&element_dt,
+    type_new_alias(
+      init_decltype(&aliasee_dt, type),
+      "SAFEARRAY",
+      &global_namespace));
+
+  return type_new_array(NULL, &element_dt, TRUE, 0,
                         NULL, NULL, FC_RP);
 }
 
 static typelib_t *make_library(const char *name, const attr_list_t *attrs)
 {
     typelib_t *typelib = xmalloc(sizeof(*typelib));
     typelib->name = xstrdup(name);
     typelib->attrs = attrs;
@@ -1921,17 +2023,17 @@ void add_incomplete(type_t *t)
   struct typenode *tn = xmalloc(sizeof *tn);
   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);
+    type_t *ot = type_alias_get_aliasee_type(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;
     t->defined = ot->defined;
   }
 }
@@ -1957,20 +2059,20 @@ static void fix_incomplete_types(type_t *complete_type)
     {
       tn->type->details.structure = complete_type->details.structure;
       list_remove(&tn->entry);
       free(tn);
     }
   }
 }
 
-static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs)
+static type_t *reg_typedefs(decl_type_t *decltype, declarator_list_t *decls, attr_list_t *attrs)
 {
   const declarator_t *decl;
-  type_t *type = decl_spec->type;
+  type_t *type = decltype->type;
 
   if (is_attr(attrs, ATTR_UUID) && !is_attr(attrs, ATTR_PUBLIC))
     attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) );
 
   /* We must generate names for tagless enum, struct or union.
      Typedef-ing a tagless enum, struct or union means we want the typedef
      to be included in a library hence the public attribute.  */
   if (type_get_type_detect_alias(type) == TYPE_ENUM ||
@@ -2004,18 +2106,18 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
        * FIXME: We may consider string separated type tables for each input
        *        for cleaner solution.
        */
       if (cur && input_name == cur->loc_info.input_name)
           error_loc("%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);
+      name = declare_var(attrs, decltype, decl, 0);
+      cur = type_new_alias(&name->decltype, name->name, current_namespace);
       cur->attrs = attrs;
 
       if (is_incomplete(cur))
         add_incomplete(cur);
       reg_type(cur, cur->name, current_namespace, 0);
     }
   }
   return type;
@@ -2280,20 +2382,20 @@ static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs)
   LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
   {
     if (!allowed_attr[attr->type].on_interface)
       error_loc("inapplicable attribute %s for interface %s\n",
                 allowed_attr[attr->type].display_name, name);
     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->decltype.type) == TYPE_BASIC &&
+            type_basic_get_type( var->decltype.type ) == TYPE_BASIC_HANDLE)
             continue;
-        if (is_aliaschain_attr( var->type, ATTR_HANDLE ))
+        if (is_aliaschain_attr( var->decltype.type, ATTR_HANDLE ))
             continue;
       error_loc("attribute %s requires a handle type in interface %s\n",
                 allowed_attr[attr->type].display_name, name);
     }
   }
   return attrs;
 }
 
@@ -2488,17 +2590,17 @@ static int is_allowed_conf_type(const type_t *type)
 
 static int is_ptr_guid_type(const type_t *type)
 {
     /* first, make sure it is a pointer to something */
     if (!is_ptr(type)) return FALSE;
 
     /* 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)
 {
     expr_t *dim;
     struct expr_loc expr_loc;
     expr_loc.v = arg;
     expr_loc.attr = attr_name;
@@ -2515,17 +2617,17 @@ static void check_conformance_expr_list(const char *attr_name, const var_t *arg,
 }
 
 static void check_remoting_fields(const var_t *var, type_t *type);
 
 /* checks that properties common to fields and arguments are consistent */
 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->decltype.type;
     int more_to_do;
     const char *container_type_name;
     const char *var_type;
 
     switch (type_get_type(container_type))
     {
     case TYPE_STRUCT:
         container_type_name = "struct";
@@ -2545,17 +2647,17 @@ static void check_field_common(const type_t *container_type,
         break;
     default:
         /* should be no other container types */
         assert(0);
         return;
     }
 
     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->decltype.type, ATTR_STRING)))
         error_loc_info(&arg->loc_info,
                        "string and length_is specified for argument %s are mutually exclusive attributes\n",
                        arg->name);
 
     if (is_attr(arg->attrs, ATTR_SIZEIS))
     {
         expr_list_t *size_is_exprs = get_attrp(arg->attrs, ATTR_SIZEIS);
         check_conformance_expr_list("size_is", arg, container_type, size_is_exprs);
@@ -2642,27 +2744,27 @@ static void check_field_common(const type_t *container_type,
                                "%s \'%s\' of %s \'%s\' cannot be a context handle\n",
                                var_type, arg->name, container_type_name,
                                container_name);
             break;
         case TGT_STRING:
         {
             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_USER_TYPE:
         case TGT_IFACE_POINTER:
         case TGT_BASIC:
         case TGT_ENUM:
         case TGT_RANGE:
             /* nothing to do */
@@ -2689,28 +2791,28 @@ static void check_remoting_fields(const var_t *var, type_t *type)
             fields = type_struct_get_fields(type);
         else
             error_loc_info(&var->loc_info, "undefined type declaration %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 (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
-        if (field->type) check_field_common(type, type->name, field);
+        if (field->decltype.type) check_field_common(type, type->name, field);
 }
 
 /* checks that arguments for a function make sense for marshalling and unmarshalling */
 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 )
+    if (func->decltype.type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->decltype.type->details.function->args, const var_t, entry )
     {
-        const type_t *type = arg->type;
+        const type_t *type = arg->decltype.type;
 
         /* check that [out] parameters have enough pointer levels */
         if (is_attr(arg->attrs, ATTR_OUT))
         {
             switch (typegen_detect_type(type, arg->attrs, TDT_ALL_TYPES))
             {
             case TGT_BASIC:
             case TGT_ENUM:
@@ -2740,44 +2842,44 @@ static void check_remoting_args(const var_t *func)
             case TGT_CTXT_HANDLE_POINTER:
             case TGT_POINTER:
             case TGT_ARRAY:
                 /* OK */
                 break;
             }
         }
 
-        check_field_common(func->type, funcname, arg);
+        check_field_common(func->decltype.type, funcname, arg);
     }
 
-    if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID)
+    if (type_get_type(type_function_get_rettype(func->decltype.type)) != TYPE_VOID)
     {
         var_t var;
         var = *func;
-        var.type = type_function_get_rettype(func->type);
+        var.decltype.type = type_function_get_rettype(func->decltype.type);
         var.name = xstrdup("return value");
-        check_field_common(func->type, funcname, &var);
+        check_field_common(func->decltype.type, funcname, &var);
         free(var.name);
     }
 }
 
 static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func)
 {
     unsigned char explicit_fc, implicit_fc;
 
     /* check for a defined binding handle */
     if (!get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ) || !explicit_fc)
     {
         /* no explicit handle specified so add
          * "[in] handle_t IDL_handle" as the first parameter to the
          * 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->decltype.type = find_type_or_error("handle_t", 0);
+        type_function_add_head_arg(func->decltype.type, idl_handle);
     }
 }
 
 static void check_functions(const type_t *iface, int is_inside_library)
 {
     const statement_t *stmt;
     if (is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE))
     {
@@ -2848,35 +2950,35 @@ static void check_async_uuid(type_t *iface)
     async_iface = get_type(TYPE_INTERFACE, concat_str("Async", iface->name), iface->namespace, 0);
     async_iface->attrs = map_attrs(iface->attrs, async_iface_attrs);
 
     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(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;
+        args = func->decltype.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))
                 begin_args = append_var(begin_args, copy_var(arg, strdup(arg->name), arg_in_attrs));
             if (is_attr(arg->attrs, ATTR_OUT))
                 finish_args = append_var(finish_args, copy_var(arg, strdup(arg->name), arg_out_attrs));
         }
 
         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->decltype.type = type_new_function(begin_args);
+        begin_func->decltype.type->attrs = func->attrs;
+        begin_func->decltype.type->details.function->retval = func->decltype.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->decltype.type = type_new_function(finish_args);
+        finish_func->decltype.type->attrs = func->attrs;
+        finish_func->decltype.type->details.function->retval = func->decltype.type->details.function->retval;
         stmts = append_statement(stmts, make_statement_declaration(finish_func));
     }
 
     type_interface_define(async_iface, inherit, stmts);
     iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface;
 }
 
 static void check_statements(const statement_list_t *stmts, int is_inside_library)
@@ -2918,20 +3020,20 @@ static void check_all_user_types(const statement_list_t *stmts)
     if (stmt->type == STMT_LIBRARY)
       check_all_user_types(stmt->u.lib->stmts);
     else if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE &&
              !is_local(stmt->u.type->attrs))
     {
       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;
-        if (func->type->details.function->args)
-          LIST_FOR_EACH_ENTRY( v, func->type->details.function->args, const var_t, entry )
-            check_for_additional_prototype_types(v->type);
-        check_for_additional_prototype_types(type_function_get_rettype(func->type));
+        if (func->decltype.type->details.function->args)
+          LIST_FOR_EACH_ENTRY( v, func->decltype.type->details.function->args, const var_t, entry )
+            check_for_additional_prototype_types(v->decltype.type);
+        check_for_additional_prototype_types(type_function_get_rettype(func->decltype.type));
       }
     }
   }
 }
 
 int is_valid_uuid(const char *s)
 {
   int i;
@@ -2969,26 +3071,26 @@ static statement_t *make_statement_reference(type_t *type)
     stmt->u.type = type;
     return stmt;
 }
 
 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->decltype.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->decltype.type) == TYPE_FUNCTION)
         check_function_attrs(var->name, var->attrs);
-    else if (var->stgclass == STG_NONE || var->stgclass == STG_REGISTER)
+    else if (var->decltype.stgclass == STG_NONE || var->decltype.stgclass == STG_REGISTER)
         error_loc("instantiation of data is illegal\n");
     return stmt;
 }
 
 static statement_t *make_statement_library(typelib_t *typelib)
 {
     statement_t *stmt = make_statement(STMT_LIBRARY);
     stmt->u.lib = typelib;
@@ -3029,35 +3131,38 @@ static statement_t *make_statement_module(type_t *type)
     stmt->u.type = type;
     return stmt;
 }
 
 static statement_t *make_statement_typedef(declarator_list_t *decls)
 {
     declarator_t *decl, *next;
     statement_t *stmt;
-    type_list_t **type_list;
+    typedef_list_t **typedef_list;
 
     if (!decls) return NULL;
 
     stmt = make_statement(STMT_TYPEDEF);
-    stmt->u.type_list = NULL;
-    type_list = &stmt->u.type_list;
+    stmt->u.typedef_list = NULL;
+    typedef_list = &stmt->u.typedef_list;
 
     LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry )
     {
         var_t *var = decl->var;
         type_t *type = find_type_or_error(var->name, 0);
-        *type_list = xmalloc(sizeof(type_list_t));
-        (*type_list)->type = type;
-        (*type_list)->next = NULL;
+        var->decltype.type = type;
+
+        assert(var->decltype.type->is_alias);
+
+        *typedef_list = xmalloc(sizeof(typedef_list_t));
+        (*typedef_list)->var = var;
+        (*typedef_list)->next = NULL;
 
-        type_list = &(*type_list)->next;
+        typedef_list = &(*typedef_list)->next;
         free(decl);
-        free(var);
     }
 
     return stmt;
 }
 
 static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2)
 {
     if (!l2) return l1;
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c
index 8d0e8b2cc5..65061ad510 100644
--- a/tools/widl/proxy.c
+++ b/tools/widl/proxy.c
@@ -100,25 +100,25 @@ static void clear_output_vars( const var_list_t *args )
 {
   const var_t *arg;
 
   if (!args) return;
   LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
   {
       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->decltype.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->decltype.type)) == TYPE_BASIC) continue;
+          if (type_get_type(type_pointer_get_ref_type(arg->decltype.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->decltype.type) && type_array_has_conformance(arg->decltype.type))
       {
-          write_expr( proxy, type_array_get_conformance(arg->type), 1, 1, NULL, NULL, "" );
+          write_expr( proxy, type_array_get_conformance(arg->decltype.type), 1, 1, NULL, NULL, "" );
           fprintf( proxy, " * " );
       }
       fprintf( proxy, "sizeof( *%s ));\n", arg->name );
   }
 }
 
 static int need_delegation(const type_t *iface)
 {
@@ -142,17 +142,17 @@ static int get_delegation_indirect(const type_t *iface, const type_t ** delegate
 static int need_delegation_indirect(const type_t *iface)
 {
   return get_delegation_indirect(iface, NULL);
 }
 
 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->decltype.type;
 
   write_parameter_conf_or_var_exprs(proxy, indent, local_var_prefix, PHASE_FREE, arg, FALSE);
 
   switch (typegen_detect_type(type, arg->attrs, TDT_IGNORE_STRINGS))
   {
   case TGT_ENUM:
   case TGT_BASIC:
     break;
@@ -186,72 +186,72 @@ static void proxy_free_variables( var_list_t *args, const char *local_var_prefix
       free_variable( arg, local_var_prefix );
       fprintf(proxy, "\n");
     }
 }
 
 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->decltype.type);
+  int has_ret = !is_void(retval->decltype.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->decltype.type->attrs, ATTR_CALLCONV);
+  const var_list_t *args = type_get_function_args(func->decltype.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_decltype_decl_left(proxy, &retval->decltype);
       print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
       write_args(proxy, args, iface->name, 1, TRUE);
       print_proxy( ")\n");
       write_client_call_routine( proxy, iface, func, "Object", proc_offset );
       return;
   }
   print_proxy( "static void __finally_%s_%s_Proxy( struct __proxy_frame *__frame )\n",
                iface->name, get_name(func) );
   print_proxy( "{\n");
   indent++;
   if (has_full_pointer) write_full_pointer_free(proxy, indent, func);
   print_proxy( "NdrProxyFreeBuffer( __frame->This, &__frame->_StubMsg );\n" );
   indent--;
   print_proxy( "}\n");
   print_proxy( "\n");
 
-  write_type_decl_left(proxy, retval->type);
+  write_decltype_decl_left(proxy, (decl_type_t*)&retval->decltype);
   print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
   write_args(proxy, args, iface->name, 1, TRUE);
   print_proxy( ")\n");
   print_proxy( "{\n");
   indent ++;
   print_proxy( "struct __proxy_frame __f, * const __frame = &__f;\n" );
   /* local variables */
   if (has_ret) {
     print_proxy( "%s", "" );
-    write_type_decl(proxy, retval->type, retval->name);
+    write_decltype_decl(proxy, &retval->decltype, retval->name);
     fprintf( proxy, ";\n" );
   }
   print_proxy( "RPC_MESSAGE _RpcMessage;\n" );
   if (has_ret) {
-    if (decl_indirect(retval->type))
+    if (decl_indirect(retval->decltype.type))
         print_proxy("void *_p_%s = &%s;\n", retval->name, retval->name);
   }
   print_proxy( "\n");
 
   print_proxy( "RpcExceptionInit( __proxy_filter, __finally_%s_%s_Proxy );\n", iface->name, get_name(func) );
   print_proxy( "__frame->This = This;\n" );
 
   if (has_full_pointer)
     write_full_pointer_init(proxy, indent, func, FALSE);
 
   /* FIXME: trace */
-  clear_output_vars( type_get_function_args(func->type) );
+  clear_output_vars( type_get_function_args(func->decltype.type) );
 
   print_proxy( "RpcTryExcept\n" );
   print_proxy( "{\n" );
   indent++;
   print_proxy( "NdrProxyInitialize(This, &_RpcMessage, &__frame->_StubMsg, &Object_StubDesc, %d);\n", idx);
   write_pointer_checks( proxy, indent, func );
 
   print_proxy( "RpcTryFinally\n" );
@@ -274,19 +274,19 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
   print_proxy("NdrConvert( &__frame->_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset );
   indent--;
   fprintf(proxy, "\n");
 
   write_remoting_arguments(proxy, indent, func, "", PASS_OUT, PHASE_UNMARSHAL);
 
   if (has_ret)
   {
-      if (decl_indirect(retval->type))
+      if (decl_indirect(retval->decltype.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->decltype.type) || is_array(retval->decltype.type))
           print_proxy("%s = 0;\n", retval->name);
       write_remoting_arguments(proxy, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL);
   }
 
   indent--;
   print_proxy( "}\n");
   print_proxy( "RpcFinally\n" );
   print_proxy( "{\n" );
@@ -296,17 +296,17 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
   print_proxy( "}\n");
   print_proxy( "RpcEndFinally\n" );
   indent--;
   print_proxy( "}\n" );
   print_proxy( "RpcExcept(__frame->_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)\n" );
   print_proxy( "{\n" );
   if (has_ret) {
     indent++;
-    proxy_free_variables( type_get_function_args(func->type), "" );
+    proxy_free_variables( type_get_function_args(func->decltype.type), "" );
     print_proxy( "_RetVal = NdrProxyErrorHandler(RpcExceptionCode());\n" );
     indent--;
   }
   print_proxy( "}\n" );
   print_proxy( "RpcEndExcept\n" );
 
   if (has_ret) {
     print_proxy( "return _RetVal;\n" );
@@ -315,17 +315,17 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
   print_proxy( "}\n");
   print_proxy( "\n");
 }
 
 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->decltype.type));
   int has_full_pointer = is_full_pointer_function(func);
 
   if (is_interpreted_func( iface, func )) return;
 
   indent = 0;
   print_proxy( "struct __frame_%s_%s_Stub\n{\n", iface->name, get_name(func));
   indent++;
   print_proxy( "__DECL_EXCEPTION_FRAME\n" );
@@ -384,38 +384,38 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
 
   print_proxy("*_pdwStubPhase = STUB_CALL_SERVER;\n");
   fprintf(proxy, "\n");
   print_proxy( "%s", has_ret ? "__frame->_RetVal = " : "" );
   if (cas) fprintf(proxy, "%s_%s_Stub", iface->name, cas);
   else fprintf(proxy, "__frame->_This->lpVtbl->%s", get_name(func));
   fprintf(proxy, "(__frame->_This");
 
-  if (type_get_function_args(func->type))
+  if (type_get_function_args(func->decltype.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_get_function_args(func->decltype.type), const var_t, entry )
+          fprintf(proxy, ", %s__frame->%s", is_array(arg->decltype.type) && !type_array_is_decl_as_ptr(arg->decltype.type) ? "*" :"" , arg->name);
   }
   fprintf(proxy, ");\n");
   fprintf(proxy, "\n");
   print_proxy("*_pdwStubPhase = STUB_MARSHAL;\n");
   fprintf(proxy, "\n");
 
   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->decltype.type)))
     write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE);
 
   print_proxy("NdrStubGetBuffer(This, _pRpcChannelBuffer, &__frame->_StubMsg);\n");
 
   write_remoting_arguments(proxy, indent, func, "__frame->", PASS_OUT, PHASE_MARSHAL);
   fprintf(proxy, "\n");
 
   /* marshall the return value */
-  if (!is_void(type_function_get_rettype(func->type)))
+  if (!is_void(type_function_get_rettype(func->decltype.type)))
     write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL);
 
   indent--;
   print_proxy("}\n");
   print_proxy("RpcFinally\n");
   print_proxy("{\n");
   indent++;
   print_proxy( "__finally_%s_%s_Stub( __frame );\n", iface->name, get_name(func) );
@@ -427,26 +427,26 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
   indent--;
 
   print_proxy("}\n");
   print_proxy("\n");
 }
 
 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->decltype.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_get_function_args( func->decltype.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->decltype.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 );
     indent++;
     if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
     {
         fprintf( proxy, ",\n%*spParamStruct->%s", 4 * indent, "", arg->name );
     }
@@ -608,24 +608,24 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset)
       fprintf(proxy, "/*****************************************************************************\n");
       fprintf(proxy, " * %s interface\n", iface->name);
       fprintf(proxy, " */\n");
       first_func = 0;
     }
     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 = func->decltype.type->details.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 = m->decltype.type->details.function->idx;
                   break;
               }
           }
       }
       func->procstring_offset = *proc_offset;
       gen_proxy(iface, func, idx, *proc_offset);
       gen_stub(iface, func, cname, *proc_offset);
       if (cas && is_interpreted_func( iface, func ))
diff --git a/tools/widl/server.c b/tools/widl/server.c
index 59c17d661f..d50fa2b596 100644
--- a/tools/widl/server.c
+++ b/tools/widl/server.c
@@ -50,17 +50,18 @@ static void print_server(const char *format, ...)
 }
 
 static void write_function_stub(const type_t *iface, const var_t *func, unsigned int proc_offset)
 {
     const var_t *var;
     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 );
-    type_t *ret_type = type_function_get_rettype(func->type);
+    decl_type_t *ret_decltype = type_function_get_retdecltype(func->decltype.type);
+    type_t *ret_type = ret_decltype->type;
 
     if (is_interpreted_func( iface, func )) return;
 
     print_server("struct __frame_%s_%s\n{\n", iface->name, get_name(func));
     indent++;
     print_server("__DECL_EXCEPTION_FRAME\n");
     print_server("MIDL_STUB_MESSAGE _StubMsg;\n");
 
@@ -116,17 +117,17 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     indent++;
     print_server("RpcTryExcept\n");
     print_server("{\n");
     indent++;
 
     if (has_full_pointer)
         write_full_pointer_init(server, indent, func, TRUE);
 
-    if (type_get_function_args(func->type))
+    if (type_get_function_args(func->decltype.type))
     {
         print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");
         indent++;
         print_server("NdrConvert(&__frame->_StubMsg, (PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n",
                      proc_offset);
         indent--;
         fprintf(server, "\n");
 
@@ -154,48 +155,48 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     /* Assign 'out' arguments */
     assign_stub_out_args(server, indent, func, "__frame->");
 
     /* Call the real server function */
     if (is_context_handle(ret_type))
     {
         print_server("__frame->_RetVal = NDRSContextUnmarshall((char*)0, _pRpcMessage->DataRepresentation);\n");
         print_server("*((");
-        write_type_decl(server, ret_type, NULL);
+        write_decltype_decl(server, ret_decltype, 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_get_function_args(func->decltype.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_get_function_args(func->decltype.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->decltype.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->decltype.type, ATTR_CONTEXTHANDLE) ? "*" : "";
                 print_server("(");
-                write_type_decl_left(server, var->type);
+                write_decltype_decl_left(server, (decl_type_t*)&var->decltype);
                 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->decltype.type) && !type_array_is_decl_as_ptr(var->decltype.type) ? "*" : "", var->name);
             }
         }
         fprintf(server, ");\n");
         indent--;
     }
     else
     {
         fprintf(server, "();\n");
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index e5fb20c55f..785cc13b07 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -80,24 +80,24 @@ static const unsigned short IsReturn = 0x0020;
 static const unsigned short IsBasetype = 0x0040;
 static const unsigned short IsByValue = 0x0080;
 static const unsigned short IsSimpleRef = 0x0100;
 /* static const unsigned short IsDontCallFreeInst = 0x0200; */
 /* static const unsigned short SaveForAsyncFinish = 0x0400; */
 
 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, decl_type_t *decltype,
                                     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, decl_type_t *decltype, const char *name, unsigned int *tfsoff);
+static int write_embedded_types(FILE *file, const attr_list_t *attrs, decl_type_t *decltype,
                                 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,
+                                     decl_type_t *decltype, 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,
                                                    unsigned int *alignment );
 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass );
 
 static const char *string_of_type(unsigned char type)
 {
@@ -192,17 +192,17 @@ static const char *string_of_type(unsigned char type)
 static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr)
 {
     const type_t *t = type;
     for (;;)
     {
         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;
     }
 }
 
 unsigned char get_basic_fc(const type_t *type)
 {
     int sign = type_basic_get_sign(type);
     switch (type_basic_get_type(type))
@@ -262,17 +262,17 @@ unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int t
     int pointer_type;
 
     assert(is_ptr(type) || is_array(type));
 
     pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
     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)
             return pointer_type;
     }
 
     if (toplevel_param)
         return FC_RP;
@@ -298,35 +298,44 @@ static unsigned char get_enum_fc(const type_t *type)
 {
     assert(type_get_type(type) == TYPE_ENUM);
     if (is_aliaschain_attr(type, ATTR_V1ENUM))
         return FC_ENUM32;
     else
         return FC_ENUM16;
 }
 
-static type_t *get_user_type(const type_t *t, const char **pname)
+static decl_type_t *get_user_decltype(const type_t *t, const char **pname)
 {
     for (;;)
     {
-        type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
-        if (ut)
+        decl_type_t *udt = get_attrdt(t->attrs, ATTR_WIREMARSHAL);
+        if (udt)
         {
             if (pname)
                 *pname = t->name;
-            return ut;
+            return udt;
         }
 
         if (type_is_alias(t))
-            t = type_alias_get_aliasee(t);
+            t = type_alias_get_aliasee_type(t);
         else
             return NULL;
     }
 }
 
+static type_t *get_user_type(const type_t *t, const char **pname)
+{
+    decl_type_t *decltype = get_user_decltype(t, pname);
+    if (decltype != NULL) {
+        return decltype->type;
+    }
+    return NULL;
+}
+
 static int is_user_type(const type_t *t)
 {
     return get_user_type(t, NULL) != NULL;
 }
 
 enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *attrs, unsigned int flags)
 {
     if (is_user_type(type))
@@ -346,20 +355,20 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
             return TGT_RANGE;
         return TGT_BASIC;
     case TYPE_ENUM:
         if (!(flags & TDT_IGNORE_RANGES) &&
             (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE)))
             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;
     case TYPE_STRUCT:
         return TGT_STRUCT;
     case TYPE_ENCAPSULATED_UNION:
     case TYPE_UNION:
         return TGT_UNION;
@@ -374,68 +383,67 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
     case TYPE_BITFIELD:
         break;
     }
     return TGT_INVALID;
 }
 
 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->decltype.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->decltype.type )) return 0;
         /* fall through */
     case TGT_POINTER:
-        return (get_pointer_fc(v->type, v->attrs, TRUE) == FC_RP);
+        return (get_pointer_fc(v->decltype.type, v->attrs, TRUE) == FC_RP);
     case TGT_CTXT_HANDLE_POINTER:
         return TRUE;
     default:
         return 0;
     }
-
 }
 
 static int get_padding(const var_list_t *fields)
 {
     unsigned short offset = 0;
     unsigned int salign = 1;
     const var_t *f;
 
     if (!fields)
         return 0;
 
     LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
     {
-        type_t *ft = f->type;
+        type_t *ft = f->decltype.type;
         unsigned int align = 0;
         unsigned int size = type_memsize_and_alignment(ft, &align);
         align = clamp_align(align);
         if (align > salign) salign = align;
         offset = ROUND_SIZE(offset, align);
         offset += size;
     }
 
     return ROUNDING(offset, salign);
 }
 
 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->decltype.type, var->attrs, TDT_ALL_TYPES ))
     {
     case TGT_BASIC:
     case TGT_ENUM:
     case TGT_RANGE:
     case TGT_STRUCT:
     case TGT_UNION:
     case TGT_USER_TYPE:
-        stack_size = type_memsize( var->type );
+        stack_size = type_memsize( var->decltype.type );
         by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */
         break;
     default:
         by_val = 0;
         break;
     }
     if (!by_val) stack_size = pointer_size;
     if (by_value) *by_value = by_val;
@@ -490,45 +498,45 @@ unsigned char get_struct_fc(const type_t *type)
 
   fields = type_struct_get_fields(type);
 
   if (get_padding(fields))
     return FC_BOGUS_STRUCT;
 
   if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
   {
-    type_t *t = field->type;
+    type_t *t = field->decltype.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->decltype.type))
         {
             if (is_conformant_array(t))
                 has_conformance = 1;
             has_variance = 1;
             continue;
         }
 
-        if (is_array(type_array_get_element(field->type)))
+        if (is_array(type_array_get_element_type(field->decltype.type)))
             return FC_BOGUS_STRUCT;
 
-        if (type_array_has_conformance(field->type))
+        if (type_array_has_conformance(field->decltype.type))
         {
             has_conformance = 1;
             if (list_next(fields, &field->entry))
                 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
                         field->name);
         }
         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);
     }
 
     switch (typegen_type)
     {
     case TGT_USER_TYPE:
     case TGT_IFACE_POINTER:
         return FC_BOGUS_STRUCT;
@@ -620,17 +628,17 @@ unsigned char get_struct_fc(const type_t *type)
 }
 
 static unsigned char get_array_fc(const type_t *type)
 {
     unsigned char fc;
     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)
     {
         unsigned int size = type_memsize(elem_type);
         if (size * type_array_get_dim(type) > 0xffffuL)
             fc = FC_LGFARRAY;
         else
@@ -709,36 +717,36 @@ static int type_has_pointers(const type_t *type)
 {
     switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
     {
     case TGT_USER_TYPE:
         return FALSE;
     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->decltype.type))
                 return TRUE;
         }
         break;
     }
     case TGT_UNION:
     {
         var_list_t *fields;
         const var_t *field;
         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->decltype.type && type_has_pointers(field->decltype.type))
                 return TRUE;
         }
         break;
     }
     case TGT_CTXT_HANDLE:
     case TGT_CTXT_HANDLE_POINTER:
     case TGT_STRING:
     case TGT_IFACE_POINTER:
@@ -763,36 +771,36 @@ 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 FALSE;
     case TGT_ARRAY:
         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->decltype.type, field->attrs, FALSE))
                 return TRUE;
         }
         break;
     }
     case TGT_UNION:
     {
         var_list_t *fields;
         const var_t *field;
         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->decltype.type && type_has_full_pointer(field->decltype.type, field->attrs, FALSE))
                 return TRUE;
         }
         break;
     }
     case TGT_CTXT_HANDLE:
     case TGT_CTXT_HANDLE_POINTER:
     case TGT_STRING:
     case TGT_IFACE_POINTER:
@@ -852,17 +860,17 @@ static int is_embedded_complex(const type_t *type)
     }
 }
 
 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);
     return NULL;
 }
 
 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
     do { \
@@ -902,26 +910,26 @@ static void write_var_init(FILE *file, int indent, const type_t *t, const char *
         print_file(file, indent, "%s_p_%s = &%s%s;\n", local_var_prefix, n, local_var_prefix, n);
     }
     else if (is_ptr(t) || is_array(t))
         print_file(file, indent, "%s%s = 0;\n", local_var_prefix, n);
 }
 
 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->decltype.type);
 
-    if (!is_void(var->type))
-        write_var_init(file, indent, var->type, var->name, local_var_prefix);
+    if (!is_void(var->decltype.type))
+        write_var_init(file, indent, var->decltype.type, var->name, local_var_prefix);
 
-    if (!type_get_function_args(func->type))
+    if (!type_get_function_args(func->decltype.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_get_function_args(func->decltype.type), const var_t, entry )
+        write_var_init(file, indent, var->decltype.type, var->name, local_var_prefix);
 
     fprintf(file, "\n");
 }
 
 static void write_formatdesc(FILE *f, int indent, const char *str)
 {
     print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
     print_file(f, indent, "{\n");
@@ -975,75 +983,75 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
     *flags = 0;
     *stack_size = get_stack_size( var, &is_byval );
     *typestring_offset = var->typestring_offset;
 
     if (is_in)     *flags |= IsIn;
     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->decltype.type ))
+        buffer_size = get_required_buffer_size_type( var->decltype.type, NULL, var->attrs, TRUE, &alignment );
 
-    switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES ))
+    switch (typegen_detect_type( var->decltype.type, var->attrs, TDT_ALL_TYPES ))
     {
     case TGT_BASIC:
         *flags |= IsBasetype;
-        fc = get_basic_fc_signed( var->type );
+        fc = get_basic_fc_signed( var->decltype.type );
         if (fc == FC_BIND_PRIMITIVE)
         {
             buffer_size = 4;  /* actually 0 but avoids setting MustSize */
             fc = FC_LONG;
         }
         break;
     case TGT_ENUM:
         *flags |= IsBasetype;
-        fc = get_enum_fc( var->type );
+        fc = get_enum_fc( var->decltype.type );
         break;
     case TGT_RANGE:
         *flags |= IsByValue;
         break;
     case TGT_STRUCT:
     case TGT_UNION:
     case TGT_USER_TYPE:
         *flags |= MustFree | (is_byval ? IsByValue : IsSimpleRef);
         break;
     case TGT_IFACE_POINTER:
         *flags |= MustFree;
         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->decltype.type) && var->decltype.type->details.array.ptr_tfsoff &&
+            get_pointer_fc( var->decltype.type, var->attrs, !is_return ) == FC_RP)
         {
-            *typestring_offset = var->type->typestring_offset;
+            *typestring_offset = var->decltype.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->decltype.type ) && get_pointer_fc( var->decltype.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->decltype.type )) *typestring_offset += 4;
             else *typestring_offset += 2;
             *flags |= IsSimpleRef;
         }
         break;
     case TGT_CTXT_HANDLE_POINTER:
         *flags |= IsSimpleRef;
         *typestring_offset += 4;
         /* fall through */
     case TGT_CTXT_HANDLE:
         buffer_size = 20;
         break;
     case TGT_POINTER:
-        if (get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP)
+        if (get_pointer_fc( var->decltype.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->decltype.type );
 
             if (!is_string_type( var->attrs, ref ))
                 buffer_size = get_required_buffer_size_type( ref, NULL, NULL, TRUE, &alignment );
 
             switch (typegen_detect_type( ref, NULL, TDT_ALL_TYPES ))
             {
             case TGT_BASIC:
                 *flags |= IsSimpleRef | IsBasetype;
@@ -1115,33 +1123,33 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
         if (server_size < 8) *flags |= server_size << 13;
     }
     return fc;
 }
 
 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_get_function_args( func->decltype.type );
+    var_t *retval = type_function_get_retval( func->decltype.type );
     unsigned char oi2_flags = 0x40;  /* HasExtensions */
     unsigned short flags;
     unsigned int stack_size, typestring_offset;
 
     if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
     {
         get_parameter_fc( var, 0, &flags, &stack_size, &typestring_offset );
         if (flags & MustSize)
         {
             if (flags & IsIn) oi2_flags |= 0x02; /* ClientMustSize */
             if (flags & IsOut) oi2_flags |= 0x01;  /* ServerMustSize */
         }
     }
 
-    if (!is_void( retval->type ))
+    if (!is_void( retval->decltype.type ))
     {
         oi2_flags |= 0x04;  /* HasRet */
         get_parameter_fc( retval, 1, &flags, &stack_size, &typestring_offset );
         if (flags & MustSize) oi2_flags |= 0x01;  /* ServerMustSize */
     }
     return oi2_flags;
 }
 
@@ -1185,50 +1193,50 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons
 {
     unsigned int size;
 
     int is_in = is_attr(var->attrs, ATTR_IN);
     int is_out = is_attr(var->attrs, ATTR_OUT);
 
     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->decltype.type) == TYPE_BASIC ||
+        type_get_type(var->decltype.type) == TYPE_ENUM)
     {
         unsigned char fc;
 
         if (is_return)
             print_file(file, indent, "0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
         else
             print_file(file, indent, "0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
 
-        if (type_get_type(var->type) == TYPE_ENUM)
+        if (type_get_type(var->decltype.type) == TYPE_ENUM)
         {
-            fc = get_enum_fc(var->type);
+            fc = get_enum_fc(var->decltype.type);
         }
         else
         {
-            fc = get_basic_fc_signed(var->type);
+            fc = get_basic_fc_signed(var->decltype.type);
 
             if (fc == FC_BIND_PRIMITIVE)
                 fc = FC_IGNORE;
         }
 
         print_file(file, indent, "0x%02x,    /* %s */\n",
                    fc, string_of_type(fc));
         size = 2; /* includes param type prefix */
     }
     else
     {
         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->decltype.type) &&
+            type_array_is_decl_as_ptr(var->decltype.type) &&
+            var->decltype.type->details.array.ptr_tfsoff)
+            offset = var->decltype.type->typestring_offset;
 
         if (is_return)
             print_file(file, indent, "0x52,    /* FC_RETURN_PARAM */\n");
         else if (is_in && is_out)
             print_file(file, indent, "0x50,    /* FC_IN_OUT_PARAM */\n");
         else if (is_out)
             print_file(file, indent, "0x51,    /* FC_OUT_PARAM */\n");
         else
@@ -1241,18 +1249,18 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons
     }
     return size;
 }
 
 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_get_function_args( func->decltype.type );
+    const type_t *ret_type = type_function_get_rettype( func->decltype.type );
 
     if (type_get_type( ret_type ) == TYPE_BASIC)
     {
         switch (type_basic_get_type( ret_type ))
         {
         case TYPE_BASIC_INT64:
         case TYPE_BASIC_HYPER:
             /* return value must fit in a long_ptr */
@@ -1264,20 +1272,20 @@ int is_interpreted_func( const type_t *iface, const var_t *func )
             return 0;
         default:
             break;
         }
     }
     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->decltype.type ))
             {
             case TYPE_BASIC:
-                switch (type_basic_get_type( var->type ))
+                switch (type_basic_get_type( var->decltype.type ))
                 {
                 /* floating point arguments are not supported in Oi mode */
                 case TYPE_BASIC_FLOAT:  return 0;
                 case TYPE_BASIC_DOUBLE: return 0;
                 default: break;
                 }
                 break;
             /* unions passed by value are not supported in Oi mode */
@@ -1292,17 +1300,17 @@ int is_interpreted_func( const type_t *iface, const var_t *func )
     return (get_stub_mode() != MODE_Os);
 }
 
 static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
                                     const var_t *func, unsigned int *offset,
                                     unsigned short num_proc )
 {
     var_t *var;
-    var_list_t *args = type_get_function_args( func->type );
+    var_list_t *args = type_get_function_args( func->decltype.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 );
     unsigned char oi_flags = Oi_HAS_RPCFLAGS | Oi_USE_NEW_INIT_ROUTINES;
     unsigned int rpc_flags = get_rpc_flags( func->attrs );
     unsigned int nb_args = 0;
     unsigned int stack_size = 0;
     unsigned short param_num = 0;
@@ -1323,17 +1331,17 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
         {
             handle_stack_offset = stack_size;
             handle_param_num = param_num;
         }
         stack_size += get_stack_size( var, NULL );
         param_num++;
         nb_args++;
     }
-    if (!is_void( type_function_get_rettype( func->type )))
+    if (!is_void( type_function_get_rettype( func->decltype.type )))
     {
         stack_size += pointer_size;
         nb_args++;
     }
 
     print_file( file, 0, "/* %u (procedure %s::%s) */\n", *offset, iface->name, func->name );
     print_file( file, indent, "0x%02x,\t/* %s */\n", implicit_fc,
                 implicit_fc ? string_of_type(implicit_fc) : "explicit handle" );
@@ -1351,32 +1359,32 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
             handle_flags = 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 );
             *offset += 4;
             break;
         case FC_BIND_GENERIC:
-            handle_flags = type_memsize( handle_var->type );
+            handle_flags = type_memsize( handle_var->decltype.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->decltype.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, 0 );
+            handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->decltype.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->decltype.type ) );
             print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num );
             *offset += 6;
             break;
         }
     }
 
     if (get_stub_mode() == MODE_Oif)
     {
@@ -1402,19 +1410,19 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
         *offset += 14;
         if (pointer_size == 8)
         {
             unsigned short pos = 0, fpu_mask = 0;
 
             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->decltype.type ) == TYPE_BASIC)
                 {
-                    switch (type_basic_get_type( var->type ))
+                    switch (type_basic_get_type( var->decltype.type ))
                     {
                     case TYPE_BASIC_FLOAT:  fpu_mask |= 1 << pos; break;
                     case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break;
                     default: break;
                     }
                 }
                 pos += 2;
                 if (pos >= 16) break;
@@ -1427,36 +1435,36 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
 
 static void write_procformatstring_func( FILE *file, int indent, const type_t *iface,
                                          const var_t *func, unsigned int *offset,
                                          unsigned short num_proc )
 {
     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->decltype.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_get_function_args(func->decltype.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_get_function_args(func->decltype.type), const var_t, entry )
         {
             print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name );
             if (is_new_style)
                 *offset += write_new_procformatstring_type(file, indent, var, FALSE, &stack_offset);
             else
                 *offset += write_old_procformatstring_type(file, indent, var, FALSE, is_interpreted);
         }
     }
 
     /* emit return value data */
-    if (is_void(retval->type))
+    if (is_void(retval->decltype.type))
     {
         if (!is_new_style)
         {
             print_file(file, 0, "/* %u (void) */\n", *offset);
             print_file(file, indent, "0x5b,\t/* FC_END */\n");
             print_file(file, indent, "0x5c,\t/* FC_PAD */\n");
             *offset += 2;
         }
@@ -1593,17 +1601,17 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
 
         return 4;
     }
 
     if (!cont_type)  /* top-level conformance */
     {
         conftype = FC_TOP_LEVEL_CONFORMANCE;
         conftype_string = "parameter";
-        cont_type = current_func->type;
+        cont_type = current_func->decltype.type;
         name = current_func->name;
         iface = current_iface;
     }
     else
     {
         name = cont_type->name;
         if (is_ptr(type) || (is_array(type) && type_array_is_decl_as_ptr(type)))
         {
@@ -1664,33 +1672,33 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
             var_list_t *args = type_get_function_args( cont_type );
 
             if (is_object( iface )) offset += pointer_size;
             if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
             {
                 if (var->name && !strcmp(var->name, subexpr->u.sval))
                 {
                     expr_loc.v = var;
-                    correlation_variable = var->type;
+                    correlation_variable = var->decltype.type;
                     break;
                 }
                 offset += get_stack_size( var, NULL );
             }
         }
         else
         {
             var_list_t *fields = type_struct_get_fields( 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->decltype.type, &offset );
                 if (var->name && !strcmp(var->name, subexpr->u.sval))
                 {
                     expr_loc.v = var;
-                    correlation_variable = var->type;
+                    correlation_variable = var->decltype.type;
                     break;
                 }
                 offset += size;
             }
         }
 
         if (!correlation_variable)
             error("write_conf_or_var_desc: couldn't find variable %s in %s\n", subexpr->u.sval, name);
@@ -1819,17 +1827,17 @@ static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align
     unsigned int size = 0;
     unsigned int max_align;
     const var_t *v;
 
     if (!fields) return 0;
     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->decltype.type, &falign);
         if (*align < falign) *align = falign;
         falign = clamp_align(falign);
         size = ROUND_SIZE(size, falign);
         size += fsize;
     }
 
     max_align = clamp_align(*align);
     size = ROUND_SIZE(size, max_align);
@@ -1841,19 +1849,19 @@ static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa)
 {
     unsigned int size, maxs = 0;
     unsigned int align = *pmaxa;
     const var_t *v;
 
     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->decltype.type)
         {
-            size = type_memsize_and_alignment(v->type, &align);
+            size = type_memsize_and_alignment(v->decltype.type, &align);
             if (maxs < size) maxs = size;
             if (*pmaxa < align) *pmaxa = align;
         }
     }
 
     return maxs;
 }
 
@@ -1931,22 +1939,22 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
         size = pointer_size;
         if (size > *align) *align = size;
         break;
     case TYPE_ARRAY:
         if (!type_array_is_decl_as_ptr(t))
         {
             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 */
         {
             assert( pointer_size );
             size = pointer_size;
             if (size > *align) *align = size;
         }
         break;
@@ -2016,42 +2024,42 @@ static unsigned int type_buffer_alignment(const type_t *t)
         default:
             error("type_buffer_alignment: Unknown enum type\n");
         }
         break;
     case TYPE_STRUCT:
         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->decltype.type) continue;
+            align = type_buffer_alignment( var->decltype.type );
             if (max < align) max = align;
         }
         break;
     case TYPE_ENCAPSULATED_UNION:
         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->decltype.type) continue;
+            align = type_buffer_alignment( var->decltype.type );
             if (max < align) max = align;
         }
         break;
     case TYPE_UNION:
         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->decltype.type) continue;
+            align = type_buffer_alignment( var->decltype.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;
     case TYPE_INTERFACE:
     case TYPE_ALIAS:
     case TYPE_VOID:
     case TYPE_COCLASS:
     case TYPE_MODULE:
@@ -2064,22 +2072,22 @@ static unsigned int type_buffer_alignment(const type_t *t)
         assert(0);
     }
     return max;
 }
 
 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->decltype.type), func->attrs, TRUE))
         return TRUE;
-    if (!type_get_function_args(func->type))
+    if (!type_get_function_args(func->decltype.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_get_function_args(func->decltype.type), const var_t, entry )
+        if (type_has_full_pointer( var->decltype.type, var->attrs, TRUE ))
             return TRUE;
     return FALSE;
 }
 
 void write_full_pointer_init(FILE *file, int indent, const var_t *func, int is_server)
 {
     print_file(file, indent, "__frame->_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
                    is_server ? "XLAT_SERVER" : "XLAT_CLIENT");
@@ -2114,17 +2122,17 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs
     {
         if (out_attr && !in_attr && pointer_type == FC_RP)
             flags |= FC_ALLOCED_ON_STACK;
     }
     else if (get_stub_mode() == MODE_Oif)
     {
         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:
                 flags |= FC_ALLOCED_ON_STACK;
                 break;
             case TGT_IFACE_POINTER:
@@ -2134,17 +2142,17 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs
             default:
                 break;
             }
         }
     }
 
     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;
     }
 
     print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
                pointer_type,
                flags,
                string_of_type(pointer_type));
@@ -2175,17 +2183,17 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
 
     /* for historical reasons, write_simple_pointer also handled string types,
      * but no longer does. catch bad uses of the function with this check */
     if (is_string_type(attrs, type))
         error("write_simple_pointer: can't handle type %s which is a string type\n", type->name);
 
     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
         fc = get_basic_fc(ref);
 
     if (!is_interpreted_func(current_iface, current_func))
     {
         if (out_attr && !in_attr && pointer_fc == FC_RP)
@@ -2200,32 +2208,33 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
     print_file(file, 2, "0x%02x, 0x%x,\t/* %s %s[simple_pointer] */\n",
                pointer_fc, flags, string_of_type(pointer_fc),
                flags & FC_ALLOCED_ON_STACK ? "[allocated_on_stack] " : "");
     print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
     print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
     return 4;
 }
 
-static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
+static void print_start_tfs_comment(FILE *file, decl_type_t *dt, unsigned int tfsoff)
 {
     print_file(file, 0, "/* %u (", tfsoff);
-    write_type_decl(file, t, NULL);
+    write_decltype_decl(file, dt, 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,
+                                      decl_type_t *decltype, 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 = decltype->type;
+    type_t *ref = type_pointer_get_ref_type(type);
 
-    print_start_tfs_comment(file, type, offset);
+    print_start_tfs_comment(file, decltype, offset);
     update_tfsoff(type, offset, file);
 
     switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES))
     {
     case TGT_BASIC:
     case TGT_ENUM:
         *typestring_offset += write_simple_pointer(file, attrs, type, context);
         break;
@@ -2258,21 +2267,23 @@ static int user_type_has_variable_size(const type_t *t)
             return TRUE;
         }
     }
     /* Note: Since this only applies to user types, we can't have a conformant
        array here, and strings should get filed under pointer in this case.  */
     return FALSE;
 }
 
-static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
+static unsigned int write_user_tfs(FILE *file, decl_type_t *decltype, unsigned int *tfsoff)
 {
     unsigned int start, absoff, flags;
     const char *name = NULL;
-    type_t *utype = get_user_type(type, &name);
+    type_t *type = decltype->type;
+    decl_type_t *udecltype = get_user_decltype(type, &name);
+    type_t *utype = udecltype ? udecltype->type : NULL;
     unsigned int usize = type_memsize(utype);
     unsigned int ualign = type_buffer_alignment(utype);
     unsigned int size = type_memsize(type);
     unsigned short funoff = user_type_offset(name);
     short reloff;
 
     if (processed(type)) return type->typestring_offset;
 
@@ -2286,38 +2297,40 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof
         unsigned char fc;
 
         if (type_get_type(utype) == TYPE_ENUM)
             fc = get_enum_fc(utype);
         else
             fc = get_basic_fc(utype);
 
         absoff = *tfsoff;
-        print_start_tfs_comment(file, utype, absoff);
+        print_start_tfs_comment(file, udecltype, 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;
     }
     else
     {
         if (!processed(utype))
-            write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
+        {
+            write_embedded_types(file, NULL, udecltype, utype->name, TRUE, tfsoff);
+        }
         absoff = utype->typestring_offset;
     }
 
     if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_RP)
         flags = 0x40;
     else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_UP)
         flags = 0x80;
     else
         flags = 0;
 
     start = *tfsoff;
     update_tfsoff(type, start, file);
-    print_start_tfs_comment(file, type, start);
+    print_start_tfs_comment(file, decltype, 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);
     print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)usize, usize);
     *tfsoff += 8;
     reloff = absoff - *tfsoff;
@@ -2364,41 +2377,42 @@ static void write_member_type(FILE *file, const type_t *cont,
     }
     else if (!write_base_type(file, type, tfsoff))
         error("Unsupported member type %d\n", type_get_type(type));
 }
 
 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);
+    decl_type_t *elem = type_array_get_element(type);
+    type_t *elemtype = elem->type;
 
-    if (!is_embedded_complex(elem) && is_ptr(elem))
+    if (!is_embedded_complex(elemtype) && is_ptr(elemtype))
     {
-        type_t *ref = type_pointer_get_ref(elem);
+        type_t *ref = type_pointer_get_ref_type(elemtype);
 
         if (processed(ref))
         {
-            write_nonsimple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER,
+            write_nonsimple_pointer(file, NULL, elemtype, TYPE_CONTEXT_CONTAINER,
                                     ref->typestring_offset, tfsoff);
             return;
         }
-        if (cont_is_complex && is_string_type(attrs, elem))
+        if (cont_is_complex && is_string_type(attrs, elemtype))
         {
             write_string_tfs(file, NULL, elem, TYPE_CONTEXT_CONTAINER, NULL, tfsoff);
             return;
         }
-        if (!is_string_type(NULL, elem) &&
+        if (!is_string_type(NULL, elemtype) &&
             (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM))
         {
-            *tfsoff += write_simple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER);
+            *tfsoff += write_simple_pointer(file, NULL, elemtype, TYPE_CONTEXT_CONTAINER);
             return;
         }
     }
-    write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff);
+    write_member_type(file, type, cont_is_complex, NULL, elemtype, NULL, tfsoff);
 }
 
 static void write_end(FILE *file, unsigned int *tfsoff)
 {
     if (*tfsoff % 2 == 0)
     {
         print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
         *tfsoff += 1;
@@ -2410,17 +2424,17 @@ static void write_end(FILE *file, unsigned int *tfsoff)
 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
 {
     unsigned int offset = 0;
     var_list_t *fs = type_struct_get_fields(type);
     var_t *f;
 
     if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
     {
-        type_t *ft = f->type;
+        type_t *ft = f->decltype.type;
         unsigned int size = field_memsize( ft, &offset );
         if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS))
         {
             short reloff;
             unsigned int absoff = ft->typestring_offset;
             if (is_attr(ft->attrs, ATTR_SWITCHTYPE))
                 absoff += 8; /* we already have a corr descr, skip it */
             reloff = absoff - (*tfsoff + 6);
@@ -2433,23 +2447,24 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
                        (unsigned short)reloff, reloff, absoff);
             *tfsoff += 8;
         }
         offset += size;
     }
 }
 
 static int write_pointer_description_offsets(
-    FILE *file, const attr_list_t *attrs, type_t *type,
+    FILE *file, const attr_list_t *attrs, decl_type_t *decltype,
     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
     unsigned int *typestring_offset)
 {
+    type_t *type = decltype->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)
         {
             unsigned int memsize;
 
             /* pointer instance
              *
@@ -2464,20 +2479,20 @@ static int write_pointer_description_offsets(
             /* increment these separately as in the case of conformant (varying)
              * structures these start at different values */
             *offset_in_buffer += memsize;
         }
         *typestring_offset += 4;
 
         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, decltype, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset);
             else if (processed(ref))
                 write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER,
                                         ref->typestring_offset, typestring_offset);
             else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)
                 *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER);
             else
                 error("write_pointer_description_offsets: type format string unknown\n");
         }
@@ -2505,23 +2520,23 @@ static int write_pointer_description_offsets(
         /* otherwise search for interesting fields to parse */
         const var_t *v;
         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
         {
             if (offset_in_memory && offset_in_buffer)
             {
                 unsigned int padding;
                 unsigned int align = 0;
-                type_memsize_and_alignment(v->type, &align);
+                type_memsize_and_alignment(v->decltype.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, (decl_type_t*)&v->decltype, offset_in_memory, offset_in_buffer,
                 typestring_offset);
         }
     }
     else
     {
         if (offset_in_memory && offset_in_buffer)
         {
             unsigned int memsize = type_memsize(type);
@@ -2531,49 +2546,50 @@ static int write_pointer_description_offsets(
             *offset_in_buffer += memsize;
         }
     }
 
     return written;
 }
 
 static int write_no_repeat_pointer_descriptions(
-    FILE *file, const attr_list_t *attrs, type_t *type,
+    FILE *file, const attr_list_t *attrs, decl_type_t *decltype,
     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
     unsigned int *typestring_offset)
 {
+    type_t *type = decltype->type;
     int written = 0;
 
     if (is_ptr(type) ||
         (is_conformant_array(type) && type_array_is_decl_as_ptr(type)))
     {
         print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", FC_NO_REPEAT);
         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, decltype,
                        offset_in_memory, offset_in_buffer, typestring_offset);
     }
 
     if (is_non_complex_struct(type))
     {
         const var_t *v;
         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
         {
             if (offset_in_memory && offset_in_buffer)
             {
                 unsigned int padding;
                 unsigned int align = 0;
-                type_memsize_and_alignment(v->type, &align);
+                type_memsize_and_alignment(v->decltype.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, (decl_type_t*)&v->decltype,
                 offset_in_memory, offset_in_buffer, typestring_offset);
         }
     }
     else
     {
         unsigned int memsize = type_memsize(type);
         *offset_in_memory += memsize;
         /* increment these separately as in the case of conformant (varying)
@@ -2582,67 +2598,68 @@ static int write_no_repeat_pointer_descriptions(
     }
 
     return written;
 }
 
 /* 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, decl_type_t *decltype,
     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
     unsigned int *typestring_offset)
 {
+    type_t *type = decltype->type;
     int pointer_count = 0;
 
     if (type_get_type(type) == TYPE_ARRAY &&
         !type_array_has_conformance(type) && !type_array_has_variance(type))
     {
         unsigned int temp = 0;
         /* unfortunately, this needs to be done in two passes to avoid
          * writing out redundant FC_FIXED_REPEAT descriptions */
         pointer_count = write_pointer_description_offsets(
             NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
         if (pointer_count > 0)
         {
             unsigned int increment_size;
             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);
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Iterations = %d */\n", (unsigned short)type_array_get_dim(type), type_array_get_dim(type));
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
             *typestring_offset += 10;
 
             pointer_count = write_pointer_description_offsets(
-                file, attrs, type, &offset_of_array_pointer_mem,
+                file, attrs, decltype, &offset_of_array_pointer_mem,
                 &offset_of_array_pointer_buf, typestring_offset);
         }
     }
     else if (type_get_type(type) == TYPE_STRUCT)
     {
         const var_t *v;
         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
         {
             if (offset_in_memory && offset_in_buffer)
             {
                 unsigned int padding;
                 unsigned int align = 0;
-                type_memsize_and_alignment(v->type, &align);
+                type_memsize_and_alignment(v->decltype.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, (decl_type_t*)&v->decltype, offset_in_memory, offset_in_buffer,
                 typestring_offset);
         }
     }
     else
     {
         if (offset_in_memory && offset_in_buffer)
         {
             unsigned int memsize;
@@ -2673,17 +2690,17 @@ static int write_conformant_array_pointer_descriptions(
         pointer_count = write_pointer_description_offsets(
             NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
         if (pointer_count > 0)
         {
             unsigned int increment_size;
             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);
 
             print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
             print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", FC_FIXED_OFFSET);
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)offset_in_memory, offset_in_memory);
@@ -2715,17 +2732,17 @@ static int write_varying_array_pointer_descriptions(
         /* unfortunately, this needs to be done in two passes to avoid
          * writing out redundant FC_VARIABLE_REPEAT descriptions */
         pointer_count = write_pointer_description_offsets(
             NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
         if (pointer_count > 0)
         {
             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);
 
             print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
             print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", FC_VARIABLE_OFFSET);
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
@@ -2741,30 +2758,30 @@ static int write_varying_array_pointer_descriptions(
     {
         const var_t *v;
         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
         {
             if (offset_in_memory && offset_in_buffer)
             {
                 unsigned int align = 0, padding;
 
-                if (is_array(v->type) && type_array_has_variance(v->type))
+                if (is_array(v->decltype.type) && type_array_has_variance(v->decltype.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->decltype.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->decltype.type, offset_in_memory, offset_in_buffer,
                 typestring_offset);
         }
     }
     else
     {
         if (offset_in_memory && offset_in_buffer)
         {
             unsigned int memsize = type_memsize(type);
@@ -2773,99 +2790,103 @@ static int write_varying_array_pointer_descriptions(
              * structures these start at different values */
             *offset_in_buffer += memsize;
         }
     }
 
     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, decl_type_t *decltype,
                                       unsigned int *typestring_offset)
 {
+    type_t *type = decltype->type;
     unsigned int offset_in_buffer;
     unsigned int offset_in_memory;
 
     /* pass 1: search for single instance of a pointer (i.e. don't descend
      * into arrays) */
     if (!is_array(type))
     {
         offset_in_memory = 0;
         offset_in_buffer = 0;
         write_no_repeat_pointer_descriptions(
-            file, NULL, type,
+            file, NULL, decltype,
             &offset_in_memory, &offset_in_buffer, typestring_offset);
     }
 
     /* pass 2: search for pointers in fixed arrays */
     offset_in_memory = 0;
     offset_in_buffer = 0;
     write_fixed_array_pointer_descriptions(
-        file, NULL, type,
+        file, NULL, decltype,
         &offset_in_memory, &offset_in_buffer, typestring_offset);
 
     /* pass 3: search for pointers in conformant only arrays (but don't descend
      * into conformant varying or varying arrays) */
     if (is_conformant_array(type) &&
         (type_array_is_decl_as_ptr(type) || !current_structure))
         write_conformant_array_pointer_descriptions(
             file, attrs, type, 0, typestring_offset);
     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)->decltype.type;
         write_conformant_array_pointer_descriptions( file, NULL, carray,
                                                      type_memsize(type), typestring_offset);
     }
 
     /* pass 4: search for pointers in varying arrays */
     offset_in_memory = 0;
     offset_in_buffer = 0;
     write_varying_array_pointer_descriptions(
             file, NULL, type,
             &offset_in_memory, &offset_in_buffer, typestring_offset);
 }
 
 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
-                                     type_t *type, enum type_context context,
+                                     decl_type_t *decltype, enum type_context context,
                                      const char *name, unsigned int *typestring_offset)
 {
+    type_t *type = decltype->type;
     unsigned int start_offset;
     unsigned char rtype;
     type_t *elem_type;
     int is_processed = processed(type);
 
     start_offset = *typestring_offset;
 
     if (is_declptr(type))
     {
         unsigned char flag = is_conformant_array(type) ? 0 : FC_SIMPLE_POINTER;
         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, decltype, *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]" : "");
         *typestring_offset += 2;
         if (!flag)
         {
             print_file(file, 2, "NdrFcShort(0x2),\n");
             *typestring_offset += 2;
         }
         is_processed = FALSE;
     }
 
     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, decltype, name, typestring_offset);
 
     if (type_get_type(elem_type) != TYPE_BASIC)
     {
         error("write_string_tfs: Unimplemented for non-basic type %s\n", name);
         return start_offset;
     }
 
     rtype = get_basic_fc(elem_type);
@@ -2929,44 +2950,45 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
         print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
         *typestring_offset += 2;
 
         update_tfsoff(type, start_offset, file);
         return start_offset;
     }
 }
 
-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, decl_type_t *decltype,
                                     const char *name, unsigned int *typestring_offset)
 {
+    type_t *type = decltype->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, decltype, 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;
 
     align = 0;
     if (fc != FC_BOGUS_ARRAY)
     {
         if (fc == FC_LGFARRAY || fc == FC_LGVARRAY)
@@ -2982,17 +3004,17 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t
 
         if (is_conformant_array(type))
             *typestring_offset
                 += write_conf_or_var_desc(file, current_structure, baseoff,
                                           type, size_is);
 
         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)
             {
                 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", dim, dim);
                 *typestring_offset += 4;
             }
             else
@@ -3005,23 +3027,23 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t
             *typestring_offset += 2;
         }
 
         if (length_is)
             *typestring_offset
                 += 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, decltype, typestring_offset);
             print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
             *typestring_offset += 1;
         }
 
         write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, FALSE, typestring_offset);
         write_end(file, typestring_offset);
     }
     else
@@ -3048,17 +3070,17 @@ static const var_t *find_array_or_string_in_struct(const type_t *type)
     const var_list_t *fields = type_struct_get_fields(type);
     const var_t *last_field;
     const type_t *ft;
 
     if (!fields || list_empty(fields))
         return NULL;
 
     last_field = LIST_ENTRY( list_tail(fields), const var_t, entry );
-    ft = last_field->type;
+    ft = last_field->decltype.type;
 
     if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft))
         return last_field;
 
     if (type_get_type(ft) == TYPE_STRUCT)
         return find_array_or_string_in_struct(ft);
     else
         return NULL;
@@ -3071,17 +3093,17 @@ static void write_struct_members(FILE *file, const type_t *type,
     const var_t *field;
     unsigned short offset = 0;
     unsigned int salign = 1;
     int padding;
     var_list_t *fields = type_struct_get_fields(type);
 
     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
     {
-        type_t *ft = field->type;
+        type_t *ft = field->decltype.type;
         unsigned int align = 0;
         unsigned int size = type_memsize_and_alignment(ft, &align);
         align = clamp_align(align);
         if (salign < align) salign = align;
 
         if (!is_conformant_array(ft) || type_array_is_decl_as_ptr(ft))
         {
             if ((align - 1) & offset)
@@ -3100,17 +3122,17 @@ static void write_struct_members(FILE *file, const type_t *type,
                     break;
                 default:
                     error("write_struct_members: cannot align type %d\n", type_get_type(ft));
                 }
                 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
                 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->decltype.type, corroff,
                               typestring_offset);
             offset += size;
         }
     }
 
     padding = ROUNDING(offset, salign);
     if (padding)
     {
@@ -3118,19 +3140,20 @@ static void write_struct_members(FILE *file, const type_t *type,
                    FC_STRUCTPAD1 + padding - 1,
                    padding);
         *typestring_offset += 1;
     }
 
     write_end(file, typestring_offset);
 }
 
-static unsigned int write_struct_tfs(FILE *file, type_t *type,
+static unsigned int write_struct_tfs(FILE *file, decl_type_t *decltype,
                                      const char *name, unsigned int *tfsoff)
 {
+    type_t *type = decltype->type;
     const type_t *save_current_structure = current_structure;
     unsigned int total_size;
     const var_t *array;
     unsigned int start_offset;
     unsigned int align;
     unsigned int corroff;
     var_t *f;
     unsigned char fc = get_struct_fc(type);
@@ -3143,41 +3166,41 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type,
 
     total_size = type_memsize(type);
     align = type_buffer_alignment(type);
     if (total_size > USHRT_MAX)
         error("structure size for %s exceeds %d bytes by %d bytes\n",
               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->decltype, f->name, FALSE, tfsoff);
 
     array = find_array_or_string_in_struct(type);
-    if (array && !processed(array->type))
+    if (array && !processed(array->decltype.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->decltype.type))
+            write_string_tfs(file, array->attrs, (decl_type_t*)&array->decltype, TYPE_CONTEXT_CONTAINER, array->name, tfsoff);
         else
-            write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
+            write_array_tfs(file, array->attrs, (decl_type_t*)&array->decltype, array->name, tfsoff);
     }
 
     corroff = *tfsoff;
     write_descriptors(file, type, tfsoff);
 
     start_offset = *tfsoff;
     update_tfsoff(type, start_offset, file);
-    print_start_tfs_comment(file, type, start_offset);
+    print_start_tfs_comment(file, decltype, 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);
     *tfsoff += 4;
 
     if (array)
     {
-        unsigned int absoff = array->type->typestring_offset;
+        unsigned int absoff = array->decltype.type->typestring_offset;
         short reloff = absoff - *tfsoff;
         print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
                    reloff, reloff, absoff);
         *tfsoff += 2;
     }
     else if (fc == FC_BOGUS_STRUCT)
     {
         print_file(file, 2, "NdrFcShort(0x0),\n");
@@ -3198,40 +3221,41 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type,
     }
     else if ((fc == FC_PSTRUCT) ||
              (fc == FC_CPSTRUCT) ||
              (fc == FC_CVSTRUCT && type_has_pointers(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, decltype, tfsoff);
         print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
         *tfsoff += 1;
     }
 
     write_struct_members(file, type, fc == FC_BOGUS_STRUCT, &corroff,
                          tfsoff);
 
     if (fc == FC_BOGUS_STRUCT)
     {
         const var_t *f;
 
         type->ptrdesc = *tfsoff;
         if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
         {
-            type_t *ft = f->type;
+            decl_type_t *fdt = (decl_type_t*)&f->decltype;
+            type_t *ft = fdt->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, fdt, 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, fdt,
+                                      type_pointer_get_ref_type(ft)->typestring_offset,
                                       TYPE_CONTEXT_CONTAINER, tfsoff);
                 break;
             case TGT_ARRAY:
                 if (type_array_is_decl_as_ptr(ft))
                 {
                     unsigned int offset;
 
                     print_file(file, 0, "/* %d */\n", *tfsoff);
@@ -3283,18 +3307,19 @@ static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
         else
             error("write_branch_type: type unimplemented %d\n", type_get_type(t));
     }
 
     *tfsoff += 2;
 }
 
 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
-                                    type_t *type, unsigned int *tfsoff)
+                                    decl_type_t *decltype, unsigned int *tfsoff)
 {
+    type_t* type = decltype->type;
     unsigned int start_offset;
     unsigned int size;
     var_list_t *fields;
     unsigned int nbranch = 0;
     type_t *deftype = NULL;
     short nodeftype = 0xffff;
     unsigned int dummy;
     var_t *f;
@@ -3309,27 +3334,28 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
 
     size = union_memsize(fields, &dummy);
 
     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
     {
         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->decltype.type)
+            write_embedded_types(file, f->attrs, &f->decltype, 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, decltype, 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->decltype.type;
         unsigned int align = 0;
         unsigned char fc;
 
         if (type_get_type(st) == TYPE_BASIC)
         {
             fc = get_basic_fc(st);
             switch (fc)
             {
@@ -3351,18 +3377,18 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
         else if (type_get_type(st) == TYPE_ENUM)
             fc = get_enum_fc(st);
         else
             error("union switch type must be an integer, char, or enum\n");
 
         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->decltype.type)
+                type_memsize_and_alignment(f->decltype.type, &align);
         }
 
         print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION);
         print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
                    (align << 4) | fc, string_of_type(fc));
         *tfsoff += 2;
     }
     else if (is_attr(type->attrs, ATTR_SWITCHTYPE))
@@ -3407,17 +3433,17 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
     }
 
     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)size, size);
     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)nbranch, nbranch);
     *tfsoff += 4;
 
     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
     {
-        type_t *ft = f->type;
+        type_t *ft = f->decltype.type;
         expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
         int deflt = is_attr(f->attrs, ATTR_DEFAULT);
         expr_t *c;
 
         if (cases == NULL && !deflt)
             error("union field %s with neither case nor default attribute\n", f->name);
 
         if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
@@ -3448,38 +3474,39 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
     {
         print_file(file, 2, "NdrFcShort(0x%hx),\n", nodeftype);
         *tfsoff += 2;
     }
 
     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, decl_type_t *decltype,
                                  unsigned int *typeformat_offset)
 {
     unsigned int i;
+    type_t *type = decltype->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, decltype, start_offset);
     update_tfsoff(type, start_offset, file);
 
     if (iid)
     {
         print_file(file, 2, "0x2f,  /* FC_IP */\n");
         print_file(file, 2, "0x5c,  /* FC_PAD */\n");
         *typeformat_offset
             += write_conf_or_var_desc(file, current_structure, 0, type, iid) + 2;
     }
     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)
             error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
 
         print_file(file, 2, "0x2f,\t/* FC_IP */\n");
         print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
         print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1);
@@ -3493,24 +3520,25 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t
 
         *typeformat_offset += 18;
     }
     return start_offset;
 }
 
 static unsigned int write_contexthandle_tfs(FILE *file,
                                             const attr_list_t *attrs,
-                                            type_t *type,
+                                            decl_type_t *decltype,
                                             enum type_context context,
                                             unsigned int *typeformat_offset)
 {
+    type_t *type = decltype->type;
     unsigned int start_offset = *typeformat_offset;
     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, decltype, start_offset);
 
     if (flags & 0x80)  /* via ptr */
     {
         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) );
         print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset);
@@ -3568,40 +3596,41 @@ static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
     print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval);
     update_tfsoff( type, start_offset, file );
     *typeformat_offset += 10;
 
     return start_offset;
 }
 
 static unsigned int write_type_tfs(FILE *file, int indent,
-                                   const attr_list_t *attrs, type_t *type,
+                                   const attr_list_t *attrs, decl_type_t *decltype,
                                    const char *name,
                                    enum type_context context,
                                    unsigned int *typeformat_offset)
 {
     unsigned int offset;
+    type_t *type = decltype->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, typeformat_offset);
+        return write_contexthandle_tfs(file, attrs, decltype, context, typeformat_offset);
     case TGT_USER_TYPE:
-        return write_user_tfs(file, type, typeformat_offset);
+        return write_user_tfs(file, decltype, typeformat_offset);
     case TGT_STRING:
-        return write_string_tfs(file, attrs, type, context, name, typeformat_offset);
+        return write_string_tfs(file, attrs, decltype, context, name, typeformat_offset);
     case TGT_ARRAY:
     {
         unsigned int off;
         /* conformant and pointer arrays are handled specially */
         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, decltype, 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);
@@ -3618,72 +3647,73 @@ 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;
         }
         return off;
     }
     case TGT_STRUCT:
-        return write_struct_tfs(file, type, name, typeformat_offset);
+        return write_struct_tfs(file, decltype, name, typeformat_offset);
     case TGT_UNION:
-        return write_union_tfs(file, attrs, type, typeformat_offset);
+        return write_union_tfs(file, attrs, decltype, typeformat_offset);
     case TGT_ENUM:
     case TGT_BASIC:
         /* nothing to do */
         return 0;
     case TGT_RANGE:
     {
         expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE);
         if (!range_list)
             range_list = get_aliaschain_attrp(type, ATTR_RANGE);
         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, decltype, typeformat_offset);
     case TGT_POINTER:
     {
         enum type_context ref_context;
-        type_t *ref = type_pointer_get_ref(type);
+        decl_type_t *ref = type_pointer_get_ref(type);
+        type_t *reftype = ref->type;
 
         if (context == TYPE_CONTEXT_TOPLEVELPARAM)
             ref_context = TYPE_CONTEXT_PARAM;
         else if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
             ref_context = TYPE_CONTEXT_CONTAINER;
         else
             ref_context = context;
 
-        if (is_string_type(attrs, ref))
+        if (is_string_type(attrs, reftype))
         {
             if (context != TYPE_CONTEXT_CONTAINER_NO_POINTERS)
-                write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset);
+                write_pointer_tfs(file, attrs, decltype, *typeformat_offset + 4, context, typeformat_offset);
 
             offset = write_type_tfs(file, indent, 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,
                                  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, decltype, offset, context, typeformat_offset);
     }
     case TGT_INVALID:
         break;
     }
     error("invalid type %s for var %s\n", type->name, name);
     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, decl_type_t *decltype,
                                 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, 2, attrs, decltype, 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)
 {
     const statement_list_t *stmts = type_iface_get_stmts(iface);
     const statement_t *stmt;
     var_t *var;
 
@@ -3691,44 +3721,44 @@ static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned in
     if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry )
     {
         switch(stmt->type)
         {
         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->decltype.stgclass != STG_NONE
+               || type_get_type_detect_alias(stmt->u.var->decltype.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, var->attrs, var->type, func->name,
+            var = type_function_get_retval(func->decltype.type);
+            if (!is_void(var->decltype.type))
+                var->typestring_offset = write_type_tfs( file, 2, var->attrs, &var->decltype, 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_get_function_args(func->decltype.type))
+                LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->decltype.type), var_t, entry )
+                    var->typestring_offset = write_type_tfs( file, 2, var->attrs, &var->decltype, var->name,
                                                              TYPE_CONTEXT_TOPLEVELPARAM, offset );
             break;
 
         }
         case STMT_TYPEDEF:
         {
-            const type_list_t *type_entry;
-            for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next)
+            const typedef_list_t *typedef_entry;
+            for (typedef_entry = stmt->u.typedef_list; typedef_entry; typedef_entry = typedef_entry->next)
             {
-                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,
+                if (is_attr(typedef_entry->var->decltype.type->attrs, ATTR_ENCODE)
+                    || is_attr(typedef_entry->var->decltype.type->attrs, ATTR_DECODE))
+                    typedef_entry->var->decltype.type->typestring_offset = write_type_tfs( file, 2,
+                            typedef_entry->var->decltype.type->attrs, &typedef_entry->var->decltype, typedef_entry->var->decltype.type->name,
                             TYPE_CONTEXT_CONTAINER, offset);
             }
             break;
         }
         default:
             break;
         }
     }
@@ -3840,17 +3870,17 @@ static unsigned int get_required_buffer_size_type(
             if (!type_struct_get_fields(type)) return 0;
             return fields_memsize(type_struct_get_fields(type), alignment);
         }
         break;
 
     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)
             {
                 size += 4 + align;
                 align = 4;
             }
             *alignment = align;
@@ -3860,17 +3890,17 @@ static unsigned int get_required_buffer_size_type(
     case TGT_ARRAY:
         if (get_pointer_fc(type, attrs, toplevel_param) == FC_RP)
         {
             switch (get_array_fc(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);
             }
         }
         break;
 
     default:
         break;
     }
@@ -3891,41 +3921,41 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali
         pass == PASS_RETURN)
     {
         if (is_ptrchain_attr(var, ATTR_CONTEXTHANDLE))
         {
             *alignment = 4;
             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->decltype.type))
+            return get_required_buffer_size_type(var->decltype.type, var->name,
                                                  var->attrs, TRUE, alignment);
     }
     return 0;
 }
 
 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_get_function_args(func->decltype.type))
     {
-        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->decltype.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->decltype.type)))
     {
         var_t v = *func;
-        v.type = type_function_get_rettype(func->type);
+        v.decltype.type = type_function_get_rettype(func->decltype.type);
         total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN);
         total_size += alignment;
     }
     return total_size;
 }
 
 static void print_phase_function(FILE *file, int indent, const char *type,
                                  const char *local_var_prefix, enum remoting_phase phase,
@@ -3951,32 +3981,33 @@ static void print_phase_function(FILE *file, int indent, const char *type,
         return;
     }
 
     print_file(file, indent, "Ndr%s%s(\n", type, function);
     indent++;
     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->decltype.type)) ? "&" : "",
                local_var_prefix,
-               (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
+               (phase == PHASE_UNMARSHAL && decl_indirect(var->decltype.type)) ? "_p_" : "",
                var->name);
     print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
                type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
     if (phase == PHASE_UNMARSHAL)
         print_file(file, indent, "0);\n");
     indent--;
 }
 
 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;
+    decl_type_t *decltype = (decl_type_t*)&var->decltype;
+    type_t *type = decltype->type;
     unsigned int alignment = 0;
 
     /* no work to do for other phases, buffer sizing is done elsewhere */
     if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
         return;
 
     if (type_get_type(type) == TYPE_ENUM ||
         (type_get_type(type) == TYPE_BASIC &&
@@ -3997,18 +4028,19 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
         print_file(file, indent+1, "&__frame->_StubMsg,\n");
         print_file(file, indent+1, "(unsigned char *)&%s%s,\n",
                    local_var_prefix,
                    var->name);
         print_file(file, indent+1, "0x%02x /* %s */);\n", fc, string_of_type(fc));
     }
     else
     {
-        const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type;
-        switch (get_basic_fc(ref))
+        const decl_type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : decltype;
+        const type_t *reftype = ref->type;
+        switch (get_basic_fc(reftype))
         {
         case FC_BYTE:
         case FC_CHAR:
         case FC_SMALL:
         case FC_USMALL:
             alignment = 1;
             break;
 
@@ -4035,72 +4067,72 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
 
         case FC_IGNORE:
         case FC_BIND_PRIMITIVE:
             /* no marshalling needed */
             return;
 
         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(reftype));
         }
 
         if (phase == PHASE_MARSHAL && alignment > 1)
             print_file(file, indent, "MIDL_memset(__frame->_StubMsg.Buffer, 0, (0x%x - (ULONG_PTR)__frame->_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1);
         print_file(file, indent, "__frame->_StubMsg.Buffer = (unsigned char *)(((ULONG_PTR)__frame->_StubMsg.Buffer + %u) & ~0x%x);\n",
                     alignment - 1, alignment - 1);
 
         if (phase == PHASE_MARSHAL)
         {
             print_file(file, indent, "*(");
-            write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
+            write_decltype_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : decltype, NULL);
             if (is_ptr(type))
                 fprintf(file, " *)__frame->_StubMsg.Buffer = *");
             else
                 fprintf(file, " *)__frame->_StubMsg.Buffer = ");
             fprintf(file, "%s%s", local_var_prefix, varname);
             fprintf(file, ";\n");
         }
         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_decltype_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : decltype, NULL);
             fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n");
             print_file(file, indent, "{\n");
             print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
             print_file(file, indent, "}\n");
             print_file(file, indent, "%s%s%s",
                        (pass == PASS_IN || pass == PASS_RETURN) ? "" : "*",
                        local_var_prefix, varname);
             if (pass == PASS_IN && is_ptr(type))
                 fprintf(file, " = (");
             else
                 fprintf(file, " = *(");
-            write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
+            write_decltype_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : decltype, 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_decltype_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : decltype, NULL);
         fprintf(file, ");\n");
     }
 }
 
 /* returns whether the MaxCount, Offset or ActualCount members need to be
  * filled in for the specified phase */
 static inline int is_conformance_needed_for_phase(enum remoting_phase phase)
 {
     return (phase != PHASE_UNMARSHAL);
 }
 
 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)
         {
             if (!x)
                 x = type_array_get_conformance(t);
             else
                 error("%s: multidimensional conformant"
                       " arrays not supported at the top level\n",
@@ -4108,17 +4140,17 @@ expr_t *get_size_is_expr(const type_t *t, const char *name)
         }
 
     return x;
 }
 
 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->decltype.type;
     /* get fundamental type for the argument */
     for (;;)
     {
         switch (typegen_detect_type(type, var->attrs, TDT_IGNORE_STRINGS|TDT_IGNORE_RANGES))
         {
         case TGT_ARRAY:
             if (is_conformance_needed_for_phase(phase))
             {
@@ -4160,17 +4192,17 @@ void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local
             {
                 print_file( file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR) " );
                 write_expr( file, iid, 1, 1, NULL, NULL, local_var_prefix );
                 fprintf( file, ";\n\n" );
             }
             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:
         case TGT_CTXT_HANDLE:
         case TGT_CTXT_HANDLE_POINTER:
         case TGT_STRING:
         case TGT_BASIC:
         case TGT_ENUM:
@@ -4182,17 +4214,17 @@ void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local
     }
 }
 
 static void write_remoting_arg(FILE *file, int indent, const var_t *func, const char *local_var_prefix,
                                enum pass pass, enum remoting_phase phase, const var_t *var)
 {
     int in_attr, out_attr, pointer_type;
     const char *type_str = NULL;
-    const type_t *type = var->type;
+    const type_t *type = var->decltype.type;
     unsigned int alignment, start_offset = type->typestring_offset;
 
     if (is_ptr(type) || is_array(type))
         pointer_type = get_pointer_fc(type, var->attrs, pass != PASS_RETURN);
     else
         pointer_type = 0;
 
     in_attr = is_attr(var->attrs, ATTR_IN);
@@ -4235,17 +4267,17 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
                            var->name);
                 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
             }
             else
             {
                 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->decltype.type));
                 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
             }
         }
         else if (phase == PHASE_UNMARSHAL)
         {
             if (pass == PASS_OUT || pass == PASS_RETURN)
             {
                 if (!in_attr)
@@ -4379,19 +4411,19 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
             const expr_t *range_max;
             expr_list_t *range_list = get_attrp(var->attrs, ATTR_RANGE);
             if (!range_list)
                 range_list = get_aliaschain_attrp(type, ATTR_RANGE);
             range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
             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_decltype_decl(file, (decl_type_t*)&var->decltype, NULL);
             fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name);
-            write_type_decl(file, var->type, NULL);
+            write_decltype_decl(file, (decl_type_t*)&var->decltype, 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");
             print_file(file, indent, "}\n");
         }
         break;
     case TGT_STRUCT:
         switch (get_struct_fc(type))
@@ -4427,17 +4459,17 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
             union_type = "EncapsulatedUnion";
 
         print_phase_function(file, indent, union_type, local_var_prefix,
                              phase, var, start_offset);
         break;
     }
     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:
             print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
             break;
         case TGT_ENUM:
             /* base types have known sizes, so don't need a sizing pass
              * and don't have any memory to free and so don't need a
@@ -4548,24 +4580,24 @@ void write_remoting_arguments(FILE *file, int indent, const var_t *func, const c
     {
         unsigned int size = get_function_buffer_size( func, pass );
         print_file(file, indent, "__frame->_StubMsg.BufferLength = %u;\n", size);
     }
 
     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->decltype.type) );
     }
     else
     {
         const var_t *var;
-        if (!type_get_function_args(func->type))
+        if (!type_get_function_args(func->decltype.type))
             return;
-        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->decltype.type), const var_t, entry )
             write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var );
     }
 }
 
 
 unsigned int get_size_procformatstring_func(const type_t *iface, const var_t *func)
 {
     unsigned int offset = 0;
@@ -4596,167 +4628,167 @@ unsigned int get_size_typeformatstring(const statement_list_t *stmts, type_pred_
     set_all_tfswrite(FALSE);
     return process_tfs(NULL, stmts, pred);
 }
 
 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->decltype.type);
 
     /* declare return value */
-    if (!is_void(var->type))
+    if (!is_void(var->decltype.type))
     {
-        if (is_context_handle(var->type))
+        if (is_context_handle(var->decltype.type))
             print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
         else
         {
             print_file(file, indent, "%s", "");
-            write_type_decl(file, var->type, var->name);
+            write_decltype_decl(file, (decl_type_t*)&var->decltype, var->name);
             fprintf(file, ";\n");
         }
     }
 
-    if (!type_get_function_args(func->type))
+    if (!type_get_function_args(func->decltype.type))
         return;
 
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->decltype.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->decltype.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->decltype.type))
             {
-                type_t *type_to_print;
+                decl_type_t *decltype_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->decltype.type) == TYPE_ARRAY &&
+                    !type_array_is_decl_as_ptr(var->decltype.type))
+                    decltype_to_print = (decl_type_t*)&var->decltype;
                 else
-                    type_to_print = type_pointer_get_ref(var->type);
+                    decltype_to_print = type_pointer_get_ref(var->decltype.type);
                 sprintf(name, "_W%u", i++);
-                write_type_decl(file, type_to_print, name);
+                write_decltype_decl(file, decltype_to_print, name);
                 fprintf(file, ";\n");
             }
 
             print_file(file, indent, "%s", "");
-            write_type_decl_left(file, var->type);
+            write_decltype_decl_left(file, (decl_type_t*)&var->decltype);
             fprintf(file, " ");
-            if (type_get_type(var->type) == TYPE_ARRAY &&
-                !type_array_is_decl_as_ptr(var->type)) {
+            if (type_get_type(var->decltype.type) == TYPE_ARRAY &&
+                !type_array_is_decl_as_ptr(var->decltype.type)) {
                 fprintf(file, "(*%s)", var->name);
             } else
                 fprintf(file, "%s", var->name);
-            write_type_right(file, var->type, FALSE);
+            write_type_right(file, var->decltype.type, FALSE);
             fprintf(file, ";\n");
 
-            if (decl_indirect(var->type))
+            if (decl_indirect(var->decltype.type))
                 print_file(file, indent, "void *_p_%s;\n", var->name);
         }
     }
 }
 
 
 void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char *local_var_prefix )
 {
     int in_attr, out_attr;
     int i = 0, sep = 0;
     const var_t *var;
-    type_t *ref;
+    type_t *reftype;
 
-    if (!type_get_function_args(func->type))
+    if (!type_get_function_args(func->decltype.type))
         return;
 
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->decltype.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 (!in_attr)
         {
             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->decltype.type, var->attrs, TDT_IGNORE_STRINGS))
             {
             case TGT_CTXT_HANDLE_POINTER:
                 fprintf(file, " = NdrContextHandleInitialize(\n");
                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
                 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
                            var->typestring_offset);
                 break;
             case TGT_ARRAY:
-                if (type_array_has_conformance(var->type))
+                if (type_array_has_conformance(var->decltype.type))
                 {
                     unsigned int size;
                     type_t *type;
 
                     fprintf(file, " = NdrAllocate(&__frame->_StubMsg, ");
-                    for (type = var->type;
+                    for (type = var->decltype.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);
                         fprintf(file, " * ");
                     }
                     size = type_memsize(type);
                     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->decltype.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);
                         fprintf(file, " * ");
                     }
                     size = type_memsize(type);
                     fprintf(file, "%u);\n", size);
                 }
                 else
                     fprintf(file, " = &%s_W%u;\n", local_var_prefix, i++);
                 break;
             case TGT_POINTER:
                 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i);
-                ref = type_pointer_get_ref(var->type);
-                switch (typegen_detect_type(ref, var->attrs, TDT_IGNORE_STRINGS))
+                reftype = type_pointer_get_ref_type(var->decltype.type);
+                switch (typegen_detect_type(reftype, var->attrs, TDT_IGNORE_STRINGS))
                 {
                 case TGT_BASIC:
                 case TGT_ENUM:
                 case TGT_POINTER:
                 case TGT_RANGE:
                 case TGT_IFACE_POINTER:
                     print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i);
                     break;
                 case TGT_USER_TYPE:
                     print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n",
                                local_var_prefix, i, local_var_prefix, i);
                     break;
                 case TGT_ARRAY:
-                    if (type_array_is_decl_as_ptr(ref))
+                    if (type_array_is_decl_as_ptr(reftype))
                     {
                         print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i);
                         break;
                     }
-                    ref = type_array_get_element(ref);
+                    reftype = type_array_get_element_type(reftype);
                     /* fall through */
                 case TGT_STRUCT:
                 case TGT_UNION:
-                    if (type_has_pointers(ref))
+                    if (type_has_pointers(reftype))
                         print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n",
                                    local_var_prefix, i, local_var_prefix, i);
                     break;
                 case TGT_CTXT_HANDLE:
                 case TGT_CTXT_HANDLE_POINTER:
                 case TGT_INVALID:
                 case TGT_STRING:
                     /* not initialised */
@@ -4782,60 +4814,60 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun
     var_t *retval = type_function_get_retval( func );
     const var_list_t *args = type_get_function_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->decltype.type )) type_memsize_and_alignment( arg->decltype.type, &align );
 
     needs_packing = (align > pointer_size);
 
     if (needs_packing) print_file( file, 0, "#include <pshpack%u.h>\n", pointer_size );
     print_file(file, 1, "struct _PARAM_STRUCT\n" );
     print_file(file, 1, "{\n" );
     if (is_object( iface )) print_file(file, 2, "%s *This;\n", iface->name );
 
     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_decltype_left( file, (decl_type_t *)&arg->decltype, NAME_DEFAULT, TRUE );
+        if (needs_space_after( arg->decltype.type )) fputc( ' ', file );
+        if (is_array( arg->decltype.type ) && !type_array_is_decl_as_ptr( arg->decltype.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->decltype.type ) || is_ptr( arg->decltype.type )) align = pointer_size;
+        else type_memsize_and_alignment( arg->decltype.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->decltype.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_decltype_decl( file, (decl_type_t*)&retval->decltype, retval->name );
+        if (is_array( retval->decltype.type ) || is_ptr( retval->decltype.type ) ||
+            type_memsize( retval->decltype.type ) == pointer_size)
             fprintf( file, ";\n" );
         else
             fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size );
     }
     print_file(file, 1, "} %s;\n", var_decl );
     if (needs_packing) print_file( file, 0, "#include <poppack.h>\n" );
     print_file( file, 0, "\n" );
 }
 
 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_get_function_args( func->decltype.type );
     const var_t *var;
 
     if (!args) return;
 
     LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
         if (cant_be_null( var ))
             print_file( file, indent, "if (!%s) RpcRaiseException(RPC_X_NULL_REF_POINTER);\n", var->name );
 }
@@ -4858,20 +4890,21 @@ int write_expr_eval_routines(FILE *file, const char *iface)
         print_file(file, 0, "{\n");
         if (type_get_type( eval->cont_type ) == TYPE_FUNCTION)
         {
             write_func_param_struct( file, eval->iface, eval->cont_type,
                                      "*pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop", FALSE );
         }
         else
         {
+            decl_type_t decltype;
             print_file(file, 1, "%s", "");
-            write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE);
+            write_decltype_left(file, init_decltype(&decltype, (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_decltype_left(file, init_decltype(&decltype, (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 */
         print_file(file, 1, "pStubMsg->MaxCount = (ULONG_PTR)");
         write_expr(file, eval->expr, 1, 1, var_name_expr, eval->cont_type, "");
         fprintf(file, ";\n");
         print_file(file, 0, "}\n\n");
         callback_offset++;
@@ -4955,30 +4988,31 @@ void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
 
 error:
     error("Invalid endpoint syntax '%s'\n", endpoint->str);
 }
 
 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 );
+    decl_type_t *retdecltype = type_function_get_retdecltype(func->decltype.type);
+    type_t *rettype = retdecltype->type;
     int has_ret = !is_void( rettype );
-    const var_list_t *args = type_get_function_args( func->type );
+    const var_list_t *args = type_get_function_args( func->decltype.type );
     const var_t *arg;
     int len, needs_params = 0;
 
     /* we need a param structure if we have more than one arg */
     if (pointer_size == 4 && args) needs_params = is_object( iface ) || list_count( args ) > 1;
 
     print_file( file, 0, "{\n");
     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->decltype.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 )
                 print_file( file, 1, "__params.%s = %s;\n", arg->name, arg->name );
     }
     else if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n\n" );
 
     len = fprintf( file, "    %s%s( ",
@@ -5005,17 +5039,17 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu
             arg = LIST_ENTRY( list_head(args), const var_t, entry );
             fprintf( file, ",\n%*s&%s", len, "", arg->name );
         }
     }
     fprintf( file, " );\n" );
     if (has_ret)
     {
         print_file( file, 1, "return (" );
-        write_type_decl_left(file, rettype);
+        write_decltype_decl_left(file, retdecltype);
         fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" );
     }
     print_file( file, 0, "}\n\n");
 }
 
 void write_exceptions( FILE *file )
 {
     fprintf( file, "#ifndef USE_COMPILER_EXCEPTIONS\n");
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index 93f8f4de19..4f6b4fc38a 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -92,19 +92,19 @@ static unsigned short builtin_vt(const type_t *t)
 #endif
   if (kwp) {
     return kwp->vt;
   }
   if (is_string_type (t->attrs, 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))
       {
       case TYPE_BASIC_CHAR: return VT_LPSTR;
       case TYPE_BASIC_WCHAR: return VT_LPWSTR;
       default: break;
       }
@@ -193,17 +193,17 @@ unsigned short get_type_vt(type_t *t)
     break;
 
   case TYPE_POINTER:
     return VT_PTR;
 
   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;
     }
     else
       return VT_CARRAY;
 
   case TYPE_INTERFACE:
     if(match(t->name, "IUnknown"))
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index b93806be98..b74448aa64 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -25,36 +25,24 @@
 #include <string.h>
 
 #include "widl.h"
 #include "utils.h"
 #include "parser.h"
 #include "typetree.h"
 #include "header.h"
 
-type_t *duptype(type_t *t, int dupname)
-{
-  type_t *d = alloc_type();
-
-  *d = *t;
-  if (dupname && t->name)
-    d->name = xstrdup(t->name);
-
-  return d;
-}
-
 type_t *make_type(enum type_type type)
 {
     type_t *t = alloc_type();
     t->name = NULL;
     t->namespace = NULL;
     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;
     t->ignore = (parse_only != 0);
     t->defined = FALSE;
     t->written = FALSE;
     t->user_types_registered = FALSE;
     t->tfswrite = FALSE;
@@ -132,27 +120,27 @@ type_t *type_new_function(var_list_t *args)
 {
     var_t *arg;
     type_t *t;
     unsigned int i = 0;
 
     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->decltype.type && type_get_type(arg->decltype.type) == TYPE_VOID)
         {
             list_remove(&arg->entry);
             free(arg);
             free(args);
             args = NULL;
         }
     }
     if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry)
     {
-        if (arg->type && type_get_type(arg->type) == TYPE_VOID)
+        if (arg->decltype.type && type_get_type(arg->decltype.type) == TYPE_VOID)
             error_loc("argument '%s' has void type\n", arg->name);
         if (!arg->name)
         {
             if (i > 26 * 26)
                 error_loc("too many unnamed arguments\n");
             else
             {
                 int unique;
@@ -177,31 +165,36 @@ type_t *type_new_function(var_list_t *args)
     t->details.function->idx = -1;
     return t;
 }
 
 type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs)
 {
     type_t *t = make_type(TYPE_POINTER);
     t->details.pointer.def_fc = pointer_default;
-    t->details.pointer.ref = ref;
+    init_decltype(&t->details.pointer.ref, ref);
     t->attrs = attrs;
     return t;
 }
 
-type_t *type_new_alias(type_t *t, const char *name)
+type_t* type_new_alias(const decl_type_t *decltype, const char *name, struct namespace *namespace)
 {
-    type_t *a = duptype(t, 0);
+    type_t *a = NULL;
+
+    assert(decltype != NULL);
+    assert(name != NULL);
+
+    a = alloc_type();
+    *a = *decltype->type;
 
     a->name = xstrdup(name);
+    a->namespace = namespace;
     a->attrs = NULL;
-    a->orig = t;
+    a->details.alias.aliasee = *decltype;
     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);
@@ -217,30 +210,33 @@ 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",
                   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,
-                       unsigned int dim, expr_t *size_is, expr_t *length_is,
-                       unsigned char ptr_default_fc)
+type_t *type_new_array(const char *name, const decl_type_t *element, int declptr,
+                           unsigned int dim, expr_t *size_is, expr_t *length_is,
+                           unsigned char ptr_default_fc)
 {
     type_t *t = make_type(TYPE_ARRAY);
     if (name) t->name = xstrdup(name);
     t->details.array.declptr = declptr;
     t->details.array.length_is = length_is;
-    if (size_is)
+    if (size_is) {
         t->details.array.size_is = size_is;
-    else
+    }
+    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;
 }
 
 type_t *type_new_basic(enum type_basic_type basic_type)
 {
     type_t *t = make_type(TYPE_BASIC);
     t->details.basic.type = basic_type;
@@ -268,24 +264,27 @@ type_t *type_new_void(void)
     static type_t *void_type = NULL;
     if (!void_type)
         void_type = make_type(TYPE_VOID);
     return void_type;
 }
 
 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);
+    type_t *t;
+
+    /* avoid creating duplicate typelib type entries */
+    if (name && (t = find_type(name, namespace, tsENUM)))
+        return 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)
+    if (defined)
     {
         t->details.enumeration = xmalloc(sizeof(*t->details.enumeration));
         t->details.enumeration->enums = enums;
         t->defined = TRUE;
     }
 
     if (name)
     {
@@ -294,72 +293,76 @@ type_t *type_new_enum(const char *name, struct namespace *namespace, int defined
         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;
+    if (name && (t = find_type(name, namespace, tsSTRUCT)))
+        return t;
 
     t = make_type(TYPE_STRUCT);
     t->name = name;
     t->namespace = namespace;
 
-    if (tag_type && tag_type->details.structure)
-        t->details.structure = tag_type->details.structure;
-    else if (defined)
+    if (defined)
     {
         t->details.structure = xmalloc(sizeof(*t->details.structure));
         t->details.structure->fields = fields;
         t->defined = TRUE;
     }
+
     if (name)
     {
         if (defined)
             reg_type(t, name, namespace, tsSTRUCT);
         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);
+    type_t *t;
+
+    /* avoid creating duplicate typelib type entries */
+    if (name && (t = find_type(name, NULL, tsUNION)))
+        return 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)
+
+    if (defined)
     {
         t->details.structure = xmalloc(sizeof(*t->details.structure));
         t->details.structure->fields = fields;
         t->defined = TRUE;
     }
+
     if (name)
     {
         if (defined)
             reg_type(t, name, NULL, tsUNION);
         else
             add_incomplete(t);
     }
     return t;
 }
 
 type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases)
 {
     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->decltype.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 );
     t->defined = TRUE;
     return t;
 }
 
 static int is_valid_bitfield_type(const type_t *type)
@@ -390,30 +393,30 @@ static int is_valid_bitfield_type(const type_t *type)
             return FALSE;
         }
         return FALSE;
     default:
         return FALSE;
     }
 }
 
-type_t *type_new_bitfield(type_t *field, const expr_t *bits)
+type_t *type_new_bitfield(const decl_type_t *field, const expr_t *bits)
 {
     type_t *t;
 
-    if (!is_valid_bitfield_type(field))
+    if (!is_valid_bitfield_type(field->type))
         error_loc("bit-field has invalid type\n");
 
     if (bits->cval < 0)
         error_loc("negative width for bit-field\n");
 
     /* FIXME: validate bits->cval <= memsize(field) * 8 */
 
     t = make_type(TYPE_BITFIELD);
-    t->details.bitfield.field = field;
+    t->details.bitfield.field = *field;
     t->details.bitfield.bits = bits;
     return t;
 }
 
 static int compute_method_indexes(type_t *iface)
 {
     int idx;
     statement_t *stmt;
@@ -425,17 +428,17 @@ static int compute_method_indexes(type_t *iface)
         idx = compute_method_indexes(type_iface_get_inherit(iface));
     else
         idx = 0;
 
     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
     {
         var_t *func = stmt->u.var;
         if (!is_callas(func->attrs))
-            func->type->details.function->idx = idx++;
+            func->decltype.type->details.function->idx = idx++;
     }
 
     return idx;
 }
 
 void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts)
 {
     iface->details.iface = xmalloc(sizeof(*iface->details.iface));
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index fc134cd575..31669d6d59 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -26,46 +26,43 @@
 
 enum name_type {
     NAME_DEFAULT,
     NAME_C
 };
 
 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_alias(const decl_type_t *decltype, const char *name, struct namespace *namespace);
 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_type_t *decltype, 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);
 type_t *type_new_int(enum type_basic_type basic_type, int sign);
 type_t *type_new_void(void);
 type_t *type_new_coclass(char *name);
 type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums);
 type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields);
 type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields);
 type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases);
-type_t *type_new_bitfield(type_t *field_type, const expr_t *bits);
+type_t *type_new_bitfield(const decl_type_t *decltype, const expr_t *bits);
 void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts);
 void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods);
 void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface);
 void type_module_define(type_t *module, statement_list_t *stmts);
 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);
-
 /* 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;
 }
 
 static inline enum type_type type_get_type(const type_t *type)
 {
     return type_get_type_detect_alias(type_get_real_type(type));
 }
@@ -100,19 +97,24 @@ static inline var_list_t *type_function_get_args(const type_t *type)
 
 static inline var_t *type_function_get_retval(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_FUNCTION);
     return type->details.function->retval;
 }
 
+static inline decl_type_t* type_function_get_retdecltype(const type_t *type)
+{
+    return &(type_function_get_retval(type)->decltype);
+}
+
 static inline type_t *type_function_get_rettype(const type_t *type)
 {
-    return type_function_get_retval(type)->type;
+    return type_function_get_retdecltype(type)->type;
 }
 
 static inline var_list_t *type_enum_get_values(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_ENUM);
     return type->details.enumeration->enums;
 }
@@ -137,17 +139,17 @@ static inline var_list_t *type_union_get_cases(const type_t *type)
 
     type = type_get_real_type(type);
     type_type = type_get_type(type);
 
     assert(type_type == TYPE_UNION || type_type == TYPE_ENCAPSULATED_UNION);
     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->decltype.type->details.structure->fields;
     }
     else
         return type->details.structure->fields;
 }
 
 static inline statement_list_t *type_iface_get_stmts(const type_t *type)
 {
     type = type_get_real_type(type);
@@ -245,21 +247,28 @@ static inline expr_t *type_array_get_conformance(const type_t *type)
 
 static inline expr_t *type_array_get_variance(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_ARRAY);
     return type->details.array.length_is;
 }
 
-static inline type_t *type_array_get_element(const type_t *type)
+static inline decl_type_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 (decl_type_t*)&type->details.array.elem;
+}
+
+static inline type_t *type_array_get_element_type(const type_t *type)
+{
+    decl_type_t *dt = type_array_get_element(type);
+    if (dt) return dt->type;
+    return NULL;
 }
 
 static inline int type_array_is_decl_as_ptr(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_ARRAY);
     return type->details.array.declptr;
 }
@@ -271,48 +280,62 @@ static inline unsigned char type_array_get_ptr_default_fc(const type_t *type)
     return type->details.array.ptr_def_fc;
 }
 
 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 decl_type_t *type_alias_get_aliasee(const type_t *type)
 {
     assert(type_is_alias(type));
-    return type->orig;
+    return (decl_type_t*)&type->details.alias.aliasee;
+}
+
+static inline type_t *type_alias_get_aliasee_type(const type_t *type)
+{
+    decl_type_t *dt = type_alias_get_aliasee(type);
+    if (dt) return dt->type;
+    return NULL;
 }
 
 static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_COCLASS);
     return type->details.coclass.ifaces;
 }
 
-static inline type_t *type_pointer_get_ref(const type_t *type)
+static inline decl_type_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 (decl_type_t*)&type->details.pointer.ref;
+}
+
+static inline type_t *type_pointer_get_ref_type(const type_t *type)
+{
+    decl_type_t *dt = type_pointer_get_ref(type);
+    if (dt) return dt->type;
+    return NULL;
 }
 
 static inline unsigned char type_pointer_get_default_fc(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_POINTER);
     return type->details.pointer.def_fc;
 }
 
-static inline type_t *type_bitfield_get_field(const type_t *type)
+static inline decl_type_t *type_bitfield_get_field(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_BITFIELD);
-    return type->details.bitfield.field;
+    return (decl_type_t*)&type->details.bitfield.field;
 }
 
 static inline const expr_t *type_bitfield_get_bits(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_BITFIELD);
     return type->details.bitfield.bits;
 }
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 1177c1a00a..bf88d35e7c 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -35,26 +35,27 @@ typedef GUID UUID;
 #define TRUE 1
 #define FALSE 0
 
 typedef struct _loc_info_t loc_info_t;
 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_type_t decl_type_t;
 typedef struct _declarator_t declarator_t;
 typedef struct _ifref_t ifref_t;
 typedef struct _typelib_entry_t typelib_entry_t;
 typedef struct _importlib_t importlib_t;
 typedef struct _importinfo_t importinfo_t;
 typedef struct _typelib_t typelib_t;
 typedef struct _user_type_t user_type_t;
 typedef struct _user_type_t context_handle_t;
 typedef struct _user_type_t generic_handle_t;
-typedef struct _type_list_t type_list_t;
+typedef struct _typedef_list_t typedef_list_t;
 typedef struct _statement_t statement_t;
 typedef struct _warning_t warning_t;
 
 typedef struct list attr_list_t;
 typedef struct list str_list_t;
 typedef struct list expr_list_t;
 typedef struct list var_list_t;
 typedef struct list declarator_list_t;
@@ -229,16 +230,28 @@ enum type_kind
 enum storage_class
 {
     STG_NONE,
     STG_STATIC,
     STG_EXTERN,
     STG_REGISTER,
 };
 
+enum type_qualifier
+{
+    TYPE_QUALIFIER_NONE,
+    TYPE_QUALIFIER_CONST
+};
+
+enum function_specifier
+{
+    FUNCTION_SPECIFIER_NONE,
+    FUNCTION_SPECIFIER_INLINE,
+};
+
 enum statement_type
 {
     STMT_LIBRARY,
     STMT_DECLARATION,
     STMT_TYPE,
     STMT_TYPEREF,
     STMT_MODULE,
     STMT_TYPEDEF,
@@ -288,21 +301,30 @@ struct _loc_info_t
 };
 
 struct str_list_entry_t
 {
     char *str;
     struct list entry;
 };
 
+struct _decl_type_t
+{
+  struct _type_t *type;
+  enum storage_class stgclass;
+  enum type_qualifier typequalifier;
+  enum function_specifier funcspecifier;
+};
+
 struct _attr_t {
   enum attr_type type;
   union {
     unsigned int ival;
     void *pval;
+    struct _decl_type_t dtval;
   } u;
   /* parser-internal */
   struct list entry;
 };
 
 struct _expr_t {
   enum expr_type type;
   const expr_t *ref;
@@ -351,17 +373,17 @@ struct module_details
 {
   statement_list_t *stmts;
 };
 
 struct array_details
 {
   expr_t *size_is;
   expr_t *length_is;
-  struct _type_t *elem;
+  struct _decl_type_t elem;
   unsigned int dim;
   unsigned char ptr_def_fc;
   unsigned char declptr; /* if declared as a pointer */
   unsigned short ptr_tfsoff;  /* offset of pointer definition for declptr */
 };
 
 struct coclass_details
 {
@@ -371,26 +393,31 @@ struct coclass_details
 struct basic_details
 {
   enum type_basic_type type;
   int sign;
 };
 
 struct pointer_details
 {
-  struct _type_t *ref;
+  struct _decl_type_t ref;
   unsigned char def_fc;
 };
 
 struct bitfield_details
 {
-  struct _type_t *field;
+  struct _decl_type_t field;
   const expr_t *bits;
 };
 
+struct typedef_details
+{
+  struct _decl_type_t aliasee;
+};
+
 #define HASHMAX 64
 
 struct namespace {
     const char *name;
     struct namespace *parent;
     struct list entry;
     struct list children;
     struct rtype *type_hash[HASHMAX];
@@ -426,38 +453,38 @@ struct _type_t {
     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 typedef_details alias;
   } 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;
   loc_info_t loc_info;
   unsigned int ignore : 1;
   unsigned int defined : 1;
   unsigned int written : 1;
   unsigned int user_types_registered : 1;
   unsigned int tfswrite : 1;   /* if the type needs to be written to the TFS */
   unsigned int checked : 1;
   unsigned int is_alias : 1; /* is the type an alias? */
 };
 
+
 struct _var_t {
   char *name;
-  type_t *type;
+  decl_type_t decltype;
   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;
 
   /* parser-internal */
   struct list entry;
 };
@@ -518,32 +545,37 @@ struct _typelib_t {
     statement_list_t *stmts;
 };
 
 struct _user_type_t {
     struct list entry;
     const char *name;
 };
 
+struct _typedef_list_t {
+  var_t *var;
+  struct _typedef_list_t *next;
+};
+
 struct _type_list_t {
     type_t *type;
     struct _type_list_t *next;
 };
 
 struct _statement_t {
     struct list entry;
     enum statement_type type;
     union
     {
         ifref_t iface;
         type_t *type;
         const char *str;
         var_t *var;
         typelib_t *lib;
-        type_list_t *type_list;
+        typedef_list_t *typedef_list;
     } u;
 };
 
 struct _warning_t {
     int num;
     struct list entry;
 };
 
@@ -591,18 +623,18 @@ 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)
+    if (stmt->type == STMT_DECLARATION && stmt->u.var->decltype.stgclass == STG_NONE && \
+        type_get_type_detect_alias(stmt->u.var->decltype.type) == TYPE_FUNCTION)
 
 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;
@@ -611,9 +643,18 @@ static inline int statements_has_func(const statement_list_t *stmts)
   return has_func;
 }
 
 static inline int is_global_namespace(const struct namespace *namespace)
 {
     return !namespace->name;
 }
 
+static inline decl_type_t* init_decltype(decl_type_t *decltype, type_t *type)
+{
+    decltype->type = type;
+    decltype->stgclass=STG_NONE;
+    decltype->typequalifier=TYPE_QUALIFIER_NONE;
+    decltype->funcspecifier=FUNCTION_SPECIFIER_NONE;
+    return decltype;
+}
+
 #endif
diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c
index 4dcbc03702..24d5c9a368 100644
--- a/tools/widl/write_msft.c
+++ b/tools/widl/write_msft.c
@@ -857,26 +857,26 @@ static int encode_type(
     case VT_LPSTR:
     case VT_LPWSTR:
         *encoded_type = 0xfffe0000 | vt;
         break;
 
     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;
         }
         /* if no type found then it must be void */
         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 */
         if(next_vt == VT_DISPATCH || next_vt == VT_UNKNOWN) {
             chat("encode_type: skipping ptr\n");
             *encoded_type = target_type;
             *decoded_size = child_size;
             break;
@@ -907,20 +907,20 @@ static int encode_type(
 	*encoded_type = typeoffset;
 
 	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
         break;
     }
 
     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) {
 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
 	    if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
 	}
 
 	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
@@ -963,17 +963,17 @@ static int encode_type(
                 type->name, importinfo->importlib->name);
             alloc_importinfo(typelib, importinfo);
             typeinfo_offset = importinfo->offset | 0x1;
         }
         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);
+                type = type_alias_get_aliasee_type(type);
 
             chat("encode_type: VT_USERDEFINED - adding new type %s, real type %d\n",
                  type->name, type_get_type(type));
 
             switch (type_get_type(type))
             {
             case TYPE_STRUCT:
                 add_structure_typeinfo(typelib, type);
@@ -1051,32 +1051,32 @@ static int encode_var(
     if (is_array(type) && !type_array_is_decl_as_ptr(type)) {
         int num_dims, elements = 1, arrayoffset;
         type_t *atype;
         int *arraydata;
 
         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);
         encode_var(typelib, atype, var, &target_type, NULL);
         arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(int), 0);
         arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
 
         arraydata[0] = target_type;
         arraydata[1] = num_dims;
         arraydata[1] |= ((num_dims * 2 * sizeof(int)) << 16);
 
         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;
             arraydata += 2;
             elements *= type_array_get_dim(atype);
         }
 
         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
@@ -1088,17 +1088,17 @@ static int encode_var(
         *encoded_type = typeoffset;
         *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
         return 0;
     }
 
     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) {
             chat("encode_var: skipping ptr\n");
             *encoded_type = target_type;
             *decoded_size = child_size;
             return 0;
         }
@@ -1109,17 +1109,17 @@ static int encode_var(
 	}
 
 	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
 	    int mix_field;
 
 	    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];
 		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
 	    }
 
 	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
@@ -1199,17 +1199,17 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e
         chat("default value '%s'\n", expr->u.sval);
         write_string_value(typelib, out, expr->u.sval);
         return;
     }
 
     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)
             warning("non-null pointer default value\n");
     } else {
         vt = get_type_vt(type);
         switch(vt) {
         case VT_I2:
@@ -1296,18 +1296,18 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
         break;
     }
 
     if (is_local( func->attrs )) {
         chat("add_func_desc: skipping local function\n");
         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_get_function_args(func->decltype.type))
+      LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->decltype.type), var_t, entry )
       {
         num_params++;
         if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
             if(attr->type == ATTR_DEFAULTVALUE)
                 num_defaults++;
             else if(attr->type == ATTR_OPTIONAL)
                 num_optional++;
         }
@@ -1439,17 +1439,17 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
             typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] &= 0xffff;
             typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] |= (index << 16);
             break;
         }
     }
 
     /* 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->decltype.type), func,
         &typedata[1], &decoded_size);
     typedata[2] = funcflags;
     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
     typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind;
     if(num_defaults) typedata[4] |= 0x1000;
     if(entry_is_ord) typedata[4] |= 0x2000;
     typedata[5] = (num_optional << 16) | num_params;
 
@@ -1466,34 +1466,34 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
     case 2: typedata[7] = help_string_offset;
     case 1: typedata[6] = help_context;
     case 0:
         break;
     default:
         warning("unknown number of optional attrs\n");
     }
 
-    if (type_get_function_args(func->type))
+    if (type_get_function_args(func->decltype.type))
     {
       i = 0;
-      LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
+      LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->decltype.type), var_t, entry )
       {
         int paramflags = 0;
         int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
         int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL;
 
         if(defaultdata) *defaultdata = -1;
 
-	encode_var(typeinfo->typelib, arg->type, arg, paramdata, &decoded_size);
+	encode_var(typeinfo->typelib, arg->decltype.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->decltype.type, (expr_t *)attr->u.pval, defaultdata);
                 break;
               }
             case ATTR_IN:
                 paramflags |= 0x01; /* PARAMFLAG_FIN */
                 break;
             case ATTR_OPTIONAL:
                 paramflags |= 0x10; /* PARAMFLAG_FOPT */
                 break;
@@ -1567,20 +1567,20 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
         if(typeinfo->typekind == TKIND_MODULE)
             namedata[9] |= 0x10;
     } else
         namedata[9] &= ~0x10;
 
     if(typeinfo->typekind == TKIND_MODULE)
         namedata[9] |= 0x20;
 
-    if (type_get_function_args(func->type))
+    if (type_get_function_args(func->decltype.type))
     {
         i = 0;
-        LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
+        LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->decltype.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 */))
             {
                 int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
                 offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
                 paramdata[1] = offset;
             }
@@ -1692,18 +1692,18 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
         typeinfo->var_offsets = xrealloc(typeinfo->var_offsets, typeinfo->vars_allocated * sizeof(int));
     }
     /* update the index data */
     typeinfo->var_indices[var_num] = id;
     typeinfo->var_names[var_num] = -1;
     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->decltype.type, &var_alignment);
+    encode_var(typeinfo->typelib, var->decltype.type, var, &typedata[1], &var_type_size);
 
     /* pad out starting position to data width */
     typeinfo->datawidth += var_alignment - 1;
     typeinfo->datawidth &= ~(var_alignment - 1);
 
     switch(typeinfo->typekind) {
     case TKIND_ENUM:
         write_int_value(typeinfo->typelib, &typedata[4], VT_I4, var->eval->cval);
@@ -2176,17 +2176,17 @@ static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef)
     msft_typeinfo_t *msft_typeinfo = NULL;
     int datatype1, datatype2, duplicate = 0;
     unsigned int size, alignment = 0;
     type_t *type;
 
     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)
     {
         tdef->typelib_idx = typelib->typelib_header.nrtypeinfos;
         msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs);
     }
     else
         duplicate = 1;
@@ -2352,24 +2352,24 @@ static void add_entry(msft_typelib_t *typelib, const statement_t *stmt)
     case STMT_DECLARATION:
         /* not included in typelib */
         break;
     case STMT_IMPORTLIB:
         /* not processed here */
         break;
     case STMT_TYPEDEF:
     {
-        const type_list_t *type_entry = stmt->u.type_list;
-        for (; type_entry; type_entry = type_entry->next) {
+        const typedef_list_t *typedef_entry = stmt->u.typedef_list;
+        for (; typedef_entry; typedef_entry = typedef_entry->next) {
             /* if the type is public then add the typedef, otherwise attempt
              * to add the aliased type */
-            if (is_attr(type_entry->type->attrs, ATTR_PUBLIC))
-                add_typedef_typeinfo(typelib, type_entry->type);
+            if (is_attr(typedef_entry->var->decltype.type->attrs, ATTR_PUBLIC))
+                add_typedef_typeinfo(typelib, typedef_entry->var->decltype.type);
             else
-                add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type));
+                add_type_typeinfo(typelib, type_alias_get_aliasee_type(typedef_entry->var->decltype.type));
         }
         break;
     }
     case STMT_MODULE:
         add_module_typeinfo(typelib, stmt->u.type);
         break;
     case STMT_TYPE:
     case STMT_TYPEREF:
-- 
2.17.1




More information about the wine-devel mailing list