blob: cf97c7ea20a5b4e4bef2e588f4e6bf19380f8afb [file] [log] [blame]
Rob Shearman80ab2a72008-04-22 11:36:38 +01001/*
2 * Expression Abstract Syntax Tree Functions
3 *
4 * Copyright 2002 Ove Kaaven
5 * Copyright 2006-2008 Robert Shearman
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include "config.h"
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <assert.h>
28#include <ctype.h>
29#include <string.h>
30
31#include "widl.h"
32#include "utils.h"
33#include "expr.h"
34#include "header.h"
Rob Shearman04a22cc2008-12-29 12:05:27 +000035#include "typetree.h"
Rob Shearmanba91ee62009-02-23 13:47:57 +000036#include "typegen.h"
37
Rob Shearmanb5440142010-03-23 13:33:46 +000038static int is_integer_type(const type_t *type)
39{
40 switch (type_get_type(type))
41 {
42 case TYPE_ENUM:
43 return TRUE;
44 case TYPE_BASIC:
45 switch (type_basic_get_type(type))
46 {
47 case TYPE_BASIC_INT8:
48 case TYPE_BASIC_INT16:
49 case TYPE_BASIC_INT32:
50 case TYPE_BASIC_INT64:
51 case TYPE_BASIC_INT:
52 case TYPE_BASIC_INT3264:
53 case TYPE_BASIC_CHAR:
54 case TYPE_BASIC_HYPER:
55 case TYPE_BASIC_BYTE:
56 case TYPE_BASIC_WCHAR:
57 case TYPE_BASIC_ERROR_STATUS_T:
58 return TRUE;
59 case TYPE_BASIC_FLOAT:
60 case TYPE_BASIC_DOUBLE:
61 case TYPE_BASIC_HANDLE:
62 return FALSE;
63 }
64 return FALSE;
65 default:
66 return FALSE;
67 }
68}
69
70static int is_signed_integer_type(const type_t *type)
71{
72 switch (type_get_type(type))
73 {
74 case TYPE_ENUM:
75 return FALSE;
76 case TYPE_BASIC:
77 switch (type_basic_get_type(type))
78 {
79 case TYPE_BASIC_INT8:
80 case TYPE_BASIC_INT16:
81 case TYPE_BASIC_INT32:
82 case TYPE_BASIC_INT64:
83 case TYPE_BASIC_INT:
84 case TYPE_BASIC_INT3264:
85 return type_basic_get_sign(type) < 0;
86 case TYPE_BASIC_CHAR:
87 return TRUE;
88 case TYPE_BASIC_HYPER:
89 case TYPE_BASIC_BYTE:
90 case TYPE_BASIC_WCHAR:
91 case TYPE_BASIC_ERROR_STATUS_T:
92 case TYPE_BASIC_FLOAT:
93 case TYPE_BASIC_DOUBLE:
94 case TYPE_BASIC_HANDLE:
95 return FALSE;
96 }
Marcus Meissner0222ad72011-03-29 15:34:15 +020097 /* FALLTHROUGH */
Rob Shearmanb5440142010-03-23 13:33:46 +000098 default:
99 return FALSE;
100 }
101}
102
103static int is_float_type(const type_t *type)
104{
105 return (type_get_type(type) == TYPE_BASIC &&
106 (type_basic_get_type(type) == TYPE_BASIC_FLOAT ||
107 type_basic_get_type(type) == TYPE_BASIC_DOUBLE));
108}
Rob Shearman80ab2a72008-04-22 11:36:38 +0100109
110expr_t *make_expr(enum expr_type type)
111{
112 expr_t *e = xmalloc(sizeof(expr_t));
113 e->type = type;
114 e->ref = NULL;
115 e->u.lval = 0;
116 e->is_const = FALSE;
117 e->cval = 0;
118 return e;
119}
120
Alexandre Julliarda83563a2010-03-26 11:42:28 +0100121expr_t *make_exprl(enum expr_type type, int val)
Rob Shearman80ab2a72008-04-22 11:36:38 +0100122{
123 expr_t *e = xmalloc(sizeof(expr_t));
124 e->type = type;
125 e->ref = NULL;
126 e->u.lval = val;
127 e->is_const = FALSE;
128 /* check for numeric constant */
129 if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE)
130 {
131 /* make sure true/false value is valid */
132 assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
133 e->is_const = TRUE;
134 e->cval = val;
135 }
136 return e;
137}
138
139expr_t *make_exprd(enum expr_type type, double val)
140{
141 expr_t *e = xmalloc(sizeof(expr_t));
142 e->type = type;
143 e->ref = NULL;
144 e->u.dval = val;
145 e->is_const = TRUE;
146 e->cval = val;
147 return e;
148}
149
150expr_t *make_exprs(enum expr_type type, char *val)
151{
152 expr_t *e;
153 e = xmalloc(sizeof(expr_t));
154 e->type = type;
155 e->ref = NULL;
156 e->u.sval = val;
157 e->is_const = FALSE;
158 /* check for predefined constants */
Rob Shearmand9b83e82010-01-18 22:15:46 +0000159 switch (type)
160 {
161 case EXPR_IDENTIFIER:
Rob Shearman80ab2a72008-04-22 11:36:38 +0100162 {
163 var_t *c = find_const(val, 0);
164 if (c)
165 {
166 e->u.sval = c->name;
167 free(val);
168 e->is_const = TRUE;
169 e->cval = c->eval->cval;
170 }
Rob Shearmand9b83e82010-01-18 22:15:46 +0000171 break;
172 }
173 case EXPR_CHARCONST:
174 if (!val[0])
175 error_loc("empty character constant\n");
176 else if (val[1])
177 error_loc("multi-character constants are endian dependent\n");
178 else
179 {
180 e->is_const = TRUE;
181 e->cval = *val;
182 }
183 break;
184 default:
185 break;
Rob Shearman80ab2a72008-04-22 11:36:38 +0100186 }
187 return e;
188}
189
Rob Shearman02280082009-11-07 15:55:22 +0100190expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
Rob Shearman80ab2a72008-04-22 11:36:38 +0100191{
192 expr_t *e;
Rob Shearman02280082009-11-07 15:55:22 +0100193 type_t *tref;
194
195 if (var->stgclass != STG_NONE && var->stgclass != STG_REGISTER)
196 error_loc("invalid storage class for type expression\n");
197
198 tref = var->type;
199
Rob Shearman80ab2a72008-04-22 11:36:38 +0100200 e = xmalloc(sizeof(expr_t));
201 e->type = type;
202 e->ref = expr;
203 e->u.tref = tref;
204 e->is_const = FALSE;
Rob Shearman80ab2a72008-04-22 11:36:38 +0100205 if (type == EXPR_SIZEOF)
206 {
Rob Shearmanba91ee62009-02-23 13:47:57 +0000207 /* only do this for types that should be the same on all platforms */
208 if (is_integer_type(tref) || is_float_type(tref))
Rob Shearman80ab2a72008-04-22 11:36:38 +0100209 {
Rob Shearman80ab2a72008-04-22 11:36:38 +0100210 e->is_const = TRUE;
Alexandre Julliardcb6a2252010-04-05 19:48:07 +0200211 e->cval = type_memsize(tref);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100212 }
213 }
Rob Shearmanba91ee62009-02-23 13:47:57 +0000214 /* check for cast of constant expression */
Rob Shearman80ab2a72008-04-22 11:36:38 +0100215 if (type == EXPR_CAST && expr->is_const)
216 {
Rob Shearmanb5440142010-03-23 13:33:46 +0000217 if (is_integer_type(tref))
218 {
Alexandre Julliardcb6a2252010-04-05 19:48:07 +0200219 unsigned int cast_type_bits = type_memsize(tref) * 8;
Alexandre Julliarda83563a2010-03-26 11:42:28 +0100220 unsigned int cast_mask;
Rob Shearmanb5440142010-03-23 13:33:46 +0000221
222 e->is_const = TRUE;
223 if (is_signed_integer_type(tref))
224 {
Jarkko Korpibb9b2f32016-06-21 09:23:22 +0300225 cast_mask = (1u << (cast_type_bits - 1)) - 1;
226 if (expr->cval & (1u << (cast_type_bits - 1)))
Rob Shearmanb5440142010-03-23 13:33:46 +0000227 e->cval = -((-expr->cval) & cast_mask);
228 else
229 e->cval = expr->cval & cast_mask;
230 }
231 else
232 {
233 /* calculate ((1 << cast_type_bits) - 1) avoiding overflow */
Jarkko Korpibb9b2f32016-06-21 09:23:22 +0300234 cast_mask = ((1u << (cast_type_bits - 1)) - 1) |
235 1u << (cast_type_bits - 1);
Rob Shearmanb5440142010-03-23 13:33:46 +0000236 e->cval = expr->cval & cast_mask;
237 }
238 }
239 else
240 {
241 e->is_const = TRUE;
242 e->cval = expr->cval;
243 }
Rob Shearman80ab2a72008-04-22 11:36:38 +0100244 }
Rob Shearman02280082009-11-07 15:55:22 +0100245 free(var);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100246 return e;
247}
248
249expr_t *make_expr1(enum expr_type type, expr_t *expr)
250{
251 expr_t *e;
252 e = xmalloc(sizeof(expr_t));
253 e->type = type;
254 e->ref = expr;
255 e->u.lval = 0;
256 e->is_const = FALSE;
257 /* check for compile-time optimization */
258 if (expr->is_const)
259 {
260 e->is_const = TRUE;
261 switch (type)
262 {
263 case EXPR_LOGNOT:
264 e->cval = !expr->cval;
265 break;
266 case EXPR_POS:
267 e->cval = +expr->cval;
268 break;
269 case EXPR_NEG:
270 e->cval = -expr->cval;
271 break;
272 case EXPR_NOT:
273 e->cval = ~expr->cval;
274 break;
275 default:
276 e->is_const = FALSE;
277 break;
278 }
279 }
280 return e;
281}
282
283expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
284{
285 expr_t *e;
286 e = xmalloc(sizeof(expr_t));
287 e->type = type;
288 e->ref = expr1;
289 e->u.ext = expr2;
290 e->is_const = FALSE;
291 /* check for compile-time optimization */
292 if (expr1->is_const && expr2->is_const)
293 {
294 e->is_const = TRUE;
295 switch (type)
296 {
297 case EXPR_ADD:
298 e->cval = expr1->cval + expr2->cval;
299 break;
300 case EXPR_SUB:
301 e->cval = expr1->cval - expr2->cval;
302 break;
303 case EXPR_MOD:
304 if (expr2->cval == 0)
305 {
306 error_loc("divide by zero in expression\n");
307 e->cval = 0;
308 }
309 else
310 e->cval = expr1->cval % expr2->cval;
311 break;
312 case EXPR_MUL:
313 e->cval = expr1->cval * expr2->cval;
314 break;
315 case EXPR_DIV:
316 if (expr2->cval == 0)
317 {
318 error_loc("divide by zero in expression\n");
319 e->cval = 0;
320 }
321 else
322 e->cval = expr1->cval / expr2->cval;
323 break;
324 case EXPR_OR:
325 e->cval = expr1->cval | expr2->cval;
326 break;
327 case EXPR_AND:
328 e->cval = expr1->cval & expr2->cval;
329 break;
330 case EXPR_SHL:
331 e->cval = expr1->cval << expr2->cval;
332 break;
333 case EXPR_SHR:
334 e->cval = expr1->cval >> expr2->cval;
335 break;
336 case EXPR_LOGOR:
337 e->cval = expr1->cval || expr2->cval;
338 break;
339 case EXPR_LOGAND:
340 e->cval = expr1->cval && expr2->cval;
341 break;
342 case EXPR_XOR:
343 e->cval = expr1->cval ^ expr2->cval;
344 break;
345 case EXPR_EQUALITY:
346 e->cval = expr1->cval == expr2->cval;
347 break;
348 case EXPR_INEQUALITY:
349 e->cval = expr1->cval != expr2->cval;
350 break;
351 case EXPR_GTR:
352 e->cval = expr1->cval > expr2->cval;
353 break;
354 case EXPR_LESS:
355 e->cval = expr1->cval < expr2->cval;
356 break;
357 case EXPR_GTREQL:
358 e->cval = expr1->cval >= expr2->cval;
359 break;
360 case EXPR_LESSEQL:
361 e->cval = expr1->cval <= expr2->cval;
362 break;
363 default:
364 e->is_const = FALSE;
365 break;
366 }
367 }
368 return e;
369}
370
371expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
372{
373 expr_t *e;
374 e = xmalloc(sizeof(expr_t));
375 e->type = type;
376 e->ref = expr1;
377 e->u.ext = expr2;
378 e->ext2 = expr3;
379 e->is_const = FALSE;
380 /* check for compile-time optimization */
381 if (expr1->is_const && expr2->is_const && expr3->is_const)
382 {
383 e->is_const = TRUE;
384 switch (type)
385 {
386 case EXPR_COND:
387 e->cval = expr1->cval ? expr2->cval : expr3->cval;
388 break;
389 default:
390 e->is_const = FALSE;
391 break;
392 }
393 }
394 return e;
395}
396
397struct expression_type
398{
399 int is_variable; /* is the expression resolved to a variable? */
400 int is_temporary; /* should the type be freed? */
401 type_t *type;
402};
403
Rob Shearman80ab2a72008-04-22 11:36:38 +0100404static void check_scalar_type(const struct expr_loc *expr_loc,
405 const type_t *cont_type, const type_t *type)
406{
407 if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
Rob Shearmanba91ee62009-02-23 13:47:57 +0000408 !is_float_type(type)))
Rob Shearman80ab2a72008-04-22 11:36:38 +0100409 error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
410 expr_loc->attr ? " for attribute " : "",
411 expr_loc->attr ? expr_loc->attr : "");
412}
413
414static void check_arithmetic_type(const struct expr_loc *expr_loc,
415 const type_t *cont_type, const type_t *type)
416{
Rob Shearmanba91ee62009-02-23 13:47:57 +0000417 if (!cont_type || (!is_integer_type(type) && !is_float_type(type)))
Rob Shearman80ab2a72008-04-22 11:36:38 +0100418 error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
419 expr_loc->attr ? " for attribute " : "",
420 expr_loc->attr ? expr_loc->attr : "");
421}
422
423static void check_integer_type(const struct expr_loc *expr_loc,
424 const type_t *cont_type, const type_t *type)
425{
426 if (!cont_type || !is_integer_type(type))
427 error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
428 expr_loc->attr ? " for attribute " : "",
429 expr_loc->attr ? expr_loc->attr : "");
430}
431
Rob Shearman1a0d28b2008-04-22 11:37:07 +0100432static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
433{
434 type_t *type = NULL;
435 const var_t *field;
436 const var_list_t *fields = NULL;
437
438 *found_in_cont_type = 0;
439
Rob Shearman04a22cc2008-12-29 12:05:27 +0000440 if (cont_type)
Rob Shearman1a0d28b2008-04-22 11:37:07 +0100441 {
Rob Shearmanba91ee62009-02-23 13:47:57 +0000442 switch (type_get_type(cont_type))
443 {
444 case TYPE_FUNCTION:
Rob Shearman04a22cc2008-12-29 12:05:27 +0000445 fields = type_function_get_args(cont_type);
Rob Shearmanba91ee62009-02-23 13:47:57 +0000446 break;
447 case TYPE_STRUCT:
Rob Shearman04a22cc2008-12-29 12:05:27 +0000448 fields = type_struct_get_fields(cont_type);
Rob Shearmanba91ee62009-02-23 13:47:57 +0000449 break;
450 case TYPE_UNION:
451 case TYPE_ENCAPSULATED_UNION:
Rob Shearman04a22cc2008-12-29 12:05:27 +0000452 fields = type_union_get_cases(cont_type);
Rob Shearmanba91ee62009-02-23 13:47:57 +0000453 break;
454 case TYPE_VOID:
455 case TYPE_BASIC:
456 case TYPE_ENUM:
457 case TYPE_MODULE:
458 case TYPE_COCLASS:
459 case TYPE_INTERFACE:
460 case TYPE_POINTER:
461 case TYPE_ARRAY:
Rob Shearmancdec0fe2009-11-07 15:55:09 +0100462 case TYPE_BITFIELD:
Rob Shearmanba91ee62009-02-23 13:47:57 +0000463 /* nothing to do */
464 break;
465 case TYPE_ALIAS:
466 /* shouldn't get here because of using type_get_type above */
467 assert(0);
468 break;
469 }
Rob Shearman1a0d28b2008-04-22 11:37:07 +0100470 }
471
472 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
473 if (field->name && !strcmp(identifier, field->name))
474 {
475 type = field->type;
476 *found_in_cont_type = 1;
477 break;
478 }
479
480 if (!type)
481 {
482 var_t *const_var = find_const(identifier, 0);
483 if (const_var) type = const_var->type;
484 }
485
486 return type;
487}
488
Rob Shearmanba91ee62009-02-23 13:47:57 +0000489static int is_valid_member_operand(const type_t *type)
490{
491 switch (type_get_type(type))
492 {
493 case TYPE_STRUCT:
494 case TYPE_UNION:
495 case TYPE_ENUM:
496 return TRUE;
497 default:
498 return FALSE;
499 }
500}
501
Rob Shearman80ab2a72008-04-22 11:36:38 +0100502static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
503 const type_t *cont_type,
504 const expr_t *e)
505{
506 struct expression_type result;
507 result.is_variable = FALSE;
508 result.is_temporary = FALSE;
509 result.type = NULL;
510 switch (e->type)
511 {
512 case EXPR_VOID:
513 break;
514 case EXPR_HEXNUM:
515 case EXPR_NUM:
516 case EXPR_TRUEFALSE:
Rob Shearman80ab2a72008-04-22 11:36:38 +0100517 result.is_temporary = FALSE;
Rob Shearman319a7a12009-03-05 08:21:51 +0000518 result.type = type_new_int(TYPE_BASIC_INT, 0);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100519 break;
Rob Shearman33c891e2008-04-25 10:59:21 +0100520 case EXPR_STRLIT:
Rob Shearman33c891e2008-04-25 10:59:21 +0100521 result.is_temporary = TRUE;
Rob Shearman23673ca2009-03-07 23:23:44 +0000522 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL);
Rob Shearman33c891e2008-04-25 10:59:21 +0100523 break;
524 case EXPR_WSTRLIT:
Rob Shearman33c891e2008-04-25 10:59:21 +0100525 result.is_temporary = TRUE;
Rob Shearman23673ca2009-03-07 23:23:44 +0000526 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
Rob Shearman33c891e2008-04-25 10:59:21 +0100527 break;
Rob Shearmand9b83e82010-01-18 22:15:46 +0000528 case EXPR_CHARCONST:
Rob Shearmand9b83e82010-01-18 22:15:46 +0000529 result.is_temporary = TRUE;
530 result.type = type_new_int(TYPE_BASIC_CHAR, 0);
531 break;
Rob Shearman80ab2a72008-04-22 11:36:38 +0100532 case EXPR_DOUBLE:
Rob Shearman319a7a12009-03-05 08:21:51 +0000533 result.is_temporary = TRUE;
534 result.type = type_new_basic(TYPE_BASIC_DOUBLE);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100535 break;
536 case EXPR_IDENTIFIER:
537 {
Rob Shearman1a0d28b2008-04-22 11:37:07 +0100538 int found_in_cont_type;
539 result.is_variable = TRUE;
540 result.is_temporary = FALSE;
541 result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100542 if (!result.type)
543 {
544 error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
545 e->u.sval, expr_loc->attr ? " for attribute " : "",
546 expr_loc->attr ? expr_loc->attr : "");
547 }
548 break;
549 }
550 case EXPR_LOGNOT:
551 result = resolve_expression(expr_loc, cont_type, e->ref);
552 check_scalar_type(expr_loc, cont_type, result.type);
553 result.is_variable = FALSE;
554 result.is_temporary = FALSE;
Rob Shearman319a7a12009-03-05 08:21:51 +0000555 result.type = type_new_int(TYPE_BASIC_INT, 0);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100556 break;
557 case EXPR_NOT:
558 result = resolve_expression(expr_loc, cont_type, e->ref);
559 check_integer_type(expr_loc, cont_type, result.type);
560 result.is_variable = FALSE;
561 break;
562 case EXPR_POS:
563 case EXPR_NEG:
564 result = resolve_expression(expr_loc, cont_type, e->ref);
565 check_arithmetic_type(expr_loc, cont_type, result.type);
566 result.is_variable = FALSE;
567 break;
568 case EXPR_ADDRESSOF:
569 result = resolve_expression(expr_loc, cont_type, e->ref);
570 if (!result.is_variable)
571 error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
572 expr_loc->attr ? " for attribute " : "",
573 expr_loc->attr ? expr_loc->attr : "");
Gerald Pfeifer3a64eb22015-06-30 00:21:08 +0200574 result.is_variable = FALSE;
Rob Shearman80ab2a72008-04-22 11:36:38 +0100575 result.is_temporary = TRUE;
Rob Shearman23673ca2009-03-07 23:23:44 +0000576 result.type = type_new_pointer(RPC_FC_UP, result.type, NULL);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100577 break;
578 case EXPR_PPTR:
579 result = resolve_expression(expr_loc, cont_type, e->ref);
580 if (result.type && is_ptr(result.type))
Rob Shearman67ac03a2009-01-05 23:34:58 +0000581 result.type = type_pointer_get_ref(result.type);
Michael Karcher1c56d292009-01-11 15:00:18 +0100582 else if(result.type && is_array(result.type)
Rob Shearman7e08ff22009-03-05 08:21:35 +0000583 && type_array_is_decl_as_ptr(result.type))
Michael Karcher1c56d292009-01-11 15:00:18 +0100584 result.type = type_array_get_element(result.type);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100585 else
586 error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
587 expr_loc->attr ? " for attribute " : "",
588 expr_loc->attr ? expr_loc->attr : "");
589 break;
590 case EXPR_CAST:
591 result = resolve_expression(expr_loc, cont_type, e->ref);
592 result.type = e->u.tref;
593 break;
594 case EXPR_SIZEOF:
Rob Shearman80ab2a72008-04-22 11:36:38 +0100595 result.is_temporary = FALSE;
Rob Shearman319a7a12009-03-05 08:21:51 +0000596 result.type = type_new_int(TYPE_BASIC_INT, 0);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100597 break;
598 case EXPR_SHL:
599 case EXPR_SHR:
600 case EXPR_MOD:
601 case EXPR_MUL:
602 case EXPR_DIV:
603 case EXPR_ADD:
604 case EXPR_SUB:
605 case EXPR_AND:
606 case EXPR_OR:
607 case EXPR_XOR:
608 {
609 struct expression_type result_right;
610 result = resolve_expression(expr_loc, cont_type, e->ref);
611 result.is_variable = FALSE;
612 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
613 /* FIXME: these checks aren't strict enough for some of the operators */
614 check_scalar_type(expr_loc, cont_type, result.type);
615 check_scalar_type(expr_loc, cont_type, result_right.type);
616 break;
617 }
618 case EXPR_LOGOR:
619 case EXPR_LOGAND:
620 case EXPR_EQUALITY:
621 case EXPR_INEQUALITY:
622 case EXPR_GTR:
623 case EXPR_LESS:
624 case EXPR_GTREQL:
625 case EXPR_LESSEQL:
626 {
627 struct expression_type result_left, result_right;
628 result_left = resolve_expression(expr_loc, cont_type, e->ref);
629 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
630 check_scalar_type(expr_loc, cont_type, result_left.type);
631 check_scalar_type(expr_loc, cont_type, result_right.type);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100632 result.is_temporary = FALSE;
Rob Shearman319a7a12009-03-05 08:21:51 +0000633 result.type = type_new_int(TYPE_BASIC_INT, 0);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100634 break;
635 }
636 case EXPR_MEMBER:
637 result = resolve_expression(expr_loc, cont_type, e->ref);
Rob Shearmanba91ee62009-02-23 13:47:57 +0000638 if (result.type && is_valid_member_operand(result.type))
Rob Shearman80ab2a72008-04-22 11:36:38 +0100639 result = resolve_expression(expr_loc, result.type, e->u.ext);
640 else
641 error_loc_info(&expr_loc->v->loc_info, "'.' or '->' operator applied to a type that isn't a structure, union or enumeration in expression%s%s\n",
642 expr_loc->attr ? " for attribute " : "",
643 expr_loc->attr ? expr_loc->attr : "");
644 break;
645 case EXPR_COND:
646 {
647 struct expression_type result_first, result_second, result_third;
648 result_first = resolve_expression(expr_loc, cont_type, e->ref);
649 check_scalar_type(expr_loc, cont_type, result_first.type);
650 result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
651 result_third = resolve_expression(expr_loc, cont_type, e->ext2);
Alexandre Julliard82f33d32011-07-25 10:43:09 +0200652 check_scalar_type(expr_loc, cont_type, result_second.type);
653 check_scalar_type(expr_loc, cont_type, result_third.type);
654 if (!is_ptr(result_second.type) ^ !is_ptr(result_third.type))
655 error_loc_info(&expr_loc->v->loc_info, "type mismatch in ?: expression\n" );
Rob Shearman80ab2a72008-04-22 11:36:38 +0100656 /* FIXME: determine the correct return type */
657 result = result_second;
658 result.is_variable = FALSE;
659 break;
660 }
661 case EXPR_ARRAY:
662 result = resolve_expression(expr_loc, cont_type, e->ref);
663 if (result.type && is_array(result.type))
664 {
665 struct expression_type index_result;
Rob Shearman2b87d262009-01-05 23:34:52 +0000666 result.type = type_array_get_element(result.type);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100667 index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
668 if (!index_result.type || !is_integer_type(index_result.type))
669 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
670 expr_loc->attr ? " for attribute " : "",
671 expr_loc->attr ? expr_loc->attr : "");
672 }
673 else
674 error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
675 expr_loc->attr ? " for attribute " : "",
676 expr_loc->attr ? expr_loc->attr : "");
677 break;
678 }
679 return result;
680}
681
682const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
683{
684 struct expression_type expr_type;
685 expr_type = resolve_expression(expr_loc, cont_type, expr);
686 return expr_type.type;
687}
688
Rob Shearman1a0d28b2008-04-22 11:37:07 +0100689void write_expr(FILE *h, const expr_t *e, int brackets,
690 int toplevel, const char *toplevel_prefix,
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200691 const type_t *cont_type, const char *local_var_prefix)
Rob Shearman80ab2a72008-04-22 11:36:38 +0100692{
693 switch (e->type)
694 {
695 case EXPR_VOID:
696 break;
697 case EXPR_NUM:
Alexandre Julliarda83563a2010-03-26 11:42:28 +0100698 fprintf(h, "%u", e->u.lval);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100699 break;
700 case EXPR_HEXNUM:
Alexandre Julliarda83563a2010-03-26 11:42:28 +0100701 fprintf(h, "0x%x", e->u.lval);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100702 break;
703 case EXPR_DOUBLE:
704 fprintf(h, "%#.15g", e->u.dval);
705 break;
706 case EXPR_TRUEFALSE:
707 if (e->u.lval == 0)
708 fprintf(h, "FALSE");
709 else
710 fprintf(h, "TRUE");
711 break;
712 case EXPR_IDENTIFIER:
Rob Shearman1a0d28b2008-04-22 11:37:07 +0100713 if (toplevel && toplevel_prefix && cont_type)
714 {
715 int found_in_cont_type;
716 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200717 if (found_in_cont_type)
718 {
719 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
720 break;
721 }
Rob Shearman1a0d28b2008-04-22 11:37:07 +0100722 }
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200723 fprintf(h, "%s%s", local_var_prefix, e->u.sval);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100724 break;
Rob Shearman33c891e2008-04-25 10:59:21 +0100725 case EXPR_STRLIT:
726 fprintf(h, "\"%s\"", e->u.sval);
727 break;
728 case EXPR_WSTRLIT:
729 fprintf(h, "L\"%s\"", e->u.sval);
730 break;
Rob Shearmand9b83e82010-01-18 22:15:46 +0000731 case EXPR_CHARCONST:
732 fprintf(h, "'%s'", e->u.sval);
733 break;
Rob Shearman80ab2a72008-04-22 11:36:38 +0100734 case EXPR_LOGNOT:
735 fprintf(h, "!");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200736 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100737 break;
738 case EXPR_NOT:
739 fprintf(h, "~");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200740 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100741 break;
742 case EXPR_POS:
743 fprintf(h, "+");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200744 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100745 break;
746 case EXPR_NEG:
747 fprintf(h, "-");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200748 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100749 break;
750 case EXPR_ADDRESSOF:
751 fprintf(h, "&");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200752 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100753 break;
754 case EXPR_PPTR:
755 fprintf(h, "*");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200756 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100757 break;
758 case EXPR_CAST:
759 fprintf(h, "(");
760 write_type_decl(h, e->u.tref, NULL);
761 fprintf(h, ")");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200762 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100763 break;
764 case EXPR_SIZEOF:
765 fprintf(h, "sizeof(");
766 write_type_decl(h, e->u.tref, NULL);
767 fprintf(h, ")");
768 break;
769 case EXPR_SHL:
770 case EXPR_SHR:
771 case EXPR_MOD:
772 case EXPR_MUL:
773 case EXPR_DIV:
774 case EXPR_ADD:
775 case EXPR_SUB:
776 case EXPR_AND:
777 case EXPR_OR:
778 case EXPR_LOGOR:
779 case EXPR_LOGAND:
780 case EXPR_XOR:
781 case EXPR_EQUALITY:
782 case EXPR_INEQUALITY:
783 case EXPR_GTR:
784 case EXPR_LESS:
785 case EXPR_GTREQL:
786 case EXPR_LESSEQL:
787 if (brackets) fprintf(h, "(");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200788 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100789 switch (e->type)
790 {
791 case EXPR_SHL: fprintf(h, " << "); break;
792 case EXPR_SHR: fprintf(h, " >> "); break;
793 case EXPR_MOD: fprintf(h, " %% "); break;
794 case EXPR_MUL: fprintf(h, " * "); break;
795 case EXPR_DIV: fprintf(h, " / "); break;
796 case EXPR_ADD: fprintf(h, " + "); break;
797 case EXPR_SUB: fprintf(h, " - "); break;
798 case EXPR_AND: fprintf(h, " & "); break;
799 case EXPR_OR: fprintf(h, " | "); break;
800 case EXPR_LOGOR: fprintf(h, " || "); break;
801 case EXPR_LOGAND: fprintf(h, " && "); break;
802 case EXPR_XOR: fprintf(h, " ^ "); break;
803 case EXPR_EQUALITY: fprintf(h, " == "); break;
804 case EXPR_INEQUALITY: fprintf(h, " != "); break;
805 case EXPR_GTR: fprintf(h, " > "); break;
806 case EXPR_LESS: fprintf(h, " < "); break;
807 case EXPR_GTREQL: fprintf(h, " >= "); break;
808 case EXPR_LESSEQL: fprintf(h, " <= "); break;
809 default: break;
810 }
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200811 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100812 if (brackets) fprintf(h, ")");
813 break;
814 case EXPR_MEMBER:
815 if (brackets) fprintf(h, "(");
816 if (e->ref->type == EXPR_PPTR)
817 {
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200818 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100819 fprintf(h, "->");
820 }
821 else
822 {
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200823 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100824 fprintf(h, ".");
825 }
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200826 write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
Rob Shearman80ab2a72008-04-22 11:36:38 +0100827 if (brackets) fprintf(h, ")");
828 break;
829 case EXPR_COND:
830 if (brackets) fprintf(h, "(");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200831 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100832 fprintf(h, " ? ");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200833 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100834 fprintf(h, " : ");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200835 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100836 if (brackets) fprintf(h, ")");
837 break;
838 case EXPR_ARRAY:
839 if (brackets) fprintf(h, "(");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200840 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100841 fprintf(h, "[");
Alexandre Julliardbf011b02008-09-15 16:46:01 +0200842 write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
Rob Shearman80ab2a72008-04-22 11:36:38 +0100843 fprintf(h, "]");
844 if (brackets) fprintf(h, ")");
845 break;
846 }
847}
848
849/* This is actually fairly involved to implement precisely, due to the
850 effects attributes may have and things like that. Right now this is
851 only used for optimization, so just check for a very small set of
852 criteria that guarantee the types are equivalent; assume every thing
853 else is different. */
854static int compare_type(const type_t *a, const type_t *b)
855{
856 if (a == b
857 || (a->name
858 && b->name
859 && strcmp(a->name, b->name) == 0))
860 return 0;
861 /* Ordering doesn't need to be implemented yet. */
862 return 1;
863}
864
865int compare_expr(const expr_t *a, const expr_t *b)
866{
867 int ret;
868
869 if (a->type != b->type)
870 return a->type - b->type;
871
872 switch (a->type)
873 {
874 case EXPR_NUM:
875 case EXPR_HEXNUM:
876 case EXPR_TRUEFALSE:
877 return a->u.lval - b->u.lval;
878 case EXPR_DOUBLE:
879 return a->u.dval - b->u.dval;
880 case EXPR_IDENTIFIER:
Rob Shearman33c891e2008-04-25 10:59:21 +0100881 case EXPR_STRLIT:
882 case EXPR_WSTRLIT:
Rob Shearmand9b83e82010-01-18 22:15:46 +0000883 case EXPR_CHARCONST:
Rob Shearman80ab2a72008-04-22 11:36:38 +0100884 return strcmp(a->u.sval, b->u.sval);
885 case EXPR_COND:
886 ret = compare_expr(a->ref, b->ref);
887 if (ret != 0)
888 return ret;
889 ret = compare_expr(a->u.ext, b->u.ext);
890 if (ret != 0)
891 return ret;
892 return compare_expr(a->ext2, b->ext2);
893 case EXPR_OR:
894 case EXPR_AND:
895 case EXPR_ADD:
896 case EXPR_SUB:
897 case EXPR_MOD:
898 case EXPR_MUL:
899 case EXPR_DIV:
900 case EXPR_SHL:
901 case EXPR_SHR:
902 case EXPR_MEMBER:
903 case EXPR_ARRAY:
904 case EXPR_LOGOR:
905 case EXPR_LOGAND:
906 case EXPR_XOR:
907 case EXPR_EQUALITY:
908 case EXPR_INEQUALITY:
909 case EXPR_GTR:
910 case EXPR_LESS:
911 case EXPR_GTREQL:
912 case EXPR_LESSEQL:
913 ret = compare_expr(a->ref, b->ref);
914 if (ret != 0)
915 return ret;
916 return compare_expr(a->u.ext, b->u.ext);
917 case EXPR_CAST:
918 ret = compare_type(a->u.tref, b->u.tref);
919 if (ret != 0)
920 return ret;
921 /* Fall through. */
922 case EXPR_NOT:
923 case EXPR_NEG:
924 case EXPR_PPTR:
925 case EXPR_ADDRESSOF:
926 case EXPR_LOGNOT:
927 case EXPR_POS:
928 return compare_expr(a->ref, b->ref);
929 case EXPR_SIZEOF:
930 return compare_type(a->u.tref, b->u.tref);
931 case EXPR_VOID:
932 return 0;
933 }
934 return -1;
935}