This is actually broken in MIDL, even as recent as the version shipped with the Windows 10 SDK, but it makes our code simpler, so there's no reason not to do it right.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: fix accidentally inverted condition
tools/widl/header.c | 109 ++++++++++++++++++++++------------------ tools/widl/header.h | 7 ++- tools/widl/parser.y | 111 +++++++++++++++++------------------------ tools/widl/typegen.c | 6 +-- tools/widl/typetree.c | 1 + tools/widl/widltypes.h | 1 - 6 files changed, 117 insertions(+), 118 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 5bf5d09ef1..dd1186845b 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -285,16 +285,31 @@ int needs_space_after(type_t *t) (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name))); }
+int decl_needs_parens(const type_t *t) +{ + if (type_is_alias(t)) + return FALSE; + if (is_array(t) && !type_array_is_decl_as_ptr(t)) + return TRUE; + return is_func(t); +} + 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)) + if (decl_needs_parens(ref)) fprintf(h, "("); + if (type_get_type_detect_alias(ref) == TYPE_FUNCTION) + { + const char *callconv = get_attrp(ref->attrs, ATTR_CALLCONV); + if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; + if (callconv) fprintf(h, "%s ", callconv); + } fprintf(h, "*"); }
-void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly) +void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly, int write_callconv) { type_t *t = ds->type; const char *name; @@ -352,7 +367,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i break; case TYPE_POINTER: { - write_type_left(h, type_pointer_get_ref(t), name_type, declonly); + 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 "); break; @@ -362,11 +377,28 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i fprintf(h, "%s", t->name); else { - write_type_left(h, type_array_get_element(t), name_type, declonly); + write_type_left(h, type_array_get_element(t), name_type, declonly, !type_array_is_decl_as_ptr(t)); if (type_array_is_decl_as_ptr(t)) write_pointer_left(h, type_array_get_element_type(t)); } break; + case TYPE_FUNCTION: + { + if (is_attr(t->attrs, ATTR_INLINE)) fprintf(h, "inline "); + write_type_left(h, type_function_get_ret(t), name_type, declonly, TRUE); + + /* A pointer to a function has to write the calling convention inside + * the parentheses. There's no way to handle that here, so we have to + * use an extra parameter to tell us whether to write the calling + * convention or not. */ + if (write_callconv) + { + const char *callconv = get_attrp(t->attrs, ATTR_CALLCONV); + if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; + if (callconv) fprintf(h, " %s ", callconv); + } + break; + } case TYPE_BASIC: if (type_basic_get_type(t) != TYPE_BASIC_INT32 && type_basic_get_type(t) != TYPE_BASIC_INT64 && @@ -426,11 +458,10 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i case TYPE_BITFIELD: { const decl_spec_t ds = {.type = type_bitfield_get_field(t)}; - write_type_left(h, &ds, name_type, declonly); + write_type_left(h, &ds, name_type, declonly, TRUE); break; } case TYPE_ALIAS: - case TYPE_FUNCTION: /* handled elsewhere */ assert(0); break; @@ -450,7 +481,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) type_t *elem = type_array_get_element_type(t); if (type_array_is_decl_as_ptr(t)) { - if (!type_is_alias(elem) && is_array(elem) && !type_array_is_decl_as_ptr(elem)) + if (decl_needs_parens(elem)) fprintf(h, ")"); } else @@ -463,10 +494,22 @@ void write_type_right(FILE *h, type_t *t, int is_field) write_type_right(h, elem, FALSE); break; } + case TYPE_FUNCTION: + { + const var_list_t *args = type_function_get_args(t); + fputc('(', h); + if (args) + write_args(h, args, NULL, 0, FALSE); + else + fprintf(h, "void"); + fputc(')', h); + write_type_right(h, type_function_get_rettype(t), FALSE); + break; + } case TYPE_POINTER: { type_t *ref = type_pointer_get_ref_type(t); - if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref)) + if (decl_needs_parens(ref)) fprintf(h, ")"); write_type_right(h, ref, FALSE); break; @@ -483,7 +526,6 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_ALIAS: case TYPE_MODULE: case TYPE_COCLASS: - case TYPE_FUNCTION: case TYPE_INTERFACE: break; } @@ -491,46 +533,17 @@ void write_type_right(FILE *h, type_t *t, int is_field)
static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name) { - type_t *t = ds->type, *pt = NULL; - int ptr_level = 0; + type_t *t = ds->type;
- if (!h) return; - - if (t) { - for (pt = t; is_ptr(pt); pt = type_pointer_get_ref_type(pt), ptr_level++) - ; - - 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_ret(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, ds, NAME_DEFAULT, declonly); - } + if (!h) return;
- if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); + if (t) + write_type_left(h, ds, NAME_DEFAULT, declonly, TRUE);
- if (t) { - if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { - const var_list_t *args = type_function_get_args(pt); + if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
- if (ptr_level) fputc(')', h); - fputc('(', h); - if (args) - write_args(h, args, NULL, 0, FALSE); - else - fprintf(h, "void"); - fputc(')', h); - } else - write_type_right(h, t, is_field); - } + if (t) + write_type_right(h, t, is_field); }
static void write_type_def_or_decl(FILE *f, const decl_spec_t *t, int field, const char *name) @@ -550,14 +563,14 @@ static void write_type_definition(FILE *f, type_t *t) write_namespace_start(f, t->namespace); } indent(f, 0); - write_type_left(f, &ds, NAME_DEFAULT, FALSE); + write_type_left(f, &ds, NAME_DEFAULT, FALSE, TRUE); fprintf(f, ";\n"); if(in_namespace) { t->written = save_written; write_namespace_end(f, t->namespace); fprintf(f, "extern "C" {\n"); fprintf(f, "#else\n"); - write_type_left(f, &ds, NAME_C, FALSE); + write_type_left(f, &ds, NAME_C, FALSE, TRUE); fprintf(f, ";\n"); fprintf(f, "#endif\n\n"); } @@ -570,7 +583,7 @@ void write_type_decl(FILE *f, const decl_spec_t *t, const char *name)
void write_type_decl_left(FILE *f, const decl_spec_t *ds) { - write_type_left(f, ds, NAME_DEFAULT, TRUE); + write_type_left(f, ds, NAME_DEFAULT, TRUE, TRUE); }
static int user_type_registered(const char *name) diff --git a/tools/widl/header.h b/tools/widl/header.h index e047e4e2e4..cebfd83fe4 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -29,7 +29,7 @@ extern int is_attr(const attr_list_t *list, enum attr_type t); extern void *get_attrp(const attr_list_t *list, enum attr_type t); extern unsigned int get_attrv(const attr_list_t *list, enum attr_type t); extern const char* get_name(const var_t *v); -extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly); +extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly, int write_callconv); extern void write_type_right(FILE *h, type_t *t, int is_field); extern void write_type_decl(FILE *f, const decl_spec_t *t, const char *name); extern void write_type_decl_left(FILE *f, const decl_spec_t *ds); @@ -66,6 +66,11 @@ static inline int is_array(const type_t *t) return type_get_type(t) == TYPE_ARRAY; }
+static inline int is_func(const type_t *t) +{ + return type_get_type(t) == TYPE_FUNCTION; +} + static inline int is_void(const type_t *t) { return type_get_type(t) == TYPE_VOID; diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 038b40725c..9cfcd7f30f 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -75,6 +75,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 void append_chain_callconv(type_t *chain, char *callconv); 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); @@ -975,8 +976,7 @@ decl_spec_no_type: 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)); } + | callconv declarator { $$ = $2; append_chain_callconv($$->type, $1); } | direct_declarator ;
@@ -984,18 +984,14 @@ direct_declarator: ident { $$ = make_declarator($1); } | '(' declarator ')' { $$ = $2; } | direct_declarator array { $$ = $1; $$->type = append_array($$->type, $2); } - | direct_declarator '(' m_args ')' { $$ = $1; - $$->func_type = append_chain_type($$->type, type_new_function($3)); - $$->type = NULL; - } + | direct_declarator '(' m_args ')' { $$ = $1; $$->type = append_chain_type($$->type, type_new_function($3)); } ;
/* 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)); } - | 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)); } + | callconv m_abstract_declarator { $$ = $2; append_chain_callconv($$->type, $1); } | abstract_direct_declarator ;
@@ -1003,8 +999,7 @@ abstract_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)); } - | 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)); } + | callconv m_any_declarator { $$ = $2; append_chain_callconv($$->type, $1); } ;
/* abstract declarator or empty */ @@ -1019,13 +1014,11 @@ abstract_direct_declarator: | array { $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); } | '(' m_args ')' { $$ = make_declarator(NULL); - $$->func_type = append_chain_type($$->type, type_new_function($2)); - $$->type = NULL; + $$->type = append_chain_type($$->type, type_new_function($2)); } | abstract_direct_declarator '(' m_args ')' { $$ = $1; - $$->func_type = append_chain_type($$->type, type_new_function($3)); - $$->type = NULL; + $$->type = append_chain_type($$->type, type_new_function($3)); } ;
@@ -1033,7 +1026,7 @@ abstract_direct_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)); } + | callconv m_any_declarator { $$ = $2; append_chain_callconv($$->type, $1); } | any_direct_declarator ;
@@ -1041,7 +1034,7 @@ any_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)); } + | callconv m_any_declarator { $$ = $2; append_chain_callconv($$->type, $1); } ;
/* abstract or non-abstract declarator or empty */ @@ -1059,13 +1052,11 @@ any_direct_declarator: | array { $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); } | '(' m_args ')' { $$ = make_declarator(NULL); - $$->func_type = append_chain_type($$->type, type_new_function($2)); - $$->type = NULL; + $$->type = append_chain_type($$->type, type_new_function($2)); } | any_direct_declarator '(' m_args ')' { $$ = $1; - $$->func_type = append_chain_type($$->type, type_new_function($3)); - $$->type = NULL; + $$->type = append_chain_type($$->type, type_new_function($3)); } ;
@@ -1463,34 +1454,58 @@ static int is_allowed_range_type(const type_t *type) } }
-static type_t *get_array_or_ptr_ref(type_t *type) +static type_t *get_chain_ref(type_t *type) { if (is_ptr(type)) return type_pointer_get_ref_type(type); else if (is_array(type)) return type_array_get_element_type(type); + else if (is_func(type)) + return type_function_get_rettype(type); return NULL; }
+static type_t *get_chain_end(type_t *type) +{ + type_t *inner; + while ((inner = get_chain_ref(type))) + type = inner; + return type; +} + static type_t *append_chain_type(type_t *chain, type_t *type) { type_t *chain_type;
if (!chain) return type; - for (chain_type = chain; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type)) - ; + chain_type = get_chain_end(chain);
if (is_ptr(chain_type)) chain_type->details.pointer.ref.type = type; else if (is_array(chain_type)) chain_type->details.array.elem.type = type; + else if (is_func(chain_type)) + chain_type->details.function->retval->declspec.type = type; 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) +{ + type_t *chain_end; + + if (chain && (chain_end = get_chain_end(chain))) + chain_end->attrs = append_attr(chain_end->attrs, make_attrp(ATTR_CALLCONV, callconv)); + else + error_loc("calling convention applied to non-function type\n"); +} + static warning_list_t *append_warning(warning_list_t *list, int num) { warning_t *entry; @@ -1514,21 +1529,14 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl 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;
if (is_attr(type->attrs, ATTR_INLINE)) { - if (!func_type) + if (!decl || !is_func(decl->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); - } + decl->type->attrs = move_attr(decl->type->attrs, type->attrs, ATTR_INLINE); }
/* add type onto the end of the pointers in pident->type */ @@ -1536,16 +1544,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl v->declspec.stgclass = decl_spec->stgclass; v->attrs = attrs;
+ if (is_attr(type->attrs, ATTR_CALLCONV) && !is_func(type)) + error_loc("calling convention applied to non-function type\n"); + /* check for pointer attribute being applied to non-pointer, non-array * type */ if (!is_array(v->declspec.type)) { int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); const type_t *ptr = NULL; - /* pointer attributes on the left side of the type belong to the function - * pointer, if one is being declared */ - type_t **pt = func_type ? &func_type : &v->declspec.type; - for (ptr = *pt; ptr && !ptr_attr; ) + for (ptr = v->declspec.type; ptr && !ptr_attr; ) { ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE); if (!ptr_attr && type_is_alias(ptr)) @@ -1560,13 +1568,13 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl warning_loc_info(&v->loc_info, "%s: pointer attribute applied to interface " "pointer type has no effect\n", v->name); - if (!ptr_attr && top && type_pointer_get_default_fc(*pt) != FC_RP) + if (!ptr_attr && top && type_pointer_get_default_fc(v->declspec.type) != 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); + v->declspec.type = duptype(v->declspec.type, 1); } } else if (ptr_attr) @@ -1667,32 +1675,6 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl 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->declspec.type; - v->declspec.type = func_type; - 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; - /* 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)) - ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV); - } - else - { - type_t *t; - for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t)) - if (is_attr(t->attrs, ATTR_CALLCONV)) - error_loc("calling convention applied to non-function-pointer type\n"); - } - if (decl->bits) v->declspec.type = type_new_bitfield(v->declspec.type, decl->bits);
@@ -1796,7 +1778,6 @@ 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->func_type = NULL; d->bits = NULL; return d; } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 55abd0a40c..2e4045154f 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -4805,7 +4805,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { print_file(file, 2, "%s", ""); - write_type_left( file, &arg->declspec, NAME_DEFAULT, TRUE ); + write_type_left( file, &arg->declspec, NAME_DEFAULT, TRUE, TRUE ); if (needs_space_after( arg->declspec.type )) fputc( ' ', file ); if (is_array( arg->declspec.type ) && !type_array_is_decl_as_ptr( arg->declspec.type )) fputc( '*', file );
@@ -4871,9 +4871,9 @@ int write_expr_eval_routines(FILE *file, const char *iface) { decl_spec_t ds = {.type = (type_t *)eval->cont_type}; print_file(file, 1, "%s", ""); - write_type_left(file, &ds, NAME_DEFAULT, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, TRUE, TRUE); fprintf(file, " *%s = (", var_name); - write_type_left(file, &ds, NAME_DEFAULT, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, TRUE, TRUE); fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); } print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index ef9a6699b2..615a758f4d 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -172,6 +172,7 @@ type_t *type_new_function(var_list_t *args) t = make_type(TYPE_FUNCTION); t->details.function = xmalloc(sizeof(*t->details.function)); t->details.function->args = args; + t->details.function->retval = make_var(xstrdup("_RetVal")); return t; }
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 3f2a719f2d..3f92192cee 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -478,7 +478,6 @@ struct _var_t { struct _declarator_t { var_t *var; type_t *type; - type_t *func_type; expr_t *bits;
/* parser-internal */
From: Richard Pospesel richard@torproject.org
Signed-off-by: Zebediah Figura z.figura12@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; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- tools/widl/header.c | 4 +++- tools/widl/parser.y | 43 ++++++++++++++++-------------------------- tools/widl/widltypes.h | 10 +++++++--- 3 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index bd7ca7e8e6..c20fe69917 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -318,6 +318,9 @@ 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 (ds->func_specifier & FUNCTION_SPECIFIER_INLINE) + fprintf(h, "inline "); + if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (type_is_alias(t) || !is_ptr(t))) fprintf(h, "const ");
@@ -383,7 +386,6 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i break; case TYPE_FUNCTION: { - if (is_attr(t->attrs, ATTR_INLINE)) fprintf(h, "inline "); write_type_left(h, type_function_get_ret(t), name_type, declonly, TRUE);
/* A pointer to a function has to write the calling convention inside diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 45782bae5f..f6d0886abe 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -60,7 +60,7 @@ 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, enum type_qualifier qual); + enum storage_class stgclass, enum type_qualifier qual, enum function_specifier func_specifier); 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); @@ -160,6 +160,7 @@ static typelib_t *current_typelib; struct _decl_spec_t *declspec; enum storage_class stgclass; enum type_qualifier type_qualifier; + enum function_specifier function_specifier; }
%token <str> aIDENTIFIER aPRAGMA @@ -261,7 +262,7 @@ static typelib_t *current_typelib; %token tWCHAR tWIREMARSHAL %token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH
-%type <attr> attribute function_specifier acf_attribute +%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 @@ -270,6 +271,7 @@ static typelib_t *current_typelib; %type <ifinfo> interfacehdr %type <stgclass> storage_cls_spec %type <type_qualifier> type_qualifier m_type_qual_list +%type <function_specifier> 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 @@ -950,7 +952,7 @@ storage_cls_spec: ;
function_specifier: - tINLINE { $$ = make_attr(ATTR_INLINE); } + tINLINE { $$ = FUNCTION_SPECIFIER_INLINE; } ;
type_qualifier: @@ -961,9 +963,9 @@ 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, 0); } +decl_spec: type m_decl_spec_no_type { $$ = make_decl_spec($1, $2, NULL, STG_NONE, 0, 0); } | decl_spec_no_type type m_decl_spec_no_type - { $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE, 0); } + { $$ = make_decl_spec($2, $1, $3, STG_NONE, 0, 0); } ;
m_decl_spec_no_type: { $$ = NULL; } @@ -971,9 +973,9 @@ m_decl_spec_no_type: { $$ = NULL; } ;
decl_spec_no_type: - 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); } + type_qualifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, $1, 0); } + | function_specifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, 0, $1); } + | storage_cls_spec m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, 0, 0); } ;
declarator: @@ -1285,57 +1287,47 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter }
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) + enum storage_class stgclass, enum type_qualifier qual, enum function_specifier func_specifier) { decl_spec_t *declspec = left ? left : right; if (!declspec) { declspec = xmalloc(sizeof(*declspec)); declspec->type = NULL; - declspec->attrs = NULL; declspec->stgclass = STG_NONE; declspec->qualifier = 0; + declspec->func_specifier = 0; } 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"); declspec->qualifier |= left->qualifier; + declspec->func_specifier |= left->func_specifier; 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"); declspec->qualifier |= right->qualifier; + declspec->func_specifier |= right->func_specifier; 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"); declspec->qualifier |= qual; - - /* 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; - } + declspec->func_specifier |= func_specifier;
return declspec; } @@ -1550,12 +1542,10 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator type_t **ptype; type_t *type = decl_spec->type;
- if (is_attr(type->attrs, ATTR_INLINE)) + if (decl_spec->func_specifier & FUNCTION_SPECIFIER_INLINE) { if (!decl || !is_func(decl->type)) error_loc("inline attribute applied to non-function type\n"); - else - decl->type->attrs = move_attr(decl->type->attrs, type->attrs, ATTR_INLINE); }
/* add type onto the end of the pointers in pident->type */ @@ -2182,7 +2172,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/widltypes.h b/tools/widl/widltypes.h index 6e88019a80..c217c5960f 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -115,7 +115,6 @@ enum attr_type ATTR_IMMEDIATEBIND, ATTR_IMPLICIT_HANDLE, ATTR_IN, - ATTR_INLINE, ATTR_INPUTSYNC, ATTR_LENGTHIS, ATTR_LIBLCID, @@ -239,6 +238,11 @@ enum type_qualifier TYPE_QUALIFIER_CONST = 1, };
+enum function_specifier +{ + FUNCTION_SPECIFIER_INLINE = 1, +}; + enum statement_type { STMT_LIBRARY, @@ -301,9 +305,9 @@ struct str_list_entry_t struct _decl_spec_t { type_t *type; - attr_list_t *attrs; enum storage_class stgclass; enum type_qualifier qualifier; + enum function_specifier func_specifier; };
struct _attr_t { @@ -630,9 +634,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->qualifier = 0; + declspec->func_specifier = 0;
return declspec; }
This fixes type format string generation for the following IDL:
typedef int *intp; [pointer_default(ref)] interface IRef { void a(intp *a); } [pointer_default(unique)] interface IUnique { void b(intp *a); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- tools/widl/expr.c | 6 +++--- tools/widl/parser.h | 6 ------ tools/widl/parser.y | 39 +++++++++++++++------------------------ tools/widl/typegen.c | 9 +++++---- tools/widl/typetree.c | 7 ++----- tools/widl/typetree.h | 19 ++----------------- tools/widl/widltypes.h | 2 -- 7 files changed, 27 insertions(+), 61 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 0b345f3f6a..d1ee599a39 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)); + result.type = type_new_pointer(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)); + result.type = type_new_pointer(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); + result.type = type_new_pointer(result.type); break; case EXPR_PPTR: result = resolve_expression(expr_loc, cont_type, e->ref); diff --git a/tools/widl/parser.h b/tools/widl/parser.h index f48cacc005..a67b160d48 100644 --- a/tools/widl/parser.h +++ b/tools/widl/parser.h @@ -21,12 +21,6 @@ #ifndef __WIDL_PARSER_H #define __WIDL_PARSER_H
-typedef struct -{ - type_t *interface; - unsigned char old_pointer_default; -} interface_info_t; - int parser_parse(void);
extern FILE *parser_in; diff --git a/tools/widl/parser.y b/tools/widl/parser.y index f6d0886abe..afbe2b1799 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -38,8 +38,6 @@ #include "expr.h" #include "typetree.h"
-static unsigned char pointer_default = FC_UP; - typedef struct list typelist_t; struct typenode { type_t *type; @@ -154,7 +152,6 @@ static typelib_t *current_typelib; UUID *uuid; unsigned int num; double dbl; - interface_info_t ifinfo; typelib_t *typelib; struct _import_t *import; struct _decl_spec_t *declspec; @@ -268,7 +265,7 @@ static typelib_t *current_typelib; %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 <type> interfacehdr %type <stgclass> storage_cls_spec %type <type_qualifier> type_qualifier m_type_qual_list %type <function_specifier> function_specifier @@ -896,10 +893,7 @@ interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_n | tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } ;
-interfacehdr: attributes interface { $$.interface = $2; - $$.old_pointer_default = pointer_default; - if (is_attr($1, ATTR_POINTERDEFAULT)) - pointer_default = get_attrv($1, ATTR_POINTERDEFAULT); +interfacehdr: attributes interface { $$ = $2; check_def($2); $2->attrs = check_iface_attrs($2->name, $1); $2->defined = TRUE; @@ -907,20 +901,18 @@ interfacehdr: attributes interface { $$.interface = $2; ;
interfacedef: interfacehdr inherit - '{' int_statements '}' semicolon_opt { $$ = $1.interface; + '{' int_statements '}' semicolon_opt { $$ = $1; if($$ == $2) error_loc("Interface can't inherit from itself\n"); type_interface_define($$, $2, $4); check_async_uuid($$); - pointer_default = $1.old_pointer_default; } /* MIDL is able to import the definition of a base class from inside the * definition of a derived class, I'll try to support it with this rule */ | interfacehdr ':' aIDENTIFIER '{' import int_statements '}' - semicolon_opt { $$ = $1.interface; + semicolon_opt { $$ = $1; type_interface_define($$, find_type_or_error2($3, 0), $6); - pointer_default = $1.old_pointer_default; } | dispinterfacedef semicolon_opt { $$ = $1; } ; @@ -980,7 +972,7 @@ decl_spec_no_type:
declarator: '*' m_type_qual_list declarator %prec PPTR - { $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } | callconv declarator { $$ = $2; append_chain_callconv($$->type, $1); } | direct_declarator ; @@ -995,7 +987,7 @@ direct_declarator: /* abstract declarator */ abstract_declarator: '*' m_type_qual_list m_abstract_declarator %prec PPTR - { $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } | callconv m_abstract_declarator { $$ = $2; append_chain_callconv($$->type, $1); } | abstract_direct_declarator ; @@ -1003,7 +995,7 @@ abstract_declarator: /* abstract declarator without accepting direct declarator */ abstract_declarator_no_direct: '*' m_type_qual_list m_any_declarator %prec PPTR - { $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } | callconv m_any_declarator { $$ = $2; append_chain_callconv($$->type, $1); } ;
@@ -1030,7 +1022,7 @@ abstract_direct_declarator: /* abstract or non-abstract declarator */ any_declarator: '*' m_type_qual_list m_any_declarator %prec PPTR - { $$ = $3; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } | callconv m_any_declarator { $$ = $2; append_chain_callconv($$->type, $1); } | any_direct_declarator ; @@ -1038,7 +1030,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; append_chain_type($$, type_new_pointer(pointer_default, NULL), $2); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } | callconv m_any_declarator { $$ = $2; append_chain_callconv($$->type, $1); } ;
@@ -1378,7 +1370,7 @@ static void append_array(declarator_t *decl, expr_t *expr) /* 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); + expr->is_const ? NULL : expr, NULL);
append_chain_type(decl, array, 0); } @@ -1579,7 +1571,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator warning_loc_info(&v->loc_info, "%s: pointer attribute applied to interface " "pointer type has no effect\n", v->name); - if (!ptr_attr && top && type_pointer_get_default_fc(v->declspec.type) != FC_RP) + if (!ptr_attr && top) { /* 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 @@ -1643,11 +1635,11 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator else *ptype = type_new_array((*ptype)->name, type_array_get_element(*ptype), FALSE, - 0, dim, NULL, FC_RP); + 0, dim, NULL); } else if (is_ptr(*ptype)) *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE, - 0, dim, NULL, pointer_default); + 0, dim, NULL); else error_loc("%s: size_is attribute applied to illegal type\n", v->name); } @@ -1671,8 +1663,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator type_array_get_element(*ptype), type_array_is_decl_as_ptr(*ptype), type_array_get_dim(*ptype), - type_array_get_conformance(*ptype), - dim, type_array_get_ptr_default_fc(*ptype)); + type_array_get_conformance(*ptype), dim); } else error_loc("%s: length_is attribute applied to illegal type\n", v->name); @@ -1798,7 +1789,7 @@ static type_t *make_safearray(type_t *type) { decl_spec_t ds = {.type = type}; ds.type = type_new_alias(&ds, "SAFEARRAY"); - return type_new_array(NULL, &ds, TRUE, 0, NULL, NULL, FC_RP); + return type_new_array(NULL, &ds, TRUE, 0, NULL, NULL); }
static typelib_t *make_library(const char *name, const attr_list_t *attrs) diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 2e4045154f..1ad3e63c6a 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -276,10 +276,11 @@ unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int t
if (toplevel_param) return FC_RP; - else if (is_ptr(type)) - return type_pointer_get_default_fc(type); - else - return type_array_get_ptr_default_fc(type); + + if ((pointer_type = get_attrv(current_iface->attrs, ATTR_POINTERDEFAULT))) + return pointer_type; + + return FC_UP; }
static unsigned char get_pointer_fc_context( const type_t *type, const attr_list_t *attrs, diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 37555be478..a066125b16 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -176,10 +176,9 @@ type_t *type_new_function(var_list_t *args) return t; }
-type_t *type_new_pointer(unsigned char pointer_default, type_t *ref) +type_t *type_new_pointer(type_t *ref) { type_t *t = make_type(TYPE_POINTER); - t->details.pointer.def_fc = pointer_default; t->details.pointer.ref.type = ref; return t; } @@ -218,8 +217,7 @@ type_t *type_new_coclass(char *name)
type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr, - unsigned int dim, expr_t *size_is, expr_t *length_is, - unsigned char ptr_default_fc) + unsigned int dim, expr_t *size_is, expr_t *length_is) { type_t *t = make_type(TYPE_ARRAY); if (name) t->name = xstrdup(name); @@ -231,7 +229,6 @@ type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr t->details.array.dim = dim; if (element) t->details.array.elem = *element; - t->details.array.ptr_def_fc = ptr_default_fc; return t; }
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index ce5e835dfd..f025f25e59 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -30,12 +30,11 @@ enum name_type { };
type_t *type_new_function(var_list_t *args); -type_t *type_new_pointer(unsigned char pointer_default, type_t *ref); +type_t *type_new_pointer(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, - unsigned int dim, expr_t *size_is, expr_t *length_is, - unsigned char ptr_default_fc); + unsigned int dim, expr_t *size_is, expr_t *length_is); 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); @@ -295,13 +294,6 @@ static inline int type_array_is_decl_as_ptr(const type_t *type) return type->details.array.declptr; }
-static inline unsigned char type_array_get_ptr_default_fc(const type_t *type) -{ - type = type_get_real_type(type); - assert(type_get_type(type) == TYPE_ARRAY); - return type->details.array.ptr_def_fc; -} - static inline int type_is_alias(const type_t *type) { return type->type_type == TYPE_ALIAS; @@ -338,13 +330,6 @@ static inline type_t *type_pointer_get_ref_type(const type_t *type) return type_pointer_get_ref(type)->type; }
-static inline unsigned char type_pointer_get_default_fc(const type_t *type) -{ - 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) { type = type_get_real_type(type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index c217c5960f..3886360bd4 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -374,7 +374,6 @@ struct array_details expr_t *length_is; struct _decl_spec_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 */ }; @@ -393,7 +392,6 @@ struct basic_details struct pointer_details { struct _decl_spec_t ref; - unsigned char def_fc; };
struct bitfield_details