[PATCH 09/15] widl: now using type qualifier and func specifier enums on decl_spec_t rather than attributes on the type_t

Richard Pospesel richard at torproject.org
Fri Jul 5 16:51:38 CDT 2019


Signed-off-by: Richard Pospesel <richard at torproject.org>
---
 tools/widl/expr.c      |   6 +-
 tools/widl/header.c    |  20 ++--
 tools/widl/parser.y    | 220 +++++++++++++++++++++++++++--------------
 tools/widl/typetree.c  |   3 +-
 tools/widl/typetree.h  |   2 +-
 tools/widl/widltypes.h |  23 +++--
 6 files changed, 178 insertions(+), 96 deletions(-)

diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index 85ba4639e1..2f07581662 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 192abece1e..9e9cd5f6ff 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -309,7 +309,7 @@ void write_declspec_left(FILE* h, const decl_spec_t *ds, enum name_type name_typ
 
   name = type_get_name(t, name_type);
 
-  if (is_attr(t->attrs, ATTR_CONST) &&
+  if ((ds->typequalifier == TYPE_QUALIFIER_CONST) &&
       (type_is_alias(t) || !is_ptr(t)))
     fprintf(h, "const ");
 
@@ -360,7 +360,7 @@ void write_declspec_left(FILE* h, const decl_spec_t *ds, enum name_type name_typ
       {
         write_declspec_left(h, type_pointer_get_ref(t), name_type, declonly);
         write_pointer_left(h, type_pointer_get_ref_type(t));
-        if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const ");
+        if (ds->typequalifier == TYPE_QUALIFIER_CONST) fprintf(h, "const ");
         break;
       }
       case TYPE_ARRAY:
@@ -501,14 +501,16 @@ static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declo
   if (!h) return;
 
   if (t) {
-    for (pt = t; is_ptr(pt); pt = type_pointer_get_ref_type(pt), ptr_level++)
+    const decl_spec_t *dpt = NULL;
+    for (dpt = ds; is_ptr(dpt->type); dpt = type_pointer_get_ref(dpt->type), ptr_level++)
       ;
+    pt = dpt->type;
 
     if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
       int i;
       const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
       if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE";
-      if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
+      if (dpt->funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(h, "inline ");
       write_declspec_left(h, type_function_get_retdeclspec(pt), NAME_DEFAULT, declonly);
       fputc(' ', h);
       if (ptr_level) fputc('(', h);
@@ -809,17 +811,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 *ds;
   /* strangely, MIDL accepts a const attribute on any pointer in the
   * declaration to mean that data isn't being instantiated. this appears
   * to be a bug, but there is no benefit to being incompatible with MIDL,
   * so we'll do the same thing */
-  for (t = var->declspec.type; ; )
+  for (ds = &var->declspec; ;)
   {
-    if (is_attr(t->attrs, ATTR_CONST))
+    if (ds->typequalifier == TYPE_QUALIFIER_CONST)
       return TRUE;
-    else if (is_ptr(t))
-      t = type_pointer_get_ref_type(t);
+    else if (is_ptr(ds->type))
+      ds = type_pointer_get_ref(ds->type);
     else break;
   }
   return FALSE;
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 07261b99dc..de1dc709fc 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -60,7 +60,7 @@ static void fix_incomplete_types(type_t *complete_type);
 static str_list_t *append_str(str_list_t *list, char *str);
 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
 static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier);
 static attr_t *make_attr(enum attr_type type);
 static attr_t *make_attrv(enum attr_type type, unsigned int val);
 static attr_t *make_attrp(enum attr_type type, void *val);
@@ -76,6 +76,7 @@ static declarator_t *make_declarator(var_t *var);
 static type_t *make_safearray(type_t *type);
 static typelib_t *make_library(const char *name, const attr_list_t *attrs);
 static type_t *append_chain_type(type_t *chain, type_t *type);
+static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier);
 static warning_list_t *append_warning(warning_list_t *, int);
 
 static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs);
@@ -158,6 +159,8 @@ static typelib_t *current_typelib;
 	struct _import_t *import;
 	struct _decl_spec_t *declspec;
 	enum storage_class stgclass;
+	enum type_qualifier typequalifier;
+	enum function_specifier funcspecifier;
 }
 
 %token <str> aIDENTIFIER aPRAGMA
@@ -259,14 +262,16 @@ static typelib_t *current_typelib;
 %token tWCHAR tWIREMARSHAL
 %token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH
 
-%type <attr> attribute type_qualifier function_specifier acf_attribute
-%type <attr_list> m_attributes attributes attrib_list m_type_qual_list
+%type <attr> attribute acf_attribute
+%type <attr_list> m_attributes attributes attrib_list
 %type <attr_list> acf_attributes acf_attribute_list
 %type <str_list> str_list
 %type <expr> m_expr expr expr_const expr_int_const array m_bitfield
 %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
 %type <ifinfo> interfacehdr
 %type <stgclass> storage_cls_spec
+%type <typequalifier> type_qualifier m_type_qual_bits
+%type <funcspecifier> function_specifier
 %type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
 %type <type> inherit interface interfacedef interfacedec
 %type <type> dispinterface dispinterfacehdr dispinterfacedef
@@ -948,20 +953,20 @@ storage_cls_spec:
 	;
 
 function_specifier:
-	  tINLINE				{ $$ = make_attr(ATTR_INLINE); }
+	  tINLINE				{ $$ = FUNCTION_SPECIFIER_INLINE; }
 	;
 
 type_qualifier:
-	  tCONST				{ $$ = make_attr(ATTR_CONST); }
+	  tCONST				{ $$ = TYPE_QUALIFIER_CONST; }
 	;
 
-m_type_qual_list:				{ $$ = NULL; }
-	| m_type_qual_list type_qualifier	{ $$ = append_attr($1, $2); }
+m_type_qual_bits:			{ $$ = TYPE_QUALIFIER_NONE; }
+	| m_type_qual_bits type_qualifier	{ $$ = $1 | $2; }
 	;
 
-decl_spec: type m_decl_spec_no_type		{ $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE); }
+decl_spec: type m_decl_spec_no_type		{ $$ = make_decl_spec($1, $2, NULL, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
 	| decl_spec_no_type type m_decl_spec_no_type
-						{ $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); }
+						{ $$ = make_decl_spec($2, $1, $3, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
 	;
 
 m_decl_spec_no_type:				{ $$ = NULL; }
@@ -969,44 +974,44 @@ m_decl_spec_no_type:				{ $$ = NULL; }
 	;
 
 decl_spec_no_type:
-	  type_qualifier m_decl_spec_no_type	{ $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
-	| function_specifier m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
-	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1); }
+	  type_qualifier m_decl_spec_no_type	{ $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, $1, FUNCTION_SPECIFIER_NONE); }
+	| function_specifier m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, TYPE_QUALIFIER_NONE, $1); }
+	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, $1, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
 	;
 
 declarator:
-	  '*' m_type_qual_list declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	  '*' m_type_qual_bits declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv declarator			{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
-						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+						           else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	| direct_declarator
 	;
 
 direct_declarator:
 	  ident					{ $$ = make_declarator($1); }
 	| '(' declarator ')'			{ $$ = $2; }
-	| direct_declarator array		{ $$ = $1; $$->type = append_array($$->type, $2); }
+	| direct_declarator array		{ $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); }
 	| direct_declarator '(' m_args ')'	{ $$ = $1;
-						  $$->func_type = append_chain_type($$->type, type_new_function($3));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($3));
+						  $$->declspec.type = NULL;
 						}
 	;
 
 /* abstract declarator */
 abstract_declarator:
-	  '*' m_type_qual_list m_abstract_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	  '*' m_type_qual_bits m_abstract_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_abstract_declarator	{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
-						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+						           else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	| abstract_direct_declarator
 	;
 
 /* abstract declarator without accepting direct declarator */
 abstract_declarator_no_direct:
-	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	  '*' m_type_qual_bits m_any_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_any_declarator		{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
-						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+						           else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	;
 
 /* abstract declarator or empty */
@@ -1017,33 +1022,33 @@ m_abstract_declarator: 				{ $$ = make_declarator(NULL); }
 /* abstract direct declarator */
 abstract_direct_declarator:
 	  '(' abstract_declarator_no_direct ')'	{ $$ = $2; }
-	| abstract_direct_declarator array	{ $$ = $1; $$->type = append_array($$->type, $2); }
-	| array					{ $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); }
+	| abstract_direct_declarator array	{ $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); }
+	| array					{ $$ = make_declarator(NULL); $$->declspec.type = append_array($$->declspec.type, $1); }
 	| '(' m_args ')'
 						{ $$ = make_declarator(NULL);
-						  $$->func_type = append_chain_type($$->type, type_new_function($2));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($2));
+						  $$->declspec.type = NULL;
 						}
 	| abstract_direct_declarator '(' m_args ')'
 						{ $$ = $1;
-						  $$->func_type = append_chain_type($$->type, type_new_function($3));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($3));
+						  $$->declspec.type = NULL;
 						}
 	;
 
 /* abstract or non-abstract declarator */
 any_declarator:
-	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
-	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+	  '*' m_type_qual_bits m_any_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
+	| callconv m_any_declarator		{ $$ = $2; $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	| any_direct_declarator
 	;
 
 /* abstract or non-abstract declarator without accepting direct declarator */
 any_declarator_no_direct:
-	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
-	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+	  '*' m_type_qual_bits m_any_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
+	| callconv m_any_declarator		{ $$ = $2; $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	;
 
 /* abstract or non-abstract declarator or empty */
@@ -1057,17 +1062,17 @@ m_any_declarator: 				{ $$ = make_declarator(NULL); }
 any_direct_declarator:
 	  ident					{ $$ = make_declarator($1); }
 	| '(' any_declarator_no_direct ')'	{ $$ = $2; }
-	| any_direct_declarator array		{ $$ = $1; $$->type = append_array($$->type, $2); }
-	| array					{ $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); }
+	| any_direct_declarator array		{ $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); }
+	| array					{ $$ = make_declarator(NULL); $$->declspec.type = append_array($$->declspec.type, $1); }
 	| '(' m_args ')'
 						{ $$ = make_declarator(NULL);
-						  $$->func_type = append_chain_type($$->type, type_new_function($2));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($2));
+						  $$->declspec.type = NULL;
 						}
 	| any_direct_declarator '(' m_args ')'
 						{ $$ = $1;
-						  $$->func_type = append_chain_type($$->type, type_new_function($3));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($3));
+						  $$->declspec.type = NULL;
 						}
 	;
 
@@ -1233,6 +1238,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr)
     LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry)
         if (attr_existing->type == attr->type)
         {
+            __builtin_trap();
             parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type));
             /* use the last attribute, like MIDL does */
             list_remove(&attr_existing->entry);
@@ -1292,53 +1298,73 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter
   return new_list;
 }
 
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass)
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier)
 {
   decl_spec_t *declspec = left ? left : right;
   if (!declspec)
   {
     declspec = xmalloc(sizeof(*declspec));
     declspec->type = NULL;
-    declspec->attrs = NULL;
     declspec->stgclass = STG_NONE;
+    declspec->typequalifier = TYPE_QUALIFIER_NONE;
+    declspec->funcspecifier = FUNCTION_SPECIFIER_NONE;
   }
   declspec->type = type;
   if (left && declspec != left)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, left->attrs);
     if (declspec->stgclass == STG_NONE)
       declspec->stgclass = left->stgclass;
     else if (left->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+      declspec->typequalifier = left->typequalifier;
+    else if (left->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      declspec->funcspecifier = left->funcspecifier;
+    else if (left->funcspecifier != FUNCTION_SPECIFIER_NONE)
+      error_loc("only one function specifier can be specified\n");
+
     assert(!left->type);
     free(left);
   }
   if (right && declspec != right)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, right->attrs);
     if (declspec->stgclass == STG_NONE)
       declspec->stgclass = right->stgclass;
     else if (right->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+      declspec->typequalifier = right->typequalifier;
+    else if (right->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      declspec->funcspecifier = right->funcspecifier;
+    else if (right->funcspecifier != FUNCTION_SPECIFIER_NONE)
+      error_loc("only one function specifier can be specified\n");
+
     assert(!right->type);
     free(right);
   }
 
-  declspec->attrs = append_attr(declspec->attrs, attr);
   if (declspec->stgclass == STG_NONE)
     declspec->stgclass = stgclass;
   else if (stgclass != STG_NONE)
     error_loc("only one storage class can be specified\n");
 
-  /* apply attributes to type */
-  if (type && declspec->attrs)
-  {
-    attr_list_t *attrs;
-    declspec->type = duptype(type, 1);
-    attrs = map_attrs(type->attrs, NULL);
-    declspec->type->attrs = append_attr_list(attrs, declspec->attrs);
-    declspec->attrs = NULL;
-  }
+  if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+    declspec->typequalifier = typequalifier;
+  else if (typequalifier != TYPE_QUALIFIER_NONE)
+    error_loc("only one type qualifier can be specified\n");
+
+  if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+    declspec->funcspecifier = funcspecifier;
+  else if (funcspecifier != FUNCTION_SPECIFIER_NONE)
+    error_loc("only one function specifier can be specified\n");
 
   return declspec;
 }
@@ -1477,7 +1503,7 @@ static type_t *get_array_or_ptr_ref(type_t *type)
 
 static type_t *append_chain_type(type_t *chain, type_t *type)
 {
-    type_t *chain_type;
+    type_t *chain_type = NULL;
 
     if (!chain)
         return type;
@@ -1495,6 +1521,34 @@ static type_t *append_chain_type(type_t *chain, type_t *type)
     return chain;
 }
 
+static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier)
+{
+    type_t *chain_type = chain->type;
+    decl_spec_t *chain_declspec = NULL;
+
+    if (!chain_type)
+    {
+        chain->type = type;
+        chain->typequalifier = typequalifier;
+        return chain;
+    }
+
+    for(; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type))
+        ;
+
+    if (is_ptr(chain_type))
+        chain_declspec = &chain_type->details.pointer.ref;
+    else if (is_array(chain_type))
+        chain_declspec = &chain_type->details.array.elem;
+    else
+        assert(NULL);
+
+    chain_declspec->type = type;
+    chain_declspec->typequalifier = typequalifier;
+
+    return chain;
+}
+
 static warning_list_t *append_warning(warning_list_t *list, int num)
 {
     warning_t *entry;
@@ -1510,7 +1564,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num)
     return list;
 }
 
-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl,
+static var_t *declare_var(attr_list_t *attrs, decl_spec_t *declspec, const declarator_t *decl,
                        int top)
 {
   var_t *v = decl->var;
@@ -1519,25 +1573,41 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   expr_t *dim;
   type_t **ptype;
   type_t *func_type = decl ? decl->func_type : NULL;
-  type_t *type = decl_spec->type;
+  type_t *type = declspec->type;
 
-  if (is_attr(type->attrs, ATTR_INLINE))
-  {
+
+  if (declspec->funcspecifier == FUNCTION_SPECIFIER_INLINE) {
     if (!func_type)
       error_loc("inline attribute applied to non-function type\n");
     else
     {
-      type_t *t;
-      /* move inline attribute from return type node to function node */
-      for (t = func_type; is_ptr(t); t = type_pointer_get_ref_type(t))
-        ;
-      t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE);
+      v->declspec.funcspecifier = declspec->funcspecifier;
     }
   }
 
-  /* add type onto the end of the pointers in pident->type */
-  v->declspec.type = append_chain_type(decl ? decl->type : NULL, type);
-  v->declspec.stgclass = decl_spec->stgclass;
+  /* if the var type is a pointerish, we need to move the type qualifier to the pointee's declspec
+   * unless the pointee already has const type qualifier*/
+  if (!decl)
+  {
+    /* simplest case, no pointers to deal with here */
+    v->declspec.typequalifier = declspec->typequalifier;
+  } else if (decl->bits)
+  {
+    /* dealing with a bitfield, generate bitfield and copy over typequalifier*/
+    v->declspec.type = type_new_bitfield(declspec->type, decl->bits);
+    v->declspec.typequalifier = declspec->typequalifier;
+  }
+  else
+  {
+    /* here we're dealing with a pointerish type chain, so we need to pull
+     * the typequalifier off of the declspec and stick them in the type's attr list
+     */
+    v->declspec.type = decl->declspec.type;
+    v->declspec.typequalifier = decl->declspec.typequalifier;
+    append_chain_declspec(&v->declspec, type, declspec->typequalifier);
+  }
+
+  v->declspec.stgclass = declspec->stgclass;
   v->attrs = attrs;
 
   /* check for pointer attribute being applied to non-pointer, non-array
@@ -1680,12 +1750,17 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   {
     type_t *ft, *t;
     type_t *return_type = v->declspec.type;
+    enum type_qualifier typequalifier = v->declspec.typequalifier;
+
     v->declspec.type = func_type;
+    v->declspec.typequalifier = TYPE_QUALIFIER_NONE;
     for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref_type(ft))
       ;
     assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION);
     ft->details.function->retval = make_var(xstrdup("_RetVal"));
     ft->details.function->retval->declspec.type = return_type;
+    ft->details.function->retval->declspec.typequalifier = typequalifier;
+
     /* move calling convention attribute, if present, from pointer nodes to
      * function node */
     for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
@@ -1699,9 +1774,6 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
         error_loc("calling convention applied to non-function-pointer type\n");
   }
 
-  if (decl->bits)
-    v->declspec.type = type_new_bitfield(v->declspec.type, decl->bits);
-
   return v;
 }
 
@@ -1801,7 +1873,7 @@ static declarator_t *make_declarator(var_t *var)
 {
   declarator_t *d = xmalloc(sizeof(*d));
   d->var = var ? var : make_var(NULL);
-  d->type = NULL;
+  init_declspec(&d->declspec, NULL);
   d->func_type = NULL;
   d->bits = NULL;
   return d;
@@ -2180,7 +2252,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" },
@@ -2215,7 +2286,6 @@ struct allowed_attr allowed_attr[] =
     /* ATTR_IMMEDIATEBIND */       { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
     /* ATTR_IMPLICIT_HANDLE */     { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
     /* ATTR_IN */                  { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
-    /* ATTR_INLINE */              { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" },
     /* ATTR_INPUTSYNC */           { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
     /* ATTR_LENGTHIS */            { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" },
     /* ATTR_LIBLCID */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" },
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 282f0dbbab..f08bee0bac 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -177,12 +177,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 9434075108..a68bc981cf 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 *aliasee, 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 d637e0024c..108e537383 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,
@@ -116,7 +115,6 @@ enum attr_type
     ATTR_IMMEDIATEBIND,
     ATTR_IMPLICIT_HANDLE,
     ATTR_IN,
-    ATTR_INLINE,
     ATTR_INPUTSYNC,
     ATTR_LENGTHIS,
     ATTR_LIBLCID,
@@ -235,6 +233,18 @@ enum storage_class
     STG_REGISTER,
 };
 
+enum type_qualifier
+{
+    TYPE_QUALIFIER_NONE = 0,
+    TYPE_QUALIFIER_CONST = 1,
+};
+
+enum function_specifier
+{
+    FUNCTION_SPECIFIER_NONE,
+    FUNCTION_SPECIFIER_INLINE,
+};
+
 enum statement_type
 {
     STMT_LIBRARY,
@@ -297,8 +307,9 @@ struct str_list_entry_t
 struct _decl_spec_t
 {
   type_t *type;
-  attr_list_t *attrs;
   enum storage_class stgclass;
+  enum type_qualifier typequalifier;
+  enum function_specifier funcspecifier;
 };
 
 struct _attr_t {
@@ -478,7 +489,7 @@ struct _var_t {
 
 struct _declarator_t {
   var_t *var;
-  type_t *type;
+  decl_spec_t declspec;
   type_t *func_type;
   expr_t *bits;
 
@@ -604,9 +615,9 @@ static inline int is_global_namespace(const struct namespace *namespace)
 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->typequalifier=TYPE_QUALIFIER_NONE;
+  declspec->funcspecifier=FUNCTION_SPECIFIER_NONE;
   return declspec;
 }
 
-- 
2.17.1




More information about the wine-devel mailing list