From: Richard Pospesel Subject: [PATCH 09/15] widl: now using type qualifier and func specifier enums on decl_spec_t rather than attributes on the type_t Message-Id: <20190705215144.7474-8-richard@torproject.org> Date: Fri, 5 Jul 2019 14:51:38 -0700 In-Reply-To: <20190705215144.7474-7-richard@torproject.org> References: <20190705215003.7384-1-richard@torproject.org> <20190705215144.7474-1-richard@torproject.org> <20190705215144.7474-2-richard@torproject.org> <20190705215144.7474-3-richard@torproject.org> <20190705215144.7474-4-richard@torproject.org> <20190705215144.7474-5-richard@torproject.org> <20190705215144.7474-6-richard@torproject.org> <20190705215144.7474-7-richard@torproject.org> Signed-off-by: Richard Pospesel --- 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 aIDENTIFIER aPRAGMA @@ -259,14 +262,16 @@ static typelib_t *current_typelib; %token tWCHAR tWIREMARSHAL %token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH -%type attribute type_qualifier function_specifier acf_attribute -%type m_attributes attributes attrib_list m_type_qual_list +%type attribute acf_attribute +%type m_attributes attributes attrib_list %type acf_attributes acf_attribute_list %type str_list %type m_expr expr expr_const expr_int_const array m_bitfield %type m_exprs /* exprs expr_list */ expr_list_int_const %type interfacehdr %type storage_cls_spec +%type type_qualifier m_type_qual_bits +%type function_specifier %type decl_spec decl_spec_no_type m_decl_spec_no_type %type inherit interface interfacedef interfacedec %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