From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 40 +++++++++++++++++++---------- tools/widl/header.c | 8 +++--- tools/widl/parser.y | 58 ++++++++++++++++++++++++++++-------------- tools/widl/widl.h | 3 ++- tools/widl/widltypes.h | 3 ++- 5 files changed, 74 insertions(+), 38 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 8ea7f932771..36f5d769d1a 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -116,6 +116,16 @@ expr_t *expr_void(void) return e; }
+expr_t *expr_decl( decl_spec_t *decl ) +{ + expr_t *e = xmalloc( sizeof(expr_t) ); + memset( e, 0, sizeof(*e) ); + e->type = EXPR_DECL; + e->u.decl = decl; + e->is_const = TRUE; + return e; +} + expr_t *expr_int( int val, const char *text ) { expr_t *e = xmalloc( sizeof(expr_t) ); @@ -177,21 +187,21 @@ expr_t *expr_str( enum expr_type type, char *val ) return e; }
-expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) +expr_t *make_exprt(enum expr_type type, expr_t *decl, expr_t *expr) { expr_t *e; type_t *tref;
- if (var->declspec.stgclass != STG_NONE && var->declspec.stgclass != STG_REGISTER) + if (decl->u.decl->stgclass != STG_NONE && decl->u.decl->stgclass != STG_REGISTER) error_loc("invalid storage class for type expression\n");
- tref = var->declspec.type; + tref = decl->u.decl->type;
e = xmalloc( sizeof(expr_t) ); memset( e, 0, sizeof(*e) ); e->type = type; - e->u.args[0] = expr; - e->tref = var->declspec; + e->u.args[0] = decl; + e->u.args[1] = expr; if (type == EXPR_SIZEOF) { /* only do this for types that should be the same on all platforms */ @@ -232,7 +242,7 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) e->cval = expr->cval; } } - free(var); + return e; }
@@ -462,6 +472,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc switch (e->type) { case EXPR_VOID: + case EXPR_DECL: break; case EXPR_INT: result.is_temporary = FALSE; @@ -533,8 +544,8 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); break; case EXPR_CAST: - result = resolve_expression( expr_loc, cont_type, e->u.args[0] ); - result.type = e->tref.type; + result = resolve_expression( expr_loc, cont_type, e->u.args[1] ); + result.type = e->u.args[0]->u.decl->type; break; case EXPR_SIZEOF: result.is_temporary = FALSE; @@ -637,6 +648,7 @@ void write_expr(FILE *h, const expr_t *e, int brackets, switch (e->type) { case EXPR_VOID: + case EXPR_DECL: break; case EXPR_INT: fprintf(h, "%s", e->text); @@ -692,13 +704,13 @@ void write_expr(FILE *h, const expr_t *e, int brackets, break; case EXPR_CAST: fprintf(h, "("); - write_type_decl( h, &e->tref, NULL ); + write_type_decl( h, e->u.args[0]->u.decl, NULL ); fprintf(h, ")"); - write_expr( h, e->u.args[0], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); + write_expr( h, e->u.args[1], 1, toplevel, toplevel_prefix, cont_type, local_var_prefix ); break; case EXPR_SIZEOF: fprintf(h, "sizeof("); - write_type_decl( h, &e->tref, NULL ); + write_type_decl( h, e->u.args[0]->u.decl, NULL ); fprintf(h, ")"); break; case EXPR_SHL: @@ -848,7 +860,7 @@ int compare_expr(const expr_t *a, const expr_t *b) return ret; return compare_expr( a->u.args[1], b->u.args[1] ); case EXPR_CAST: - ret = compare_type( a->tref.type, b->tref.type ); + ret = compare_type( a->u.args[0]->u.decl->type, b->u.args[0]->u.decl->type ); if (ret != 0) return ret; /* Fall through. */ @@ -860,7 +872,9 @@ int compare_expr(const expr_t *a, const expr_t *b) case EXPR_POS: return compare_expr( a->u.args[0], b->u.args[0] ); case EXPR_SIZEOF: - return compare_type( a->tref.type, b->tref.type ); + return compare_type( a->u.args[0]->u.decl->type, b->u.args[0]->u.decl->type ); + case EXPR_DECL: + return compare_type( a->u.decl->type, b->u.decl->type ); case EXPR_VOID: return 0; } diff --git a/tools/widl/header.c b/tools/widl/header.c index 006e5a274a0..bd7dddca862 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1581,8 +1581,8 @@ static void write_apicontract_guard_start(FILE *header, const expr_t *expr) char *name; int ver; if (!winrt_mode) return; - type = expr->tref.type; - ver = expr->u.args[0]->u.lval; + type = expr->u.args[0]->u.decl->type; + ver = expr->u.args[1]->u.lval; name = format_apicontract_macro(type); fprintf(header, "#if %s_VERSION >= %#x\n", name, ver); free(name); @@ -1594,8 +1594,8 @@ static void write_apicontract_guard_end(FILE *header, const expr_t *expr) char *name; int ver; if (!winrt_mode) return; - type = expr->tref.type; - ver = expr->u.args[0]->u.lval; + type = expr->u.args[0]->u.decl->type; + ver = expr->u.args[1]->u.lval; name = format_apicontract_macro(type); fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver); free(name); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 9805e33d33d..edaa27a3e43 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -305,6 +305,7 @@ void pop_import( PARSER_LTYPE *yylloc ); %type <type_qualifier> type_qualifier m_type_qual_list %type <function_specifier> function_specifier %type <declspec> decl_spec unqualified_decl_spec decl_spec_no_type m_decl_spec_no_type +%type <declspec> cast_decl_spec %type <type> inherit interface interfacedef %type <type> interfaceref %type <type> dispinterfaceref @@ -597,26 +598,31 @@ contract_ver: contract_req : decl_spec ',' contract_ver { expr_t *contract = expr_int( $3, strmake( "%u", $3 ) ); + expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_APICONTRACT) error_loc( "type %s is not an apicontract\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_GTREQL, declare_var( NULL, $decl_spec, make_declarator( NULL ), 0 ), contract ); + $$ = make_exprt( EXPR_GTREQL, decl, contract ); } ;
static_attr - : decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) - error_loc("type %s is not an interface\n", $1->type->name); - $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); - } - ; + : decl_spec ',' contract_req { + expr_t *decl = expr_decl( $decl_spec ); + if ($decl_spec->type->type_type != TYPE_INTERFACE) + error_loc( "type %s is not an interface\n", $decl_spec->type->name ); + $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + } + ;
activatable_attr: - decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) - error_loc("type %s is not an interface\n", $1->type->name); - $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); - } - | contract_req { $$ = $1; } /* activatable on the default activation factory */ - ; + decl_spec ',' contract_req { + expr_t *decl = expr_decl( $decl_spec ); + if ($decl_spec->type->type_type != TYPE_INTERFACE) + error_loc( "type %s is not an interface\n", $decl_spec->type->name ); + $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + } + | contract_req { $$ = $contract_req; } /* activatable on the default activation factory */ + ;
access_attr : tPUBLIC { $$ = attr_int( @$, ATTR_PUBLIC, 0 ); } @@ -625,9 +631,11 @@ access_attr
composable_attr : decl_spec ',' access_attr ',' contract_req - { if ($1->type->type_type != TYPE_INTERFACE) - error_loc( "type %s is not an interface\n", $1->type->name ); - $$ = make_exprt( EXPR_MEMBER, declare_var( append_attr( NULL, $3 ), $1, make_declarator( NULL ), 0 ), $5 ); + { + expr_t *decl = expr_decl( $decl_spec ); + if ($decl_spec->type->type_type != TYPE_INTERFACE) + error_loc( "type %s is not an interface\n", $decl_spec->type->name ); + $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); } ;
@@ -884,10 +892,15 @@ expr: aNUM { $$ = expr_int( $aNUM, strmake( expr_t *member = expr_str( EXPR_IDENTIFIER, $aIDENTIFIER ); $$ = expr_op( EXPR_MEMBER, $obj, member, NULL ); } - | '(' unqualified_decl_spec m_abstract_declarator ')' expr %prec CAST - { $$ = make_exprt(EXPR_CAST, declare_var(NULL, $2, $3, 0), $5); free($2); free($3); } - | tSIZEOF '(' unqualified_decl_spec m_abstract_declarator ')' - { $$ = make_exprt(EXPR_SIZEOF, declare_var(NULL, $3, $4, 0), NULL); free($3); free($4); } + | '(' cast_decl_spec ')' expr[value] %prec CAST + { + expr_t *decl = expr_decl( $cast_decl_spec ); + $$ = make_exprt( EXPR_CAST, decl, $value ); + } + | tSIZEOF '(' cast_decl_spec ')' { + expr_t *decl = expr_decl( $cast_decl_spec ); + $$ = make_exprt( EXPR_SIZEOF, decl, NULL ); + } | expr[array] '[' expr[index] ']' { $$ = expr_op( EXPR_ARRAY, $array, $index, NULL ); } | '(' expr ')' { $$ = $2; } ; @@ -1204,6 +1217,13 @@ unqualified_decl_spec: unqualified_type m_decl_spec_no_type { $$ = make_decl_spec($2, $1, $3, STG_NONE, 0, 0); } ;
+cast_decl_spec: unqualified_decl_spec m_abstract_declarator + { + append_chain_type( $m_abstract_declarator, $unqualified_decl_spec->type, $unqualified_decl_spec->qualifier ); + $$ = make_decl_spec( $m_abstract_declarator->type, $unqualified_decl_spec, NULL, STG_NONE, 0, 0 ); + } + ; + m_decl_spec_no_type : %empty { $$ = NULL; } | decl_spec_no_type diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 2bd2d1b8a9d..506d9e39809 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -140,10 +140,11 @@ struct expr_loc };
extern expr_t *expr_void(void); +extern expr_t *expr_decl( decl_spec_t *decl ); extern expr_t *expr_int( int val, const char *text ); extern expr_t *expr_double( double val ); extern expr_t *expr_str( enum expr_type type, char *val ); -extern expr_t *make_exprt( enum expr_type type, var_t *var, expr_t *expr ); +extern expr_t *make_exprt( enum expr_type type, expr_t *decl, expr_t *expr ); extern expr_t *expr_op( enum expr_type type, expr_t *arg0, expr_t *arg1, expr_t *arg2 );
extern const type_t *expr_resolve_type( const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr ); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 322c6084f26..ba4fecdbede 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -189,6 +189,7 @@ enum attr_type enum expr_type { EXPR_VOID, + EXPR_DECL, EXPR_INT, EXPR_DOUBLE, EXPR_IDENTIFIER, @@ -352,9 +353,9 @@ struct _expr_t { int lval; double dval; const char *sval; + decl_spec_t *decl; const expr_t *args[3]; } u; - decl_spec_t tref; int is_const; int cval; /* parser-internal */