[PATCH v2 2/4] widl: Store the "const" type qualifier inside the decl_spec_t structure.

Zebediah Figura z.figura12 at gmail.com
Sat Aug 17 20:07:06 CDT 2019


From: Richard Pospesel <richard at torproject.org>

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
Significant changes from https://source.winehq.org/patches/data/167604:
* Accept duplicate type qualifiers, as does MIDL.
* Just store a type_qualifier enum inside declarator_t, as that's the only
  relevant part of the declspec; the rest comes from the (innermost) type.
* Simplify the logic in declare_var() used to append the innermost type;
  since append_chain_type() already handles this, we can just keep using it.

 tools/widl/expr.c      |   6 +--
 tools/widl/header.c    |  15 +++---
 tools/widl/parser.y    | 111 ++++++++++++++++++++++++-----------------
 tools/widl/typetree.c  |   3 +-
 tools/widl/typetree.h  |   2 +-
 tools/widl/widltypes.h |   9 +++-
 6 files changed, 86 insertions(+), 60 deletions(-)

diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index 41afb4b40e..0b345f3f6a 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -521,11 +521,11 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
         break;
     case EXPR_STRLIT:
         result.is_temporary = TRUE;
-        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL);
+        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_CHAR, 0));
         break;
     case EXPR_WSTRLIT:
         result.is_temporary = TRUE;
-        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
+        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0));
         break;
     case EXPR_CHARCONST:
         result.is_temporary = TRUE;
@@ -575,7 +575,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
                            expr_loc->attr ? expr_loc->attr : "");
         result.is_variable = FALSE;
         result.is_temporary = TRUE;
-        result.type = type_new_pointer(FC_UP, result.type, NULL);
+        result.type = type_new_pointer(FC_UP, result.type);
         break;
     case EXPR_PPTR:
         result = resolve_expression(expr_loc, cont_type, e->ref);
diff --git a/tools/widl/header.c b/tools/widl/header.c
index dd1186845b..bd7ca7e8e6 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -318,8 +318,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
 
   name = type_get_name(t, name_type);
 
-  if (is_attr(t->attrs, ATTR_CONST) &&
-      (type_is_alias(t) || !is_ptr(t)))
+  if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (type_is_alias(t) || !is_ptr(t)))
     fprintf(h, "const ");
 
   if (type_is_alias(t)) fprintf(h, "%s", t->name);
@@ -369,7 +368,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
       {
         write_type_left(h, type_pointer_get_ref(t), name_type, declonly, FALSE);
         write_pointer_left(h, type_pointer_get_ref_type(t));
-        if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const ");
+        if (ds->qualifier & TYPE_QUALIFIER_CONST) fprintf(h, "const ");
         break;
       }
       case TYPE_ARRAY:
@@ -813,17 +812,17 @@ static void write_typedef(FILE *header, type_t *type)
 
 int is_const_decl(const var_t *var)
 {
-  const type_t *t;
+  const decl_spec_t *t;
   /* 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->declspec.type; ; )
+  for (t = &var->declspec; ; )
   {
-    if (is_attr(t->attrs, ATTR_CONST))
+    if (t->qualifier & TYPE_QUALIFIER_CONST)
       return TRUE;
-    else if (is_ptr(t))
-      t = type_pointer_get_ref_type(t);
+    else if (is_ptr(t->type))
+      t = type_pointer_get_ref(t->type);
     else break;
   }
   return FALSE;
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 9cfcd7f30f..45782bae5f 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -59,13 +59,13 @@ static void fix_incomplete_types(type_t *complete_type);
 static str_list_t *append_str(str_list_t *list, char *str);
 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
 static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right,
+        attr_t *attr, enum storage_class stgclass, enum type_qualifier qual);
 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 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_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, 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 ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface);
 static ifref_t *make_ifref(type_t *iface);
@@ -74,7 +74,8 @@ static declarator_list_t *append_declarator(declarator_list_t *list, declarator_
 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 void append_array(declarator_t *decl, expr_t *expr);
+static void append_chain_type(declarator_t *decl, type_t *type, enum type_qualifier qual);
 static void append_chain_callconv(type_t *chain, char *callconv);
 static warning_list_t *append_warning(warning_list_t *, int);
 
@@ -158,6 +159,7 @@ static typelib_t *current_typelib;
 	struct _import_t *import;
 	struct _decl_spec_t *declspec;
 	enum storage_class stgclass;
+	enum type_qualifier type_qualifier;
 }
 
 %token <str> aIDENTIFIER aPRAGMA
@@ -259,14 +261,15 @@ static typelib_t *current_typelib;
 %token tWCHAR tWIREMARSHAL
 %token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH
 
-%type <attr> attribute type_qualifier function_specifier acf_attribute
-%type <attr_list> m_attributes attributes attrib_list m_type_qual_list
+%type <attr> attribute function_specifier acf_attribute
+%type <attr_list> m_attributes attributes attrib_list
 %type <attr_list> acf_attributes acf_attribute_list
 %type <str_list> str_list
 %type <expr> m_expr expr expr_const expr_int_const array m_bitfield
 %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
 %type <ifinfo> interfacehdr
 %type <stgclass> storage_cls_spec
+%type <type_qualifier> type_qualifier m_type_qual_list
 %type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
 %type <type> inherit interface interfacedef interfacedec
 %type <type> dispinterface dispinterfacehdr dispinterfacedef
@@ -951,16 +954,16 @@ function_specifier:
 	;
 
 type_qualifier:
-	  tCONST				{ $$ = make_attr(ATTR_CONST); }
+	  tCONST				{ $$ = TYPE_QUALIFIER_CONST; }
 	;
 
-m_type_qual_list:				{ $$ = NULL; }
-	| m_type_qual_list type_qualifier	{ $$ = append_attr($1, $2); }
+m_type_qual_list:				{ $$ = 0; }
+	| m_type_qual_list type_qualifier	{ $$ = $1 | $2; }
 	;
 
-decl_spec: type m_decl_spec_no_type		{ $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE); }
+decl_spec: type m_decl_spec_no_type		{ $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE, 0); }
 	| decl_spec_no_type type m_decl_spec_no_type
-						{ $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); }
+						{ $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE, 0); }
 	;
 
 m_decl_spec_no_type:				{ $$ = NULL; }
@@ -968,14 +971,14 @@ m_decl_spec_no_type:				{ $$ = NULL; }
 	;
 
 decl_spec_no_type:
-	  type_qualifier m_decl_spec_no_type	{ $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
-	| function_specifier m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
-	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1); }
+	  type_qualifier m_decl_spec_no_type	{ $$ = make_decl_spec(NULL, $2, NULL, NULL, STG_NONE, $1); }
+	| function_specifier m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE, 0); }
+	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1, 0); }
 	;
 
 declarator:
 	  '*' m_type_qual_list declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+						{ $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv declarator			{ $$ = $2; append_chain_callconv($$->type, $1); }
 	| direct_declarator
 	;
@@ -983,14 +986,14 @@ declarator:
 direct_declarator:
 	  ident					{ $$ = make_declarator($1); }
 	| '(' declarator ')'			{ $$ = $2; }
-	| direct_declarator array		{ $$ = $1; $$->type = append_array($$->type, $2); }
-	| direct_declarator '(' m_args ')'	{ $$ = $1; $$->type = append_chain_type($$->type, type_new_function($3)); }
+	| direct_declarator array		{ $$ = $1; append_array($$, $2); }
+	| direct_declarator '(' m_args ')'	{ $$ = $1; append_chain_type($$, type_new_function($3), 0); }
 	;
 
 /* abstract declarator */
 abstract_declarator:
 	  '*' m_type_qual_list m_abstract_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+						{ $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_abstract_declarator	{ $$ = $2; append_chain_callconv($$->type, $1); }
 	| abstract_direct_declarator
 	;
@@ -998,7 +1001,7 @@ abstract_declarator:
 /* abstract declarator without accepting direct declarator */
 abstract_declarator_no_direct:
 	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+						{ $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_any_declarator		{ $$ = $2; append_chain_callconv($$->type, $1); }
 	;
 
@@ -1010,22 +1013,22 @@ m_abstract_declarator: 				{ $$ = make_declarator(NULL); }
 /* abstract direct declarator */
 abstract_direct_declarator:
 	  '(' abstract_declarator_no_direct ')'	{ $$ = $2; }
-	| abstract_direct_declarator array	{ $$ = $1; $$->type = append_array($$->type, $2); }
-	| array					{ $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); }
+	| abstract_direct_declarator array	{ $$ = $1; append_array($$, $2); }
+	| array					{ $$ = make_declarator(NULL); append_array($$, $1); }
 	| '(' m_args ')'
 						{ $$ = make_declarator(NULL);
-						  $$->type = append_chain_type($$->type, type_new_function($2));
+						  append_chain_type($$, type_new_function($2), 0);
 						}
 	| abstract_direct_declarator '(' m_args ')'
 						{ $$ = $1;
-						  $$->type = append_chain_type($$->type, type_new_function($3));
+						  append_chain_type($$, type_new_function($3), 0);
 						}
 	;
 
 /* abstract or non-abstract declarator */
 any_declarator:
 	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+						{ $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_any_declarator		{ $$ = $2; append_chain_callconv($$->type, $1); }
 	| any_direct_declarator
 	;
@@ -1033,7 +1036,7 @@ any_declarator:
 /* abstract or non-abstract declarator without accepting direct declarator */
 any_declarator_no_direct:
 	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+						{ $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_any_declarator		{ $$ = $2; append_chain_callconv($$->type, $1); }
 	;
 
@@ -1048,15 +1051,15 @@ m_any_declarator: 				{ $$ = make_declarator(NULL); }
 any_direct_declarator:
 	  ident					{ $$ = make_declarator($1); }
 	| '(' any_declarator_no_direct ')'	{ $$ = $2; }
-	| any_direct_declarator array		{ $$ = $1; $$->type = append_array($$->type, $2); }
-	| array					{ $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); }
+	| any_direct_declarator array		{ $$ = $1; append_array($$, $2); }
+	| array					{ $$ = make_declarator(NULL); append_array($$, $1); }
 	| '(' m_args ')'
 						{ $$ = make_declarator(NULL);
-						  $$->type = append_chain_type($$->type, type_new_function($2));
+						  append_chain_type($$, type_new_function($2), 0);
 						}
 	| any_direct_declarator '(' m_args ')'
 						{ $$ = $1;
-						  $$->type = append_chain_type($$->type, type_new_function($3));
+						  append_chain_type($$, type_new_function($3), 0);
 						}
 	;
 
@@ -1281,7 +1284,8 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter
   return new_list;
 }
 
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass)
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right,
+        attr_t *attr, enum storage_class stgclass, enum type_qualifier qual)
 {
   decl_spec_t *declspec = left ? left : right;
   if (!declspec)
@@ -1290,6 +1294,7 @@ static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t
     declspec->type = NULL;
     declspec->attrs = NULL;
     declspec->stgclass = STG_NONE;
+    declspec->qualifier = 0;
   }
   declspec->type = type;
   if (left && declspec != left)
@@ -1299,6 +1304,7 @@ static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t
       declspec->stgclass = left->stgclass;
     else if (left->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+    declspec->qualifier |= left->qualifier;
     assert(!left->type);
     free(left);
   }
@@ -1309,6 +1315,7 @@ static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t
       declspec->stgclass = right->stgclass;
     else if (right->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+    declspec->qualifier |= right->qualifier;
     assert(!right->type);
     free(right);
   }
@@ -1318,6 +1325,7 @@ static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t
     declspec->stgclass = stgclass;
   else if (stgclass != STG_NONE)
     error_loc("only one storage class can be specified\n");
+  declspec->qualifier |= qual;
 
   /* apply attributes to type */
   if (type && declspec->attrs)
@@ -1368,19 +1376,19 @@ static expr_list_t *append_expr(expr_list_t *list, expr_t *expr)
     return list;
 }
 
-static type_t *append_array(type_t *chain, expr_t *expr)
+static void append_array(declarator_t *decl, expr_t *expr)
 {
     type_t *array;
 
     if (!expr)
-        return chain;
+        return;
 
     /* An array is always a reference pointer unless explicitly marked otherwise
      * (regardless of what the default pointer attribute is). */
     array = type_new_array(NULL, NULL, FALSE, expr->is_const ? expr->cval : 0,
             expr->is_const ? NULL : expr, NULL, FC_RP);
 
-    return append_chain_type(chain, array);
+    append_chain_type(decl, array, 0);
 }
 
 static struct list type_pool = LIST_INIT(type_pool);
@@ -1473,27 +1481,38 @@ static type_t *get_chain_end(type_t *type)
     return type;
 }
 
-static type_t *append_chain_type(type_t *chain, type_t *type)
+static void append_chain_type(declarator_t *decl, type_t *type, enum type_qualifier qual)
 {
     type_t *chain_type;
 
-    if (!chain)
-        return type;
-    chain_type = get_chain_end(chain);
+    if (!decl->type)
+    {
+        decl->type = type;
+        decl->qualifier = qual;
+        return;
+    }
+    chain_type = get_chain_end(decl->type);
 
     if (is_ptr(chain_type))
+    {
         chain_type->details.pointer.ref.type = type;
+        chain_type->details.pointer.ref.qualifier = qual;
+    }
     else if (is_array(chain_type))
+    {
         chain_type->details.array.elem.type = type;
+        chain_type->details.array.elem.qualifier = qual;
+    }
     else if (is_func(chain_type))
+    {
         chain_type->details.function->retval->declspec.type = type;
+        chain_type->details.function->retval->declspec.qualifier = qual;
+    }
     else
         assert(0);
 
     if (!is_func(chain_type))
         type->attrs = move_attr(type->attrs, chain_type->attrs, ATTR_CALLCONV);
-
-    return chain;
 }
 
 static void append_chain_callconv(type_t *chain, char *callconv)
@@ -1521,7 +1540,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num)
     return list;
 }
 
-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl,
+static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_t *decl,
                        int top)
 {
   var_t *v = decl->var;
@@ -1540,8 +1559,10 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   }
 
   /* add type onto the end of the pointers in pident->type */
-  v->declspec.type = append_chain_type(decl ? decl->type : NULL, type);
-  v->declspec.stgclass = decl_spec->stgclass;
+  append_chain_type(decl, type, decl_spec->qualifier);
+  v->declspec = *decl_spec;
+  v->declspec.type = decl->type;
+  v->declspec.qualifier = decl->qualifier;
   v->attrs = attrs;
 
   if (is_attr(type->attrs, ATTR_CALLCONV) && !is_func(type))
@@ -1778,6 +1799,7 @@ static declarator_t *make_declarator(var_t *var)
   declarator_t *d = xmalloc(sizeof(*d));
   d->var = var ? var : make_var(NULL);
   d->type = NULL;
+  d->qualifier = 0;
   d->bits = NULL;
   return d;
 }
@@ -1912,7 +1934,7 @@ static void fix_incomplete_types(type_t *complete_type)
 
 static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs)
 {
-  const declarator_t *decl;
+  declarator_t *decl;
   type_t *type = decl_spec->type;
 
   if (is_attr(attrs, ATTR_UUID) && !is_attr(attrs, ATTR_PUBLIC))
@@ -1934,7 +1956,7 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
         type->attrs = attrs;
   }
 
-  LIST_FOR_EACH_ENTRY( decl, decls, const declarator_t, entry )
+  LIST_FOR_EACH_ENTRY( decl, decls, declarator_t, entry )
   {
 
     if (decl->var->name) {
@@ -2126,7 +2148,6 @@ struct allowed_attr allowed_attr[] =
     /* ATTR_CASE */                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" },
     /* ATTR_CODE */                { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" },
     /* ATTR_COMMSTATUS */          { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" },
-    /* ATTR_CONST */               { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" },
     /* ATTR_CONTEXTHANDLE */       { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
     /* ATTR_CONTROL */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" },
     /* ATTR_DECODE */              { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 615a758f4d..37555be478 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -176,12 +176,11 @@ type_t *type_new_function(var_list_t *args)
     return t;
 }
 
-type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs)
+type_t *type_new_pointer(unsigned char pointer_default, type_t *ref)
 {
     type_t *t = make_type(TYPE_POINTER);
     t->details.pointer.def_fc = pointer_default;
     t->details.pointer.ref.type = ref;
-    t->attrs = attrs;
     return t;
 }
 
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 6377614999..ce5e835dfd 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -30,7 +30,7 @@ enum name_type {
 };
 
 type_t *type_new_function(var_list_t *args);
-type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs);
+type_t *type_new_pointer(unsigned char pointer_default, type_t *ref);
 type_t *type_new_alias(const decl_spec_t *t, const char *name);
 type_t *type_new_module(char *name);
 type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr,
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 3f92192cee..6e88019a80 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -81,7 +81,6 @@ enum attr_type
     ATTR_CASE,
     ATTR_CODE,
     ATTR_COMMSTATUS,
-    ATTR_CONST, /* const pseudo-attribute */
     ATTR_CONTEXTHANDLE,
     ATTR_CONTROL,
     ATTR_DECODE,
@@ -235,6 +234,11 @@ enum storage_class
     STG_REGISTER,
 };
 
+enum type_qualifier
+{
+    TYPE_QUALIFIER_CONST = 1,
+};
+
 enum statement_type
 {
     STMT_LIBRARY,
@@ -299,6 +303,7 @@ struct _decl_spec_t
   type_t *type;
   attr_list_t *attrs;
   enum storage_class stgclass;
+  enum type_qualifier qualifier;
 };
 
 struct _attr_t {
@@ -478,6 +483,7 @@ struct _var_t {
 struct _declarator_t {
   var_t *var;
   type_t *type;
+  enum type_qualifier qualifier;
   expr_t *bits;
 
   /* parser-internal */
@@ -626,6 +632,7 @@ static inline decl_spec_t *init_declspec(decl_spec_t *declspec, type_t *type)
   declspec->type = type;
   declspec->attrs = NULL;
   declspec->stgclass = STG_NONE;
+  declspec->qualifier = 0;
 
   return declspec;
 }
-- 
2.22.0




More information about the wine-devel mailing list