diff --git a/tools/widl/header.c b/tools/widl/header.c index 7d224fe6014..16bf82bf91c 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -483,6 +483,10 @@ void write_expr(FILE *h, const expr_t *e, int brackets) write_expr(h, e->ext2, 1); if (brackets) fprintf(h, ")"); break; + case EXPR_ADDRESSOF: + fprintf(h, "&"); + write_expr(h, e->ref, 1); + break; } } diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 06f00352ad2..ffeca26cedc 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -280,6 +280,7 @@ static void check_all_user_types(ifref_list_t *ifaces); %right CAST %right PPTR %right NEG +%right ADDRESSOF %% @@ -612,6 +613,7 @@ expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } | expr SHR expr { $$ = make_expr2(EXPR_SHR, $1, $3); } | '~' expr { $$ = make_expr1(EXPR_NOT, $2); } | '-' expr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); } + | '&' expr %prec ADDRESSOF { $$ = make_expr1(EXPR_ADDRESSOF, $2); } | '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); } | '(' type ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, $2, $4); } | tSIZEOF '(' type ')' { $$ = make_exprt(EXPR_SIZEOF, $3, NULL); } @@ -1138,6 +1140,8 @@ static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr) static expr_t *make_expr1(enum expr_type type, expr_t *expr) { expr_t *e; + if (type == EXPR_ADDRESSOF && expr->type != EXPR_IDENTIFIER) + error("address-of operator applied to invalid expression\n"); e = xmalloc(sizeof(expr_t)); e->type = type; e->ref = expr; diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 346318f7496..1988f363a1e 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -288,6 +288,7 @@ static int compare_expr(const expr_t *a, const expr_t *b) case EXPR_NOT: case EXPR_NEG: case EXPR_PPTR: + case EXPR_ADDRESSOF: return compare_expr(a->ref, b->ref); case EXPR_SIZEOF: return compare_type(a->u.tref, b->u.tref); @@ -3023,6 +3024,10 @@ static void write_struct_expr(FILE *h, const expr_t *e, int brackets, write_struct_expr(h, e->ext2, 1, fields, structvar); if (brackets) fprintf(h, ")"); break; + case EXPR_ADDRESSOF: + fprintf(h, "&"); + write_struct_expr(h, e->ref, 1, fields, structvar); + break; } } diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 4145be2661b..6930f711719 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -154,6 +154,7 @@ enum expr_type EXPR_OR, EXPR_COND, EXPR_TRUEFALSE, + EXPR_ADDRESSOF, }; enum type_kind